diff options
347 files changed, 45839 insertions, 7602 deletions
diff --git a/.gitignore b/.gitignore index 887e45e6a6a..ac67886c51c 100644 --- a/.gitignore +++ b/.gitignore @@ -120,8 +120,8 @@ scripts/mysql_config.pl scripts/mysql_convert_table_format scripts/mysql_find_rows scripts/mysql_fix_extensions -scripts/mysql_fix_privilege_tables.sql -scripts/mysql_fix_privilege_tables_sql.c +scripts/mariadb_fix_privilege_tables.sql +scripts/mariadb_fix_privilege_tables_sql.c scripts/mysql_install_db scripts/mysql_secure_installation scripts/mysql_setpermission diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6c5381428fd..2b9c34e48dc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -289,10 +289,8 @@ centos7: # Install packages so tests and the dependencies install # @TODO: RPM missing 'patch' and 'diff' as dependency, so installing it manually for now - yum install -y rpm/*.rpm patch diffutils - # @TODO: Fix on packaging level for /usr/share/mariadb to work and errormsg.sys be found - - rm -rf /usr/share/mariadb; ln -s /usr/share/mysql /usr/share/mariadb # mtr expects to be launched in-place and with write access to it's own directories - - cd /usr/share/mysql-test + - cd /usr/share/mariadb-test # Skip failing tests - | echo " @@ -508,7 +506,7 @@ mini-benchmark: mariadb --skip-column-names -e "SELECT @@version, @@version_comment" | tee /tmp/version grep $MARIADB_MAJOR_VERSION /tmp/version || echo "MariaDB didn't install properly" - yum install -y sysbench procps-ng perf util-linux || yum install -y https://kojipkgs.fedoraproject.org//packages/luajit/2.0.4/3.el7/x86_64/luajit-2.0.4-3.el7.x86_64.rpm https://kojipkgs.fedoraproject.org//packages/sysbench/1.0.17/2.el7/x86_64/sysbench-1.0.17-2.el7.x86_64.rpm https://kojipkgs.fedoraproject.org//packages/ck/0.5.2/2.el7/x86_64/ck-0.5.2-2.el7.x86_64.rpm - - /usr/share/mysql/mini-benchmark + - /usr/share/mariadb/mini-benchmark - cp -av */sysbench-run-*.log */metrics.txt .. # Move files one level down so they can be saved as artifacts artifacts: when: always @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=11 -MYSQL_VERSION_MINOR=0 -MYSQL_VERSION_PATCH=2 -SERVER_MATURITY=gamma +MYSQL_VERSION_MINOR=1 +MYSQL_VERSION_PATCH=0 +SERVER_MATURITY=beta diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 97401ff1c06..d5c81409eaf 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -18,7 +18,7 @@ #include "client_priv.h" #include <sslopt-vars.h> -#include <../scripts/mysql_fix_privilege_tables_sql.c> +#include <../scripts/mariadb_fix_privilege_tables_sql.c> #define VER "2.0" #include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */ @@ -1333,7 +1333,7 @@ static int run_sql_fix_privilege_tables(void) a forked mysql client, because the script uses session variables and prepared statements. */ - for ( query_ptr= &mysql_fix_privilege_tables[0]; + for ( query_ptr= &mariadb_fix_privilege_tables[0]; *query_ptr != NULL; query_ptr++ ) diff --git a/cmake/create_initial_db.cmake b/cmake/create_initial_db.cmake index ba2b25c0b63..0209d84071e 100644 --- a/cmake/create_initial_db.cmake +++ b/cmake/create_initial_db.cmake @@ -30,7 +30,7 @@ ENDIF() # Create bootstrapper SQL script FILE(WRITE bootstrap.sql "use mysql;\n" ) -FOREACH(FILENAME mysql_system_tables.sql mysql_system_tables_data.sql mysql_performance_tables.sql) +FOREACH(FILENAME mariadb_system_tables.sql mariadb_system_tables_data.sql mariadb_performance_tables.sql) FILE(STRINGS ${TOP_SRCDIR}/scripts/${FILENAME} CONTENTS) FOREACH(STR ${CONTENTS}) IF(NOT STR MATCHES "@current_hostname") @@ -39,7 +39,7 @@ FOREACH(FILENAME mysql_system_tables.sql mysql_system_tables_data.sql mysql_perf ENDFOREACH() ENDFOREACH() -FOREACH(FILENAME ${TOP_SRCDIR}/scripts/fill_help_tables.sql ${TOP_SRCDIR}/scripts/mysql_sys_schema.sql) +FOREACH(FILENAME ${TOP_SRCDIR}/scripts/fill_help_tables.sql ${TOP_SRCDIR}/scripts/mariadb_sys_schema.sql) FILE(READ ${FILENAME} CONTENTS) FILE(APPEND bootstrap.sql "${CONTENTS}") ENDFOREACH() diff --git a/cmake/install_layout.cmake b/cmake/install_layout.cmake index 877b147bc6e..eb969679bf7 100644 --- a/cmake/install_layout.cmake +++ b/cmake/install_layout.cmake @@ -119,7 +119,7 @@ SET(INSTALL_INFODIR_STANDALONE "docs") # SET(INSTALL_SHAREDIR_STANDALONE "share") SET(INSTALL_MYSQLSHAREDIR_STANDALONE "share") -SET(INSTALL_MYSQLTESTDIR_STANDALONE "mysql-test") +SET(INSTALL_MYSQLTESTDIR_STANDALONE "mariadb-test") SET(INSTALL_SQLBENCHDIR_STANDALONE ".") SET(INSTALL_SUPPORTFILESDIR_STANDALONE "support-files") # @@ -152,10 +152,10 @@ SET(INSTALL_INFODIR_RPM "share/info") SET(INSTALL_MANDIR_RPM "share/man") # SET(INSTALL_SHAREDIR_RPM "share") -SET(INSTALL_MYSQLSHAREDIR_RPM "share/mysql") -SET(INSTALL_MYSQLTESTDIR_RPM "share/mysql-test") +SET(INSTALL_MYSQLSHAREDIR_RPM "share/mariadb") +SET(INSTALL_MYSQLTESTDIR_RPM "share/mariadb-test") SET(INSTALL_SQLBENCHDIR_RPM "") -SET(INSTALL_SUPPORTFILESDIR_RPM "share/mysql") +SET(INSTALL_SUPPORTFILESDIR_RPM "share/mariadb") # SET(INSTALL_MYSQLDATADIR_RPM "/var/lib/mysql") @@ -186,10 +186,10 @@ SET(INSTALL_MANDIR_DEB "share/man") SET(INSTALL_INFODIR_DEB "share/info") # SET(INSTALL_SHAREDIR_DEB "share") -SET(INSTALL_MYSQLSHAREDIR_DEB "share/mysql") -SET(INSTALL_MYSQLTESTDIR_DEB "share/mysql/mysql-test") +SET(INSTALL_MYSQLSHAREDIR_DEB "share/mariadb") +SET(INSTALL_MYSQLTESTDIR_DEB "share/mariadb/mariadb-test") SET(INSTALL_SQLBENCHDIR_DEB ".") -SET(INSTALL_SUPPORTFILESDIR_DEB "share/mysql") +SET(INSTALL_SUPPORTFILESDIR_DEB "share/mariadb") # SET(INSTALL_MYSQLDATADIR_DEB "/var/lib/mysql") @@ -219,7 +219,7 @@ SET(INSTALL_INFODIR_SVR4 "docs") # SET(INSTALL_SHAREDIR_SVR4 "share") SET(INSTALL_MYSQLSHAREDIR_SVR4 "share") -SET(INSTALL_MYSQLTESTDIR_SVR4 "mysql-test") +SET(INSTALL_MYSQLTESTDIR_SVR4 "mariadb-test") SET(INSTALL_SQLBENCHDIR_SVR4 ".") SET(INSTALL_SUPPORTFILESDIR_SVR4 "support-files") # diff --git a/debian/additions/debian-start b/debian/additions/debian-start index 2a8b61ddaff..2b897e913cf 100755 --- a/debian/additions/debian-start +++ b/debian/additions/debian-start @@ -6,7 +6,7 @@ # Changes to this file will be preserved when updating the Debian package. # -source /usr/share/mysql/debian-start.inc.sh +source /usr/share/mariadb/debian-start.inc.sh # Read default/mysql first and then default/mariadb just like the init.d file does if [ -f /etc/default/mysql ]; then diff --git a/debian/additions/mariadb.conf.d/50-server.cnf b/debian/additions/mariadb.conf.d/50-server.cnf index 6dcfe16cd55..2d7a176471a 100644 --- a/debian/additions/mariadb.conf.d/50-server.cnf +++ b/debian/additions/mariadb.conf.d/50-server.cnf @@ -108,7 +108,7 @@ collation-server = utf8mb4_general_ci # you can put MariaDB-only options here [mariadbd] -# This group is only read by MariaDB-11.0 servers. +# This group is only read by MariaDB-11.1 servers. # If you use the same .cnf file for MariaDB of different versions, # use this group for options that older servers don't understand -[mariadb-11.0] +[mariadb-11.1] diff --git a/debian/additions/mariadb.conf.d/60-galera.cnf b/debian/additions/mariadb.conf.d/60-galera.cnf index 274891b1313..67ccb3edc0e 100644 --- a/debian/additions/mariadb.conf.d/60-galera.cnf +++ b/debian/additions/mariadb.conf.d/60-galera.cnf @@ -1,7 +1,7 @@ # # * Galera-related settings # -# See the examples of server wsrep.cnf files in /usr/share/mysql +# See the examples of server wsrep.cnf files in /usr/share/mariadb # and read more at https://mariadb.com/kb/en/galera-cluster/ [galera] diff --git a/debian/changelog b/debian/changelog index 60ef886f6dd..1f9f854d829 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -mariadb (1:11.0.0) unstable; urgency=medium +mariadb (1:11.1.0) unstable; urgency=medium * Initial Release diff --git a/debian/mariadb-plugin-mroonga.install b/debian/mariadb-plugin-mroonga.install index fedcf62eef0..a78f1db1550 100644 --- a/debian/mariadb-plugin-mroonga.install +++ b/debian/mariadb-plugin-mroonga.install @@ -1,5 +1,5 @@ usr/lib/mysql/plugin/ha_mroonga.so -usr/share/mysql/mroonga/AUTHORS -usr/share/mysql/mroonga/COPYING -usr/share/mysql/mroonga/install.sql -usr/share/mysql/mroonga/uninstall.sql +usr/share/mariadb/mroonga/AUTHORS +usr/share/mariadb/mroonga/COPYING +usr/share/mariadb/mroonga/install.sql +usr/share/mariadb/mroonga/uninstall.sql diff --git a/debian/mariadb-plugin-mroonga.prerm b/debian/mariadb-plugin-mroonga.prerm index cdd26ebbc45..54cba1e74ff 100644 --- a/debian/mariadb-plugin-mroonga.prerm +++ b/debian/mariadb-plugin-mroonga.prerm @@ -3,7 +3,7 @@ set -e # Uninstall Mroonga -mysql --defaults-file=/etc/mysql/debian.cnf < /usr/share/mysql/mroonga/uninstall.sql || true +mariadb --defaults-file=/etc/mysql/debian.cnf < /usr/share/mariadb/mroonga/uninstall.sql || true # Always exit with success instead of leaving dpkg in a broken state diff --git a/debian/mariadb-server-core.install b/debian/mariadb-server-core.install index d61c42c77c4..b21dcdc4b85 100644 --- a/debian/mariadb-server-core.install +++ b/debian/mariadb-server-core.install @@ -8,39 +8,39 @@ usr/share/man/man1/mariadb-install-db.1 usr/share/man/man1/mariadb-upgrade.1 usr/share/man/man1/resolveip.1 usr/share/man/man8/mariadbd.8 -usr/share/mysql/bulgarian -usr/share/mysql/charsets -usr/share/mysql/chinese -usr/share/mysql/czech -usr/share/mysql/danish -usr/share/mysql/dutch -usr/share/mysql/english -usr/share/mysql/estonian -usr/share/mysql/fill_help_tables.sql -usr/share/mysql/french -usr/share/mysql/german -usr/share/mysql/georgian -usr/share/mysql/greek -usr/share/mysql/hindi -usr/share/mysql/hungarian -usr/share/mysql/italian -usr/share/mysql/japanese -usr/share/mysql/korean -usr/share/mysql/maria_add_gis_sp_bootstrap.sql -usr/share/mysql/mysql_performance_tables.sql -usr/share/mysql/mysql_sys_schema.sql -usr/share/mysql/mysql_system_tables.sql -usr/share/mysql/mysql_system_tables_data.sql -usr/share/mysql/mysql_test_data_timezone.sql -usr/share/mysql/mysql_test_db.sql -usr/share/mysql/norwegian -usr/share/mysql/norwegian-ny -usr/share/mysql/polish -usr/share/mysql/portuguese -usr/share/mysql/romanian -usr/share/mysql/russian -usr/share/mysql/serbian -usr/share/mysql/slovak -usr/share/mysql/spanish -usr/share/mysql/swedish -usr/share/mysql/ukrainian +usr/share/mariadb/bulgarian +usr/share/mariadb/chinese +usr/share/mariadb/charsets +usr/share/mariadb/czech +usr/share/mariadb/danish +usr/share/mariadb/dutch +usr/share/mariadb/english +usr/share/mariadb/estonian +usr/share/mariadb/fill_help_tables.sql +usr/share/mariadb/french +usr/share/mariadb/german +usr/share/mariadb/georgian +usr/share/mariadb/greek +usr/share/mariadb/hindi +usr/share/mariadb/hungarian +usr/share/mariadb/italian +usr/share/mariadb/japanese +usr/share/mariadb/korean +usr/share/mariadb/maria_add_gis_sp_bootstrap.sql +usr/share/mariadb/mariadb_performance_tables.sql +usr/share/mariadb/mariadb_sys_schema.sql +usr/share/mariadb/mariadb_system_tables.sql +usr/share/mariadb/mariadb_system_tables_data.sql +usr/share/mariadb/mariadb_test_data_timezone.sql +usr/share/mariadb/mariadb_test_db.sql +usr/share/mariadb/norwegian +usr/share/mariadb/norwegian-ny +usr/share/mariadb/polish +usr/share/mariadb/portuguese +usr/share/mariadb/romanian +usr/share/mariadb/russian +usr/share/mariadb/serbian +usr/share/mariadb/slovak +usr/share/mariadb/spanish +usr/share/mariadb/swedish +usr/share/mariadb/ukrainian diff --git a/debian/mariadb-server.install b/debian/mariadb-server.install index 4a849bc2a46..55cb9623b3a 100644 --- a/debian/mariadb-server.install +++ b/debian/mariadb-server.install @@ -1,6 +1,6 @@ debian/additions/debian-start etc/mysql -debian/additions/debian-start.inc.sh usr/share/mysql -debian/additions/echo_stderr usr/share/mysql +debian/additions/debian-start.inc.sh usr/share/mariadb +debian/additions/echo_stderr usr/share/mariadb debian/additions/mariadb.conf.d/50-mariadb_safe.cnf etc/mysql/mariadb.conf.d debian/additions/mariadb.conf.d/50-server.cnf etc/mysql/mariadb.conf.d debian/additions/source_mariadb.py usr/share/apport/package-hooks @@ -75,7 +75,7 @@ usr/share/man/man1/wsrep_sst_mariabackup.1 usr/share/man/man1/wsrep_sst_mysqldump.1 usr/share/man/man1/wsrep_sst_rsync.1 usr/share/man/man1/wsrep_sst_rsync_wan.1 -usr/share/mysql/errmsg-utf8.txt -usr/share/mysql/mini-benchmark -usr/share/mysql/wsrep.cnf -usr/share/mysql/wsrep_notify +usr/share/mariadb/errmsg-utf8.txt +usr/share/mariadb/mini-benchmark +usr/share/mariadb/wsrep.cnf +usr/share/mariadb/wsrep_notify diff --git a/debian/mariadb-server.postinst b/debian/mariadb-server.postinst index a5ab6e8e1dc..c256d3d0957 100644 --- a/debian/mariadb-server.postinst +++ b/debian/mariadb-server.postinst @@ -52,7 +52,7 @@ case "$1" in fi fi - mysql_statedir=/usr/share/mysql + mysql_statedir=/usr/share/mariadb mysql_datadir=/var/lib/mysql mysql_logdir=/var/log/mysql mysql_cfgdir=/etc/mysql diff --git a/debian/mariadb-test-data.install b/debian/mariadb-test-data.install index 718fc0e122c..fd40bf77d22 100644 --- a/debian/mariadb-test-data.install +++ b/debian/mariadb-test-data.install @@ -1,6 +1,6 @@ -usr/share/mysql/mysql-test/collections -usr/share/mysql/mysql-test/include -usr/share/mysql/mysql-test/main -usr/share/mysql/mysql-test/plugin -usr/share/mysql/mysql-test/std_data -usr/share/mysql/mysql-test/suite +usr/share/mariadb/mariadb-test/collections +usr/share/mariadb/mariadb-test/include +usr/share/mariadb/mariadb-test/main +usr/share/mariadb/mariadb-test/plugin +usr/share/mariadb/mariadb-test/std_data +usr/share/mariadb/mariadb-test/suite diff --git a/debian/mariadb-test-data.lintian-overrides b/debian/mariadb-test-data.lintian-overrides index b73e31029e6..cb05b748061 100644 --- a/debian/mariadb-test-data.lintian-overrides +++ b/debian/mariadb-test-data.lintian-overrides @@ -1,32 +1,32 @@ # These should be moved, see https://jira.mariadb.org/browse/MDEV-21654 -arch-dependent-file-in-usr-share [usr/share/mysql/mysql-test/suite/plugins/pam/pam_mariadb_mtr.so] -arch-independent-package-contains-binary-or-object [usr/share/mysql/mysql-test/suite/plugins/pam/pam_mariadb_mtr.so] +arch-dependent-file-in-usr-share [usr/share/mariadb/mariadb-test/suite/plugins/pam/pam_mariadb_mtr.so] +arch-independent-package-contains-binary-or-object [usr/share/mariadb/mariadb-test/suite/plugins/pam/pam_mariadb_mtr.so] # Mainly for support for *BSD family. Not right way to do but this is test package and not for production -incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/std_data/checkDBI_DBD-MariaDB.pl] -incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/suite/engines/rr_trx/run_stress_tx_rr.pl] -incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/suite/funcs_1/lib/DataGen_local.pl] -incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/suite/funcs_1/lib/DataGen_modify.pl] -incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/suite/funcs_2/lib/gen_charset_utf8.pl] -incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/suite/rpl/extension/checksum.pl] +incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mariadb/mariadb-test/std_data/checkDBI_DBD-MariaDB.pl] +incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mariadb/mariadb-test/suite/engines/rr_trx/run_stress_tx_rr.pl] +incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mariadb/mariadb-test/suite/funcs_1/lib/DataGen_local.pl] +incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mariadb/mariadb-test/suite/funcs_1/lib/DataGen_modify.pl] +incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mariadb/mariadb-test/suite/funcs_2/lib/gen_charset_utf8.pl] +incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mariadb/mariadb-test/suite/rpl/extension/checksum.pl] # Intentional for test files -national-encoding usr/share/mysql/mysql-test/* +national-encoding usr/share/mariadb/mariadb-test/* # Extra test documentation files that really need to be kept in context in test directory -package-contains-documentation-outside-usr-share-doc usr/share/mysql/mysql-test/* +package-contains-documentation-outside-usr-share-doc usr/share/mariadb/mariadb-test/* # Intentional directory structure -repeated-path-segment auth_gssapi usr/share/mysql/mysql-test/plugin/auth_gssapi/auth_gssapi/ -repeated-path-segment connect usr/share/mysql/mysql-test/plugin/connect/connect/ -repeated-path-segment disks usr/share/mysql/mysql-test/plugin/disks/disks/ -repeated-path-segment func_test usr/share/mysql/mysql-test/plugin/func_test/func_test/ -repeated-path-segment metadata_lock_info usr/share/mysql/mysql-test/plugin/metadata_lock_info/metadata_lock_info/ -repeated-path-segment mroonga usr/share/mysql/mysql-test/plugin/mroonga/mroonga/ -repeated-path-segment mroonga usr/share/mysql/mysql-test/plugin/mroonga/mroonga/include/mroonga/ -repeated-path-segment oqgraph usr/share/mysql/mysql-test/plugin/oqgraph/oqgraph/ -repeated-path-segment query_response_time usr/share/mysql/mysql-test/plugin/query_response_time/query_response_time/ -repeated-path-segment rocksdb usr/share/mysql/mysql-test/plugin/rocksdb/rocksdb/ -repeated-path-segment sequence usr/share/mysql/mysql-test/plugin/sequence/sequence/ -repeated-path-segment sphinx usr/share/mysql/mysql-test/plugin/sphinx/sphinx/ -repeated-path-segment spider usr/share/mysql/mysql-test/plugin/spider/spider/ -repeated-path-segment type_inet usr/share/mysql/mysql-test/plugin/type_inet/type_inet/ -repeated-path-segment type_test usr/share/mysql/mysql-test/plugin/type_test/type_test/ -repeated-path-segment user_variables usr/share/mysql/mysql-test/plugin/user_variables/user_variables/ -repeated-path-segment wsrep_info usr/share/mysql/mysql-test/plugin/wsrep_info/wsrep_info/ +repeated-path-segment auth_gssapi usr/share/mariadb/mariadb-test/plugin/auth_gssapi/auth_gssapi/ +repeated-path-segment connect usr/share/mariadb/mariadb-test/plugin/connect/connect/ +repeated-path-segment disks usr/share/mariadb/mariadb-test/plugin/disks/disks/ +repeated-path-segment func_test usr/share/mariadb/mariadb-test/plugin/func_test/func_test/ +repeated-path-segment metadata_lock_info usr/share/mariadb/mariadb-test/plugin/metadata_lock_info/metadata_lock_info/ +repeated-path-segment mroonga usr/share/mariadb/mariadb-test/plugin/mroonga/mroonga/ +repeated-path-segment mroonga usr/share/mariadb/mariadb-test/plugin/mroonga/mroonga/include/mroonga/ +repeated-path-segment oqgraph usr/share/mariadb/mariadb-test/plugin/oqgraph/oqgraph/ +repeated-path-segment query_response_time usr/share/mariadb/mariadb-test/plugin/query_response_time/query_response_time/ +repeated-path-segment rocksdb usr/share/mariadb/mariadb-test/plugin/rocksdb/rocksdb/ +repeated-path-segment sequence usr/share/mariadb/mariadb-test/plugin/sequence/sequence/ +repeated-path-segment sphinx usr/share/mariadb/mariadb-test/plugin/sphinx/sphinx/ +repeated-path-segment spider usr/share/mariadb/mariadb-test/plugin/spider/spider/ +repeated-path-segment type_inet usr/share/mariadb/mariadb-test/plugin/type_inet/type_inet/ +repeated-path-segment type_test usr/share/mariadb/mariadb-test/plugin/type_test/type_test/ +repeated-path-segment user_variables usr/share/mariadb/mariadb-test/plugin/user_variables/user_variables/ +repeated-path-segment wsrep_info usr/share/mariadb/mariadb-test/plugin/wsrep_info/wsrep_info/ diff --git a/debian/mariadb-test.install b/debian/mariadb-test.install index 5dda38d665c..c4a58246820 100644 --- a/debian/mariadb-test.install +++ b/debian/mariadb-test.install @@ -35,17 +35,17 @@ usr/share/man/man1/mysql_client_test.1 usr/share/man/man1/mysql_client_test_embedded.1 usr/share/man/man1/mysqltest.1 usr/share/man/man1/mysqltest_embedded.1 -usr/share/mysql/mysql-test/README -usr/share/mysql/mysql-test/README-gcov -usr/share/mysql/mysql-test/README.stress -usr/share/mysql/mysql-test/dgcov.pl -usr/share/mysql/mysql-test/lib -usr/share/mysql/mysql-test/mariadb-stress-test.pl -usr/share/mysql/mysql-test/mariadb-test-run -usr/share/mysql/mysql-test/mariadb-test-run.pl -usr/share/mysql/mysql-test/mtr -usr/share/mysql/mysql-test/mysql-test-run -usr/share/mysql/mysql-test/mysql-test-run.pl -usr/share/mysql/mysql-test/purify.supp -usr/share/mysql/mysql-test/suite.pm -usr/share/mysql/mysql-test/valgrind.supp +usr/share/mariadb/mariadb-test/README +usr/share/mariadb/mariadb-test/README-gcov +usr/share/mariadb/mariadb-test/README.stress +usr/share/mariadb/mariadb-test/dgcov.pl +usr/share/mariadb/mariadb-test/lib +usr/share/mariadb/mariadb-test/mariadb-stress-test.pl +usr/share/mariadb/mariadb-test/mariadb-test-run +usr/share/mariadb/mariadb-test/mariadb-test-run.pl +usr/share/mariadb/mariadb-test/mtr +usr/share/mariadb/mariadb-test/mysql-test-run +usr/share/mariadb/mariadb-test/mysql-test-run.pl +usr/share/mariadb/mariadb-test/purify.supp +usr/share/mariadb/mariadb-test/suite.pm +usr/share/mariadb/mariadb-test/valgrind.supp diff --git a/debian/mariadb-test.lintian-overrides b/debian/mariadb-test.lintian-overrides index d09cfe3c537..6e7bdf05e39 100644 --- a/debian/mariadb-test.lintian-overrides +++ b/debian/mariadb-test.lintian-overrides @@ -1,8 +1,8 @@ # These should be moved, see https://jira.mariadb.org/browse/MDEV-21653 -arch-dependent-file-in-usr-share [usr/share/mysql/mysql-test/lib/My/SafeProcess/my_safe_process] -arch-dependent-file-in-usr-share [usr/share/mysql/mysql-test/lib/My/SafeProcess/wsrep_check_version] +arch-dependent-file-in-usr-share [usr/share/mariadb/mariadb-test/lib/My/SafeProcess/my_safe_process] +arch-dependent-file-in-usr-share [usr/share/mariadb/mariadb-test/lib/My/SafeProcess/wsrep_check_version] # Mainly for support for *BSD family. Not right way to do but this is test package and not for production -incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/lib/process-purecov-annotations.pl] -incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/lib/v1/mysql-test-run.pl] -incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/mysql-stress-test.pl] -incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/mysql-test-run.pl] +incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mariadb/mariadb-test/lib/process-purecov-annotations.pl] +incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mariadb/mariadb-test/lib/v1/mysql-test-run.pl] +incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mariadb/mariadb-test/mariadb-stress-test.pl] +incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mariadb/mariadb-test/mariadb-test-run.pl] diff --git a/debian/not-installed b/debian/not-installed index c0d08565616..1cbeeade721 100644 --- a/debian/not-installed +++ b/debian/not-installed @@ -29,7 +29,7 @@ usr/lib/mysql/plugin/type_test.so 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/mysql/mroonga/COPYING") +usr/share/doc/mariadb-server/COPYING (related file: "debian/tmp/usr/share/mariadb/mroonga/COPYING") usr/share/doc/mariadb-server/CREDITS usr/share/doc/mariadb-server/INSTALL-BINARY usr/share/doc/mariadb-server/README-wsrep @@ -44,30 +44,30 @@ usr/share/man/man1/mysql_embedded.1 # Symlink to mariadb-embedded.1 which is int usr/share/man/man1/my_safe_process.1 usr/share/man/man1/mysql-stress-test.pl.1 usr/share/man/man1/mysql.server.1 -usr/share/mysql/JavaWrappers.jar -usr/share/mysql/JdbcInterface.jar -usr/share/mysql/Mongo2.jar -usr/share/mysql/Mongo3.jar -usr/share/mysql/binary-configure -usr/share/mysql/magic -usr/share/mysql/mariadb.logrotate -usr/share/mysql/maria_add_gis_sp.sql # mariadb-server-core.install has *_bootstrap.sql -usr/share/mysql/mysql-test/asan.supp -usr/share/mysql/mysql-test/lsan.supp -usr/share/mysql/mysql-test/unstable-tests -usr/share/mysql/mysql.server # Debian packaging uses mariadb-server.mariadb.init -usr/share/mysql/mysqld_multi.server -usr/share/mysql/policy/apparmor/README # In MariaDB we don't want to use AppArmor at the moment -usr/share/mysql/policy/apparmor/usr.sbin.mysqld # In MariaDB we don't want to use AppArmor at the moment -usr/share/mysql/policy/apparmor/usr.sbin.mysqld.local # In MariaDB we don't want to use AppArmor at the moment -usr/share/mysql/policy/selinux/README # In MariaDB we don't want to use SELinux at the moment -usr/share/mysql/policy/selinux/mariadb-server.fc # In MariaDB we don't want to use SELinux at the moment -usr/share/mysql/policy/selinux/mariadb-server.te # In MariaDB we don't want to use SELinux at the moment -usr/share/mysql/policy/selinux/mariadb.te # In MariaDB we don't want to use SELinux at the moment -usr/share/mysql/systemd/mariadb-extra@.socket # Installed by rules file -usr/share/mysql/systemd/mariadb.service # Installed by rules file -usr/share/mysql/systemd/mariadb@.service # Installed by rules file -usr/share/mysql/systemd/mariadb@.socket # Installed by rules file -usr/share/mysql/systemd/mysql.service # Installed by rules file -usr/share/mysql/systemd/mysqld.service # Installed by rules file -usr/share/mysql/systemd/use_galera_new_cluster.conf +usr/share/mariadb/JavaWrappers.jar +usr/share/mariadb/JdbcInterface.jar +usr/share/mariadb/Mongo2.jar +usr/share/mariadb/Mongo3.jar +usr/share/mariadb/binary-configure +usr/share/mariadb/magic +usr/share/mariadb/mariadb.logrotate +usr/share/mariadb/maria_add_gis_sp.sql # mariadb-server-core.install has *_bootstrap.sql +usr/share/mariadb/mariadb-test/asan.supp +usr/share/mariadb/mariadb-test/lsan.supp +usr/share/mariadb/mariadb-test/unstable-tests +usr/share/mariadb/mysql.server # Debian packaging uses mariadb-server.mariadb.init +usr/share/mariadb/mysqld_multi.server +usr/share/mariadb/policy/apparmor/README # In MariaDB we don't want to use AppArmor at the moment +usr/share/mariadb/policy/apparmor/usr.sbin.mysqld # In MariaDB we don't want to use AppArmor at the moment +usr/share/mariadb/policy/apparmor/usr.sbin.mysqld.local # In MariaDB we don't want to use AppArmor at the moment +usr/share/mariadb/policy/selinux/README # In MariaDB we don't want to use SELinux at the moment +usr/share/mariadb/policy/selinux/mariadb-server.fc # In MariaDB we don't want to use SELinux at the moment +usr/share/mariadb/policy/selinux/mariadb-server.te # In MariaDB we don't want to use SELinux at the moment +usr/share/mariadb/policy/selinux/mariadb.te # In MariaDB we don't want to use SELinux at the moment +usr/share/mariadb/systemd/mariadb-extra@.socket # Installed by rules file +usr/share/mariadb/systemd/mariadb.service # Installed by rules file +usr/share/mariadb/systemd/mariadb@.service # Installed by rules file +usr/share/mariadb/systemd/mariadb@.socket # Installed by rules file +usr/share/mariadb/systemd/mysql.service # Installed by rules file +usr/share/mariadb/systemd/mysqld.service # Installed by rules file +usr/share/mariadb/systemd/use_galera_new_cluster.conf diff --git a/debian/rules b/debian/rules index 95ab0844a24..08ca3b8f96e 100755 --- a/debian/rules +++ b/debian/rules @@ -159,7 +159,7 @@ endif cd $(BUILDDIR) && $(MAKE) install DESTDIR=$(TMP) > /dev/null # 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/mysql/mysql-test + 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 diff --git a/debian/salsa-ci.yml b/debian/salsa-ci.yml index a5c0ec3ee9c..15626d2afbc 100644 --- a/debian/salsa-ci.yml +++ b/debian/salsa-ci.yml @@ -360,7 +360,7 @@ test basic features: password=asdf234 protocol=tcp EOF - export CERT_PATH=/usr/share/mysql/mysql-test/std_data + export CERT_PATH=/usr/share/mariadb/mariadb-test/std_data openssl verify -CAfile $CERT_PATH/cacert.pem $CERT_PATH/server-cert.pem openssl x509 -subject -issuer -noout -in $CERT_PATH/cacert.pem openssl x509 -subject -issuer -noout -in $CERT_PATH/server-cert.pem diff --git a/debian/source/lintian-overrides b/debian/source/lintian-overrides index 7686591f0a8..fc7a8780651 100644 --- a/debian/source/lintian-overrides +++ b/debian/source/lintian-overrides @@ -50,8 +50,8 @@ very-long-line-length-in-source-file plugin/handler_socket/regtest/test_01_lib/t # SQL source file that has very long inserts/selects very-long-line-length-in-source-file mysql-test/std_data/init_file_longline_3816.sql * very-long-line-length-in-source-file scripts/fill_help_tables.sql * -very-long-line-length-in-source-file scripts/mysql_system_tables.sql * -very-long-line-length-in-source-file scripts/mysql_test_data_timezone.sql * +very-long-line-length-in-source-file scripts/mariadb_system_tables.sql * +very-long-line-length-in-source-file scripts/mariadb_test_data_timezone.sql * # Machine formatted HTML very-long-line-length-in-source-file sql/share/charsets/languages.html * very-long-line-length-in-source-file sql/share/errmsg-utf8.txt * diff --git a/debian/tests/upstream b/debian/tests/upstream index c48701864b7..dc55c74ad97 100644 --- a/debian/tests/upstream +++ b/debian/tests/upstream @@ -26,12 +26,12 @@ echo "Setting up skip-tests-list" # Use unstable-tests list as base to skip all tests considered unstable # or create an empty file if that upstream file does not exists on this branch -cp /usr/share/mysql/mysql-test/unstable-tests $SKIP_TEST_LST || touch $SKIP_TEST_LST +cp /usr/share/mariadb/mariadb-test/unstable-tests $SKIP_TEST_LST || touch $SKIP_TEST_LST # Also use the arch specific skiplists if exist -if [ -f /usr/share/mysql/mysql-test/unstable-tests.$ARCH ] +if [ -f /usr/share/mariadb/mariadb-test/unstable-tests.$ARCH ] then - cat /usr/share/mysql/mysql-test/unstable-tests.$ARCH >> $SKIP_TEST_LST + cat /usr/share/mariadb/mariadb-test/unstable-tests.$ARCH >> $SKIP_TEST_LST fi # Skip tests that cannot run properly on ci.debian.net / autopkgtests.ubuntu.com @@ -61,9 +61,9 @@ fi # failed autopkgtest runs cp -v $SKIP_TEST_LST $AUTOPKGTEST_ARTIFACTS -cd /usr/share/mysql/mysql-test -echo "starting mysql-test-tun.pl..." -eatmydata perl -I. ./mysql-test-run.pl --suite=main \ +cd /usr/share/mariadb/mariadb-test +echo "starting mariadb-test-run.pl..." +eatmydata perl -I. ./mariadb-test-run.pl --suite=main \ --vardir="$WORKDIR/var" --tmpdir="$WORKDIR/tmp" \ --parallel=auto --skip-rpl \ --force --skip-test-list=$SKIP_TEST_LST \ diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc index dbf12cedd68..1827601dae0 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -1560,7 +1560,7 @@ bool backup_finish(ds_ctxt *ds_data) return(false); } - if (!write_xtrabackup_info(ds_data, mysql_connection, XTRABACKUP_INFO, + if (!write_xtrabackup_info(ds_data, mysql_connection, MB_INFO, opt_history != 0, true)) { return(false); } @@ -1616,10 +1616,14 @@ ibx_copy_incremental_over_full() const char *ext_list[] = {"frm", "isl", "MYD", "MYI", "MAD", "MAI", "MRG", "TRG", "TRN", "ARM", "ARZ", "CSM", "CSV", "opt", "par", NULL}; - const char *sup_files[] = {"xtrabackup_binlog_info", - "xtrabackup_galera_info", - "xtrabackup_slave_info", - "xtrabackup_info", + const char *sup_files[] = {MB_BINLOG_INFO, + MB_GALERA_INFO, + MB_SLAVE_INFO, + MB_INFO, + XTRABACKUP_BINLOG_INFO, + XTRABACKUP_GALERA_INFO, + XTRABACKUP_SLAVE_INFO, + XTRABACKUP_INFO, "ib_lru_dump", NULL}; datadir_iter_t *it = NULL; @@ -1958,8 +1962,12 @@ copy_back() while (datadir_iter_next(it, &node)) { const char *ext_list[] = {"backup-my.cnf", - "xtrabackup_binary", "xtrabackup_binlog_info", - "xtrabackup_checkpoints", ".qp", ".pmap", ".tmp", + "xtrabackup_binary", + MB_BINLOG_INFO, + MB_METADATA_FILENAME, + XTRABACKUP_BINLOG_INFO, + XTRABACKUP_METADATA_FILENAME, + ".qp", ".pmap", ".tmp", NULL}; const char *filename; char c_tmp; diff --git a/extra/mariabackup/backup_copy.h b/extra/mariabackup/backup_copy.h index b4a323f2e89..973863625c6 100644 --- a/extra/mariabackup/backup_copy.h +++ b/extra/mariabackup/backup_copy.h @@ -6,11 +6,19 @@ #include <mysql.h> #include "datasink.h" -/* special files */ +/* special files, backward compatibility */ #define XTRABACKUP_SLAVE_INFO "xtrabackup_slave_info" #define XTRABACKUP_GALERA_INFO "xtrabackup_galera_info" #define XTRABACKUP_BINLOG_INFO "xtrabackup_binlog_info" #define XTRABACKUP_INFO "xtrabackup_info" +#define XTRABACKUP_METADATA_FILENAME "xtrabackup_checkpoints" + +/* special files */ +#define MB_SLAVE_INFO "mariadb_backup_slave_info" +#define MB_GALERA_INFO "mariadb_backup_galera_info" +#define MB_BINLOG_INFO "mariadb_backup_binlog_info" +#define MB_INFO "mariadb_backup_info" +#define MB_METADATA_FILENAME "mariadb_backup_checkpoints" extern bool binlog_locked; diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc index cf8a50517a8..a3b65df998d 100644 --- a/extra/mariabackup/backup_mysql.cc +++ b/extra/mariabackup/backup_mysql.cc @@ -1347,7 +1347,7 @@ write_slave_info(ds_ctxt *datasink, MYSQL *connection) } mysql_slave_position= strdup(comment.c_ptr()); - return datasink->backup_file_print_buf(XTRABACKUP_SLAVE_INFO, + return datasink->backup_file_print_buf(MB_SLAVE_INFO, sql.ptr(), sql.length()); } @@ -1371,7 +1371,7 @@ write_galera_info(ds_ctxt *datasink, MYSQL *connection) }; /* When backup locks are supported by the server, we should skip - creating xtrabackup_galera_info file on the backup stage, because + creating MB_GALERA_INFO file on the backup stage, because wsrep_local_state_uuid and wsrep_last_committed will be inconsistent without blocking commits. The state file will be created on the prepare stage using the WSREP recovery procedure. */ @@ -1388,7 +1388,7 @@ write_galera_info(ds_ctxt *datasink, MYSQL *connection) goto cleanup; } - result = datasink->backup_file_printf(XTRABACKUP_GALERA_INFO, + result = datasink->backup_file_printf(MB_GALERA_INFO, "%s:%s\n", state_uuid ? state_uuid : state_uuid55, last_committed ? last_committed : last_committed55); if (result) @@ -1522,7 +1522,7 @@ write_binlog_info(ds_ctxt *datasink, MYSQL *connection) read_mysql_variables(connection, "SHOW VARIABLES", vars, true); if (filename == NULL || position == NULL) { - /* Do not create xtrabackup_binlog_info if binary + /* Do not create MB_BINLOG_INFO if binary log is disabled */ result = true; goto cleanup; @@ -1538,14 +1538,14 @@ write_binlog_info(ds_ctxt *datasink, MYSQL *connection) "filename '%s', position '%s', " "GTID of the last change '%s'", filename, position, gtid) != -1); - result = datasink->backup_file_printf(XTRABACKUP_BINLOG_INFO, + result = datasink->backup_file_printf(MB_BINLOG_INFO, "%s\t%s\t%s\n", filename, position, gtid); } else { ut_a(asprintf(&mysql_binlog_position, "filename '%s', position '%s'", filename, position) != -1); - result = datasink->backup_file_printf(XTRABACKUP_BINLOG_INFO, + result = datasink->backup_file_printf(MB_BINLOG_INFO, "%s\t%s\n", filename, position); } @@ -1580,7 +1580,7 @@ operator<<(std::ostream& s, const escape_and_quote& eq) } /*********************************************************************//** -Writes xtrabackup_info file and if backup_history is enable creates +Writes MB_INFO file and if backup_history is enable creates mysql.mariabackup_history and writes a new history record to the table containing all the history info particular to the just completed backup. */ @@ -1657,7 +1657,7 @@ write_xtrabackup_info(ds_ctxt *datasink, xb_stream_name[xtrabackup_stream_fmt], /* format */ xtrabackup_compress ? "compressed" : "N"); /* compressed */ if (buf_len < 0) { - msg("Error: cannot generate xtrabackup_info"); + msg("Error: cannot generate " MB_INFO); result = false; goto cleanup; } diff --git a/extra/mariabackup/backup_wsrep.h b/extra/mariabackup/backup_wsrep.h index 50a8a3a53e7..d992d925722 100644 --- a/extra/mariabackup/backup_wsrep.h +++ b/extra/mariabackup/backup_wsrep.h @@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA #define BACKUP_WSREP_H /*********************************************************************** -Store Galera checkpoint info in the 'xtrabackup_galera_info' file, if that +Store Galera checkpoint info in the MB_GALERA_INFO file, if that information is present in the trx system header. Otherwise, do nothing. */ void xb_write_galera_info(bool incremental_prepare); diff --git a/extra/mariabackup/innobackupex.cc b/extra/mariabackup/innobackupex.cc index b925b41552d..6c9a837b761 100644 --- a/extra/mariabackup/innobackupex.cc +++ b/extra/mariabackup/innobackupex.cc @@ -242,7 +242,7 @@ static struct my_option ibx_long_options[] = GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"galera-info", OPT_GALERA_INFO, "This options creates the " - "xtrabackup_galera_info file which contains the local node state at " + MB_GALERA_INFO " file which contains the local node state at " "the time of the backup. Option should be used when performing the " "backup of MariaDB Galera Cluster. Has no effect when backup locks " "are used to create the backup.", @@ -252,10 +252,10 @@ static struct my_option ibx_long_options[] = {"slave-info", OPT_SLAVE_INFO, "This option is useful when backing " "up a replication slave server. It prints the binary log position " "and name of the master server. It also writes this information to " - "the \"xtrabackup_slave_info\" file as a \"CHANGE MASTER\" command. " + "the \"" MB_SLAVE_INFO "\" file as a \"CHANGE MASTER\" command. " "A new slave for this master can be set up by starting a slave server " "on this backup and issuing a \"CHANGE MASTER\" command with the " - "binary log position saved in the \"xtrabackup_slave_info\" file.", + "binary log position saved in the \"" MB_SLAVE_INFO "\" file.", (uchar *) &opt_ibx_slave_info, (uchar *) &opt_ibx_slave_info, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -518,7 +518,7 @@ static struct my_option ibx_long_options[] = {"extra-lsndir", OPT_EXTRA_LSNDIR, "This option specifies the " "directory in which to save an extra copy of the " - "\"xtrabackup_checkpoints\" file. The option accepts a string " + "\"" MB_METADATA_FILENAME "\" file. The option accepts a string " "argument.", (uchar*) &ibx_xtrabackup_extra_lsndir, (uchar*) &ibx_xtrabackup_extra_lsndir, diff --git a/extra/mariabackup/wsrep.cc b/extra/mariabackup/wsrep.cc index 1b93e9ed10e..45d44fb1fbb 100644 --- a/extra/mariabackup/wsrep.cc +++ b/extra/mariabackup/wsrep.cc @@ -53,9 +53,10 @@ permission notice: /*! Name of file where Galera info is stored on recovery */ #define XB_GALERA_INFO_FILENAME "xtrabackup_galera_info" +#define MB_GALERA_INFO_FILENAME "mariadb_backup_galera_info" /*********************************************************************** -Store Galera checkpoint info in the 'xtrabackup_galera_info' file, if that +Store Galera checkpoint info in the MB_GALERA_INFO_FILENAME file, if that information is present in the trx system header. Otherwise, do nothing. */ void xb_write_galera_info(bool incremental_prepare) @@ -70,7 +71,8 @@ xb_write_galera_info(bool incremental_prepare) /* Do not overwrite existing an existing file to be compatible with servers with older server versions */ if (!incremental_prepare && - my_stat(XB_GALERA_INFO_FILENAME, &statinfo, MYF(0)) != NULL) { + (my_stat(XB_GALERA_INFO_FILENAME, &statinfo, MYF(0)) != NULL || + my_stat(MB_GALERA_INFO_FILENAME, &statinfo, MYF(0)) != NULL)) { return; } @@ -89,11 +91,11 @@ xb_write_galera_info(bool incremental_prepare) return; } - fp = fopen(XB_GALERA_INFO_FILENAME, "w"); + fp = fopen(MB_GALERA_INFO_FILENAME, "w"); if (fp == NULL) { die( - "could not create " XB_GALERA_INFO_FILENAME + "could not create " MB_GALERA_INFO_FILENAME ", errno = %d\n", errno); exit(EXIT_FAILURE); @@ -107,7 +109,7 @@ xb_write_galera_info(bool incremental_prepare) if (fprintf(fp, "%s:%lld", uuid_str, (long long) seqno) < 0) { die( - "could not write to " XB_GALERA_INFO_FILENAME + "could not write to " MB_GALERA_INFO_FILENAME ", errno = %d\n", errno);; } diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 1ca4c5fad7e..9b1d335aaef 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -126,7 +126,7 @@ int sd_notifyf() { return 0; } int sys_var_init(); /* === xtrabackup specific options === */ -char xtrabackup_real_target_dir[FN_REFLEN] = "./xtrabackup_backupfiles/"; +char xtrabackup_real_target_dir[FN_REFLEN] = "./mariadb_backup_files/"; char *xtrabackup_target_dir= xtrabackup_real_target_dir; static my_bool xtrabackup_version; static my_bool verbose; @@ -223,7 +223,6 @@ my_bool opt_extended_validation; my_bool opt_encrypted_backup; /* === metadata of backup === */ -#define XTRABACKUP_METADATA_FILENAME "xtrabackup_checkpoints" char metadata_type[30] = ""; /*[full-backuped|log-applied|incremental]*/ static lsn_t metadata_from_lsn; lsn_t metadata_to_lsn; @@ -1183,8 +1182,8 @@ struct my_option xb_client_options[]= { (G_PTR *) &xtrabackup_log_copy_interval, 0, GET_LONG, REQUIRED_ARG, 1000, 0, LONG_MAX, 0, 1, 0}, {"extra-lsndir", OPT_XTRA_EXTRA_LSNDIR, - "(for --backup): save an extra copy of the xtrabackup_checkpoints file " - "in this directory.", + "(for --backup): save an extra copy of the " MB_METADATA_FILENAME + " file in this directory.", (G_PTR *) &xtrabackup_extra_lsndir, (G_PTR *) &xtrabackup_extra_lsndir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"incremental-lsn", OPT_XTRA_INCREMENTAL, @@ -1298,7 +1297,7 @@ struct my_option xb_client_options[]= { {"galera-info", OPT_GALERA_INFO, "This options creates the " - "xtrabackup_galera_info file which contains the local node state at " + MB_GALERA_INFO " file which contains the local node state at " "the time of the backup. Option should be used when performing the " "backup of MariaDB Galera Cluster. Has no effect when backup locks " "are used to create the backup.", @@ -1309,10 +1308,10 @@ struct my_option xb_client_options[]= { "This option is useful when backing " "up a replication slave server. It prints the binary log position " "and name of the master server. It also writes this information to " - "the \"xtrabackup_slave_info\" file as a \"CHANGE MASTER\" command. " + "the \"" MB_SLAVE_INFO "\" file as a \"CHANGE MASTER\" command. " "A new slave for this master can be set up by starting a slave server " "on this backup and issuing a \"CHANGE MASTER\" command with the " - "binary log position saved in the \"xtrabackup_slave_info\" file.", + "binary log position saved in the \"" MB_SLAVE_INFO "\" file.", (uchar *) &opt_slave_info, (uchar *) &opt_slave_info, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -2457,6 +2456,37 @@ end: return(r); } + +/* +Read backup meta info. +@return TRUE on success, FALSE on failure. */ +static +my_bool +mb_read_metadata(const char *dir, const char *name) +{ + char filename[FN_REFLEN]; + snprintf(filename, sizeof(filename), "%s/%s", dir, name); + if (!xtrabackup_read_metadata(filename)) { + msg("mariabackup: error: failed to read metadata from " + "%s", filename); + return false; + } + return true; +} + + +/* +Read backup meta info from the given directory +with backward compatibility. */ +static +my_bool +mb_read_metadata_from_dir(const char *dir) +{ + return mb_read_metadata(dir, MB_METADATA_FILENAME) || + mb_read_metadata(dir, XTRABACKUP_METADATA_FILENAME); +} + + /*********************************************************************** Print backup meta info to a specified buffer. */ static @@ -2496,9 +2526,12 @@ xtrabackup_stream_metadata(ds_ctxt_t *ds_ctxt) mystat.st_size = len; mystat.st_mtime = my_time(0); - stream = ds_open(ds_ctxt, XTRABACKUP_METADATA_FILENAME, &mystat); + stream = ds_open(ds_ctxt, MB_METADATA_FILENAME, &mystat); + if (stream == NULL) { + stream = ds_open(ds_ctxt, XTRABACKUP_METADATA_FILENAME, &mystat); + } if (stream == NULL) { - msg("Error: cannot open output stream for %s", XTRABACKUP_METADATA_FILENAME); + msg("Error: cannot open output stream for %s", MB_METADATA_FILENAME); return(FALSE); } @@ -4523,14 +4556,14 @@ bool Backup_datasinks::backup_low() char filename[FN_REFLEN]; sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, - XTRABACKUP_METADATA_FILENAME); + MB_METADATA_FILENAME); if (!xtrabackup_write_metadata(filename)) { msg("Error: failed to write metadata " "to '%s'.", filename); return false; } sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, - XTRABACKUP_INFO); + MB_INFO); if (!write_xtrabackup_info(m_data, mysql_connection, filename, false, false)) { msg("Error: failed to write info " @@ -5908,7 +5941,6 @@ static ibool prepare_handle_del_files(const char *datadir, const char *db, const static bool xtrabackup_prepare_func(char** argv) { CorruptedPages corrupted_pages; - char metadata_path[FN_REFLEN]; /* cd to target-dir */ @@ -5959,12 +5991,7 @@ static bool xtrabackup_prepare_func(char** argv) /* read metadata of target */ - sprintf(metadata_path, "%s/%s", xtrabackup_target_dir, - XTRABACKUP_METADATA_FILENAME); - - if (!xtrabackup_read_metadata(metadata_path)) { - msg("Error: failed to read metadata from '%s'\n", - metadata_path); + if (!mb_read_metadata_from_dir(xtrabackup_target_dir)) { return(false); } @@ -6123,14 +6150,14 @@ error: metadata_last_lsn = incremental_last_lsn; } - sprintf(filename, "%s/%s", xtrabackup_target_dir, XTRABACKUP_METADATA_FILENAME); + sprintf(filename, "%s/%s", xtrabackup_target_dir, MB_METADATA_FILENAME); if (!xtrabackup_write_metadata(filename)) { msg("mariabackup: Error: failed to write metadata " "to '%s'", filename); ok = false; } else if (xtrabackup_extra_lsndir) { - sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, XTRABACKUP_METADATA_FILENAME); + sprintf(filename, "%s/%s", xtrabackup_extra_lsndir, MB_METADATA_FILENAME); if (!xtrabackup_write_metadata(filename)) { msg("mariabackup: Error: failed to write " "metadata to '%s'", filename); @@ -6888,26 +6915,14 @@ static int main_low(char** argv) return(EXIT_FAILURE); } } else if (xtrabackup_backup && xtrabackup_incremental_basedir) { - char filename[FN_REFLEN]; - - sprintf(filename, "%s/%s", xtrabackup_incremental_basedir, XTRABACKUP_METADATA_FILENAME); - - if (!xtrabackup_read_metadata(filename)) { - msg("mariabackup: error: failed to read metadata from " - "%s", filename); + if (!mb_read_metadata_from_dir(xtrabackup_incremental_basedir)) { return(EXIT_FAILURE); } incremental_lsn = metadata_to_lsn; xtrabackup_incremental = xtrabackup_incremental_basedir; //dummy } else if (xtrabackup_prepare && xtrabackup_incremental_dir) { - char filename[FN_REFLEN]; - - sprintf(filename, "%s/%s", xtrabackup_incremental_dir, XTRABACKUP_METADATA_FILENAME); - - if (!xtrabackup_read_metadata(filename)) { - msg("mariabackup: error: failed to read metadata from " - "%s", filename); + if (!mb_read_metadata_from_dir(xtrabackup_incremental_dir)) { return(EXIT_FAILURE); } diff --git a/include/json_lib.h b/include/json_lib.h index f7231b07636..61091448632 100644 --- a/include/json_lib.h +++ b/include/json_lib.h @@ -443,6 +443,11 @@ int json_normalize(DYNAMIC_STRING *result, int json_skip_array_and_count(json_engine_t *j, int* n_item); +inline static int json_scan_ended(json_engine_t *j) +{ + return (j->state == JST_ARRAY_END && j->stack_p == 0); +} + #ifdef __cplusplus } #endif diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index 5d5cc35e1be..52126f6b796 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -65,10 +65,13 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.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_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_event.cc ../sql/log_event_server.cc ../sql/mf_iocache.cc ../sql/my_decimal.cc - ../sql/net_serv.cc ../sql/opt_range.cc ../sql/opt_sum.cc + ../sql/net_serv.cc ../sql/opt_range.cc + ../sql/opt_rewrite_date_cmp.cc + ../sql/opt_sum.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 diff --git a/man/mariadbd-multi.1 b/man/mariadbd-multi.1 index e195eb59e2e..76d1c97d206 100644 --- a/man/mariadbd-multi.1 +++ b/man/mariadbd-multi.1 @@ -579,8 +579,8 @@ script\&. Check especially the lines: MY_PWD=`pwd` # Check if we are starting this relative (for the binary release) if test \-d $MY_PWD/data/mysql \-a \e - \-f \&./share/mysql/english/errmsg\&.sys \-a \e - \-x \&./bin/mysqld + \-f \&./share/mariadb/english/errmsg\&.sys \-a \e + \-x \&./bin/mariadbd \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- .fi .if n \{\ @@ -637,28 +637,28 @@ socket = /tmp/mysql\&.sock2 port = 3307 pid\-file = /usr/local/mysql/var2/hostname\&.pid2 datadir = /usr/local/mysql/var2 -language = /usr/local/share/mysql/english +language = /usr/local/share/mariadb/english user = john [mysqld3] socket = /tmp/mysql\&.sock3 port = 3308 pid\-file = /usr/local/mysql/var3/hostname\&.pid3 datadir = /usr/local/mysql/var3 -language = /usr/local/share/mysql/swedish +language = /usr/local/share/mariadb/swedish user = monty [mysqld4] socket = /tmp/mysql\&.sock4 port = 3309 pid\-file = /usr/local/mysql/var4/hostname\&.pid4 datadir = /usr/local/mysql/var4 -language = /usr/local/share/mysql/estonia +language = /usr/local/share/mariadb/estonia user = tonu [mysqld6] socket = /tmp/mysql\&.sock6 port = 3311 pid\-file = /usr/local/mysql/var6/hostname\&.pid6 datadir = /usr/local/mysql/var6 -language = /usr/local/share/mysql/japanese +language = /usr/local/share/mariadb/japanese user = jani .fi .if n \{\ diff --git a/mysql-test/README b/mysql-test/README index ae1d6d56433..b2f9979458e 100644 --- a/mysql-test/README +++ b/mysql-test/README @@ -12,18 +12,18 @@ To run the tests in a source directory, you must do "make" first. In Red Hat distributions, you should run the script as user "mysql". The user is created with nologin shell, so the best bet is something like # su - - # cd /usr/share/mysql-test + # cd /usr/share/mariadb-test # su -s /bin/bash mysql -c ./mysql-test-run This will use the installed MariaDB executables, but will run a private -copy of the server process (using data files within /usr/share/mysql-test), +copy of the server process (using data files within /usr/share/mariadb-test), so you need not start the mysqld service beforehand. You can omit --skip-test-list option if you want to check whether the listed failures occur for you. To clean up afterwards, remove the created "var" subdirectory, e.g. - # su -s /bin/bash - mysql -c "rm -rf /usr/share/mysql-test/var" + # su -s /bin/bash - mysql -c "rm -rf /usr/share/mariadb-test/var" If tests fail on your system, please read the following manual section for instructions on how to report the problem: @@ -37,7 +37,7 @@ you are expected to provide names of the tests to run. For example, here is the command to run the "alias" and "analyze" tests with an external server: - # mysql-test-run --extern socket=/tmp/mysql.sock alias analyze + # mariadb-test-run --extern socket=/tmp/mysql.sock alias analyze To match your setup, you might need to provide other relevant options. @@ -63,20 +63,20 @@ and over again. If you are using mysqltest commands in your test case, you should create the result file as follows: - # mysql-test-run --record test_case_name + # mariadb-test-run --record test_case_name or - # mysqltest --record < t/test_case_name.test + # mariadb-test --record < t/test_case_name.test If you only have a simple test case consisting of SQL statements and comments, you can create the result file in one of the following ways: - # mysql-test-run --record test_case_name + # mariadb-test-run --record test_case_name - # mysql test < t/test_case_name.test > r/test_case_name.result + # mariadb test < t/test_case_name.test > r/test_case_name.result - # mysqltest --record --database test --result-file=r/test_case_name.result < t/test_case_name.test + # mariadb-test --record --database test --result-file=r/test_case_name.result < t/test_case_name.test When this is done, take a look at r/test_case_name.result. If the result is incorrect, you have found a bug. In this case, you should diff --git a/mysql-test/README.stress b/mysql-test/README.stress index 6be4e9a0236..696f28c15b1 100644 --- a/mysql-test/README.stress +++ b/mysql-test/README.stress @@ -6,13 +6,12 @@ The stress script is designed to perform testing of the MySQL server in a multi-threaded environment. All functionality regarding stress testing is implemented in the -mysql-stress-test.pl script. +mariadb-stress-test.pl script. The stress script allows: - - To stress test the mysqltest binary test engine. - - To stress test the regular test suite and any additional test suites - (such as mysql-test-extra-5.0). + - To stress test the mariadb-test binary test engine. + - To stress test the regular test suite. - To specify files with lists of tests both for initialization of stress db and for further testing itself. - To define the number of threads to be concurrently used in testing. @@ -22,14 +21,14 @@ The stress script allows: - To get a readable log file that can be used for identification of errors that occur during testing. -There are two ways to run the mysql-stress-test.pl script: +There are two ways to run the mariadb-stress-test.pl script: - For most cases, it is enough to use the options below for starting - the stress test from the mysql-test-run wrapper. In this case, the + the stress test from the mariadb-test-run wrapper. In this case, the server is run automatically, all preparation steps are performed, and after that the stress test is started. - - In advanced case, you can run the mysql-stress-test.pl script directly. + - In advanced case, you can run the mariadb-stress-test.pl script directly. But this requires that you perform some preparation steps and to specify a bunch of options as well, so this invocation method may be a bit complicated. @@ -87,21 +86,21 @@ Examples 1. Example of a simple command line to start a stress test: - mysql-test-run --stress alias + mariadb-test-run --stress alias Runs a stress test with default values for number of threads and number of tests, with test 'alias' from suite 'main'. 2. Using in stress testing tests from other suites: - - mysql-test-run --stress --stress-threads=10 --stress-test-count=1000 \ + - mariadb-test-run --stress --stress-threads=10 --stress-test-count=1000 \ --stress-suite=example --stress-tests-file=testslist.txt Runs a stress test with 10 threads, executes 1000 tests by all threads, tests are used from suite 'example', the list of tests is taken from file 'testslist.txt' - - mysql-test-run --stress --stress-threads=10 --stress-test-count=1000 \ + - mariadb-test-run --stress --stress-threads=10 --stress-test-count=1000 \ --stress-suite=example sum_distinct Runs stress test with 10 threads, executes 1000 tests by all @@ -110,11 +109,11 @@ of tests, with test 'alias' from suite 'main'. 3. Debugging of issues found with stress test - Right now, the stress test is not fully integrated in mysql-test-run + Right now, the stress test is not fully integrated in mariadb-test-run and does not support the --gdb option. To debug issues found with the - stress test, you must start the MySQL server separately under a debugger + stress test, you must start the MariaDB server separately under a debugger and then run the stress test like this: - - mysql-test-run --extern --stress --stress-threads=10 \ + - mariadb-test-run --extern --stress --stress-threads=10 \ --stress-test-count=1000 --stress-suite=example \ sum_distinct diff --git a/mysql-test/collections/smoke_test b/mysql-test/collections/smoke_test index deaf38beb33..6a949f037e9 100644 --- a/mysql-test/collections/smoke_test +++ b/mysql-test/collections/smoke_test @@ -30,7 +30,6 @@ handler.interface heap.heap innodb.innodb innodb.autoinc_persist -innodb.innodb_defrag_binlog innodb.innodb_mysql innodb.monitor innodb.purge diff --git a/mysql-test/include/concurrent.inc b/mysql-test/include/concurrent.inc index 1d65549f8f4..f9058c069ca 100644 --- a/mysql-test/include/concurrent.inc +++ b/mysql-test/include/concurrent.inc @@ -30,7 +30,7 @@ SET SQL_MODE=""; # # Show prerequisites for this test. # -SELECT @@global.tx_isolation; +SELECT @@global.transaction_isolation; # # With the transaction isolation level REPEATABLE READ (the default) # or SERIALIZEBLE, InnoDB takes "next-key locks"/"gap locks". This means it @@ -43,7 +43,7 @@ SELECT @@global.tx_isolation; # We use the variable $keep_locks to set the expectations for # lock wait timeouts accordingly. # -let $keep_locks= `SELECT @@global.tx_isolation IN ('REPEATABLE-READ','SERIALIZABLE')`; +let $keep_locks= `SELECT @@global.transaction_isolation IN ('REPEATABLE-READ','SERIALIZABLE')`; --echo # keep_locks == $keep_locks # diff --git a/mysql-test/include/delete_use_source.inc b/mysql-test/include/delete_use_source.inc new file mode 100644 index 00000000000..3f789767142 --- /dev/null +++ b/mysql-test/include/delete_use_source.inc @@ -0,0 +1,94 @@ +create table t1 (c1 integer, c2 integer, c3 integer); + +insert into t1(c1,c2,c3) + values (1,1,1),(1,2,2),(1,3,3), + (2,1,4),(2,2,5),(2,3,6), + (2,4,7),(2,5,8); +insert into t1 select c1+10,c2,c3+10 from t1; +insert into t1 select c1+20,c2+1,c3+20 from t1; +analyze table t1 persistent for all; + +create view v1 as select * from t1 where c2=2; + +--echo ####################################### +--echo # Test without any index # +--echo ####################################### +--source include/delete_use_source_cases.inc +--source include/delete_use_source_cases_non_innodb.inc + +--echo ####################################### +--echo # Test with an index # +--echo ####################################### +create index t1_c2 on t1 (c2,c1); +--source include/delete_use_source_cases.inc +--source include/delete_use_source_cases_non_innodb.inc + +--echo ####################################### +--echo # Test with a primary key # +--echo ####################################### +drop index t1_c2 on t1; +alter table t1 add primary key (c3); +--source include/delete_use_source_cases.inc +--source include/delete_use_source_cases_non_innodb.inc + +drop view v1; +drop table t1; + +--echo # +--echo # Test on dynamic columns (blob) +--echo # +create table assets ( + item_name varchar(32) primary key, -- A common attribute for all items + dynamic_cols blob -- Dynamic columns will be stored here +); + +INSERT INTO assets + VALUES ('MariaDB T-shirt', + COLUMN_CREATE('color', 'blue', 'size', 'XL')); +INSERT INTO assets + VALUES ('Thinkpad Laptop', + COLUMN_CREATE('color', 'black', 'price', 500)); +INSERT INTO assets + VALUES ('Fridge', + COLUMN_CREATE('color', 'white', 'warranty', '5 years')); +INSERT INTO assets + VALUES ('Microwave', + COLUMN_CREATE('warranty', '3 years')); +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color + FROM assets ORDER BY item_name; +UPDATE assets SET dynamic_cols=COLUMN_DELETE(dynamic_cols, 'color') + WHERE item_name='Fridge'; +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color + FROM assets ORDER BY item_name; +DELETE FROM assets + WHERE item_name in + (select b.item_name from assets b + where COLUMN_GET(b.dynamic_cols, 'color' as char) ='black'); +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color + FROM assets ORDER BY item_name; +DELETE FROM assets WHERE item_name='Microwave'; +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color + FROM assets ORDER BY item_name; +drop table assets ; + + +--echo # +--echo # Test on fulltext columns +--echo # +CREATE TABLE ft2(copy TEXT,FULLTEXT(copy)); +INSERT INTO ft2(copy) VALUES + ('MySQL vs MariaDB database'), + ('Oracle vs MariaDB database'), + ('PostgreSQL vs MariaDB database'), + ('MariaDB overview'), + ('Foreign keys'), + ('Primary keys'), + ('Indexes'), + ('Transactions'), + ('Triggers'); + +SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('database'); +DELETE FROM ft2 WHERE MATCH(copy) AGAINST('database'); +SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('database'); +drop table ft2; + diff --git a/mysql-test/include/delete_use_source_cases.inc b/mysql-test/include/delete_use_source_cases.inc new file mode 100644 index 00000000000..24408b7dd50 --- /dev/null +++ b/mysql-test/include/delete_use_source_cases.inc @@ -0,0 +1,214 @@ +--echo # +--echo # Delete with value from subquery on the same table +--echo # + +analyze table t1 persistent for all; + +let $c = c1=(select a.c3 from t1 a where a.c3 = t1.c3); +eval create table tmp as select * from t1 where $c; +let $q = delete from t1 where $c; +eval explain select * from t1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete with EXISTS subquery over the updated table +--echo # in WHERE + possibly sargable condition +--echo # + +analyze table t1 persistent for all; + +let $c = c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +eval create table tmp as select * from t1 where $c; +let $q = delete from t1 where $c; +eval explain select * from t1 where $c; +eval explain $q; +eval analyze $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete with IN predicand over the updated table in WHERE +--echo # +let $c = c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +eval create table tmp as select * from t1 where $c; +let $q = delete from t1 where $c; +eval explain select * from t1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete with a limit - can be deleted +--echo # +let $c = c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +eval create table tmp as select * from t1 where $c; +let $q = delete from t1 where $c; +eval explain select * from t1 where $c; +eval explain $q; +eval analyze $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete with a limit and an order by +--echo # + +let $c = c1 in (select a.c2 from t1 a where a.c3 = t1.c3) + order by c3 desc limit 1; +eval create table tmp as select * from t1 where $c; +let $q = delete from t1 where $c; +eval explain select * from t1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete: 2 execution of PS +--echo # + +prepare create_tmp_stmt from + "create table tmp as select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +prepare delete_t1_stmt from + "delete from t1 where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=5; +execute create_tmp_stmt using @a; +execute delete_t1_stmt using @a; +execute delete_t1_stmt using @a; +--sorted_result +select * from t1; + +prepare insert_tmp_stmt from + "insert into tmp(c1,c2,c3) select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=2; +execute insert_tmp_stmt using @a; +execute delete_t1_stmt using @a; +--sorted_result +select * from t1; + +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +--sorted_result +select * from t1; + +drop table tmp; + +--echo # +--echo # Delete in stored procedure +--echo # + +delimiter //; +create procedure sp() +begin + delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) + order by c3 desc limit 1; +end +// +delimiter ;// + +create table tmp as select * from t1 + where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) + order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 + where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) + order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 + where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) + order by c3 desc limit 1; +CALL sp; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop procedure sp; +drop table tmp; + +--echo # +--echo # Delete in stored function +--echo # +delimiter //; +create function f1(IN a INT) returns int +begin + delete from t1 where c3 < a order by c3 limit 1; + return 1; +end;// +delimiter ;// + +set @a:=7; +create table tmp as select * from t1 where c3 < @a + order by c3 limit 1; +select f1(@a); +insert into tmp(c1,c2,c3) select * from t1 where c3 < @a + order by c3 limit 1; +select f1(@a); +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop function f1; +drop table tmp; + +--echo # +--echo # Delete in trigger +--echo # + +create table t2 (c1 integer); +insert into t2(c1) values (1), (2), (3), (4), (5), (6), (7), (8); + +CREATE TABLE cnt(del integer); +INSERT INTO cnt VALUES(0); + +CREATE TRIGGER tr1 AFTER DELETE ON t1 FOR EACH ROW + UPDATE cnt SET del=del+1; +CREATE TRIGGER tr2 AFTER DELETE ON t1 FOR EACH ROW + DELETE FROM t2 WHERE c1> (SELECT count(*)-1 FROM t2); + +CREATE TABLE tmp as SELECT * FROM t1 WHERE c2>=3; +--enable_info ONCE +DELETE FROM t1 WHERE c2>=3; + +--sorted_result +select * from t1; +--sorted_result +SELECT * FROM t2; +SELECT * FROM cnt; + +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; + +DROP TRIGGER tr1; +DROP TRIGGER tr2; +drop table t2, cnt, tmp; + +--echo # +--echo # Delete with a reference to view in subquery +--echo # +let $c = t1.c2 in ( select max(a.c2) from v1 a + where a.c1 = t1.c1); +eval create table tmp as select * from t1 where $c; +let $q = delete from t1 where $c; +eval explain select * from t1 where $c; +eval explain $q; +eval analyze $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + diff --git a/mysql-test/include/delete_use_source_cases_memory.inc b/mysql-test/include/delete_use_source_cases_memory.inc new file mode 100644 index 00000000000..7a61b59e2a5 --- /dev/null +++ b/mysql-test/include/delete_use_source_cases_memory.inc @@ -0,0 +1,294 @@ +--echo # +--echo # Delete with value from subquery on the same table +--echo # + +analyze table t1 persistent for all; + +let $c = c1=(select a.c3 from t1 a where a.c3 = t1.c3); +eval create table tmp as select * from t1 where $c; +let $q = delete from t1 where $c; +eval explain select * from t1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete with EXISTS subquery over the updated table +--echo # in WHERE + possibly sargable condition +--echo # + +analyze table t1 persistent for all; + +let $c = c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +eval create table tmp as select * from t1 where $c; +let $q = delete from t1 where $c; +eval explain select * from t1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete with EXISTS subquery over the updated table +--echo # in WHERE + non-sargable condition +--echo # + +analyze table t1 persistent for all; + +let $c = exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +eval create table tmp as select * from t1 where $c; +let $q = delete from t1 where $c; +eval explain select * from t1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete with order by +--echo # + +analyze table t1 persistent for all; + +let $c = exists (select 'X' from t1 a where a.c2 = t1.c2) + and c2 >= 3 order by c2; +eval create table tmp as select * from t1 where $c; +let $q = delete from t1 where $c; +eval explain select * from t1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete with IN predicand over the updated table in WHERE +--echo # +let $c = c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +eval create table tmp as select * from t1 where $c; +let $q = delete from t1 where $c; +eval explain select * from t1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete with a limit - can be deleted +--echo # +let $c = c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +eval create table tmp as select * from t1 where $c; +let $q = delete from t1 where $c; +eval explain select * from t1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete with a limit and an order by +--echo # + +let $c = c1 in (select a.c2 from t1 a where a.c3 = t1.c3) + order by c3 desc limit 1; +eval create table tmp as select * from t1 where $c; +let $q = delete from t1 where $c; +eval explain select * from t1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete: 2 execution of PS +--echo # + +prepare create_tmp_stmt from + "create table tmp as select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +prepare delete_t1_stmt from + "delete from t1 where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=5; +execute create_tmp_stmt using @a; +execute delete_t1_stmt using @a; +execute delete_t1_stmt using @a; +--sorted_result +select * from t1; + +prepare insert_tmp_stmt from + "insert into tmp(c1,c2,c3) select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=2; +execute insert_tmp_stmt using @a; +execute delete_t1_stmt using @a; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +--sorted_result +select * from t1; + +drop table tmp; + +--echo # +--echo # Delete in stored procedure +--echo # + +delimiter //; +create procedure sp() +begin + delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) + order by c3 desc limit 1; +end +// +delimiter ;// + +create table tmp as select * from t1 + where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) + order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 + where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) + order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 + where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) + order by c3 desc limit 1; +CALL sp; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop procedure sp; +drop table tmp; + +--echo # +--echo # Delete in stored function +--echo # +delimiter //; +create function f1(IN a INT) returns int +begin + delete from t1 where c3 < a order by c3 limit 1; + return 1; +end;// +delimiter ;// + +set @a:=7; +create table tmp as select * from t1 where c3 < @a + order by c3 limit 1; +select f1(@a); +insert into tmp(c1,c2,c3) select * from t1 where c3 < @a + order by c3 limit 1; +select f1(@a); +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop function f1; +drop table tmp; + +--echo # +--echo # Delete in trigger +--echo # + +create table t2 (c1 integer); +insert into t2(c1) values (1), (2), (3), (4), (5), (6), (7), (8); + +CREATE TABLE cnt(del integer); +INSERT INTO cnt VALUES(0); + +CREATE TRIGGER tr1 AFTER DELETE ON t1 FOR EACH ROW + UPDATE cnt SET del=del+1; +CREATE TRIGGER tr2 AFTER DELETE ON t1 FOR EACH ROW + DELETE FROM t2 WHERE c1> (SELECT count(*)-1 FROM t2); + +CREATE TABLE tmp as SELECT * FROM t1 WHERE c2>=3; +--enable_info ONCE +DELETE FROM t1 WHERE c2>=3; + +--sorted_result +select * from t1; +--sorted_result +SELECT * FROM t2; +SELECT * FROM cnt; + +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; + +DROP TRIGGER tr1; +DROP TRIGGER tr2; +drop table t2, cnt, tmp; + +--echo # +--echo Delete with a reference to view in subquery +--echo # +let $c = t1.c2 in ( select max(a.c2) from v1 a + where a.c1 = t1.c1); +eval create table tmp as select * from t1 where $c; +let $q = delete from t1 where $c; +eval explain select * from t1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete from view +--echo # + +analyze table t1 persistent for all; + +let $c = v1.c1 in + (select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +eval create table tmp as select * from v1 where $c; +let $q = delete from v1 where $c; +eval explain select * from v1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete from view using reference +--echo # to the same view in subquery +--echo # + +analyze table t1 persistent for all; + +let $c = v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) + and c1 = 2 + and exists (select 'X' from v1 a where a.c1 = v1.c1); +eval create table tmp as select * from v1 where $c; +let $q = delete from v1 where $c; +eval explain select * from v1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + diff --git a/mysql-test/include/delete_use_source_cases_non_innodb.inc b/mysql-test/include/delete_use_source_cases_non_innodb.inc new file mode 100644 index 00000000000..caa581716dc --- /dev/null +++ b/mysql-test/include/delete_use_source_cases_non_innodb.inc @@ -0,0 +1,81 @@ +--echo # +--echo # Delete with EXISTS subquery over the updated table +--echo # in WHERE + non-sargable condition +--echo # + +analyze table t1 persistent for all; + +let $c = exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +eval create table tmp as select * from t1 where $c; +let $q = delete from t1 where $c; +eval explain select * from t1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete with order by +--echo # + +analyze table t1 persistent for all; + +let $c = exists (select 'X' from t1 a where a.c2 = t1.c2) + and c2 >= 3 order by c2; +eval create table tmp as select * from t1 where $c; +let $q = delete from t1 where $c; +--replace_column 9 # +eval explain select * from t1 where $c; +--replace_column 9 # +eval explain $q; +--replace_column 9 # +eval analyze $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete from view +--echo # + +analyze table t1 persistent for all; + +let $c = v1.c1 in + (select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +eval create table tmp as select * from v1 where $c; +let $q = delete from v1 where $c; +eval explain select * from v1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; + +--echo # +--echo # Delete from view using reference +--echo # to the same view in subquery +--echo # + +analyze table t1 persistent for all; + +let $c = v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) + and c1 = 2 + and exists (select 'X' from v1 a where a.c1 = v1.c1); +eval create table tmp as select * from v1 where $c; +let $q = delete from v1 where $c; +--replace_column 9 # +eval explain select * from v1 where $c; +--replace_column 9 # +eval explain $q; +--replace_column 9 # +eval analyze $q; +--sorted_result +select * from t1; +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; diff --git a/mysql-test/include/delete_use_source_innodb.inc b/mysql-test/include/delete_use_source_innodb.inc new file mode 100644 index 00000000000..83915d47656 --- /dev/null +++ b/mysql-test/include/delete_use_source_innodb.inc @@ -0,0 +1,91 @@ +create table t1 (c1 integer, c2 integer, c3 integer); + +insert into t1(c1,c2,c3) + values (1,1,1),(1,2,2),(1,3,3), + (2,1,4),(2,2,5),(2,3,6), + (2,4,7),(2,5,8); +insert into t1 select c1+10,c2,c3+10 from t1; +insert into t1 select c1+20,c2+1,c3+20 from t1; +analyze table t1 persistent for all; + +create view v1 as select * from t1 where c2=2; + +--echo ####################################### +--echo # Test without any index # +--echo ####################################### +--source include/delete_use_source_cases.inc + +--echo ####################################### +--echo # Test with an index # +--echo ####################################### +create index t1_c2 on t1 (c2,c1); +--source include/delete_use_source_cases.inc + +--echo ####################################### +--echo # Test with a primary key # +--echo ####################################### +drop index t1_c2 on t1; +alter table t1 add primary key (c3); +--source include/delete_use_source_cases.inc + +drop view v1; +drop table t1; + +--echo # +--echo # Test on dynamic columns (blob) +--echo # +create table assets ( + item_name varchar(32) primary key, -- A common attribute for all items + dynamic_cols blob -- Dynamic columns will be stored here +); + +INSERT INTO assets + VALUES ('MariaDB T-shirt', + COLUMN_CREATE('color', 'blue', 'size', 'XL')); +INSERT INTO assets + VALUES ('Thinkpad Laptop', + COLUMN_CREATE('color', 'black', 'price', 500)); +INSERT INTO assets + VALUES ('Fridge', + COLUMN_CREATE('color', 'white', 'warranty', '5 years')); +INSERT INTO assets + VALUES ('Microwave', + COLUMN_CREATE('warranty', '3 years')); +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color + FROM assets ORDER BY item_name; +UPDATE assets SET dynamic_cols=COLUMN_DELETE(dynamic_cols, 'color') + WHERE item_name='Fridge'; +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color + FROM assets ORDER BY item_name; +DELETE FROM assets + WHERE item_name in + (select b.item_name from assets b + where COLUMN_GET(b.dynamic_cols, 'color' as char) ='black'); +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color + FROM assets ORDER BY item_name; +DELETE FROM assets WHERE item_name='Microwave'; +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color + FROM assets ORDER BY item_name; +drop table assets ; + + +--echo # +--echo # Test on fulltext columns +--echo # +CREATE TABLE ft2(copy TEXT,FULLTEXT(copy)); +INSERT INTO ft2(copy) VALUES + ('MySQL vs MariaDB database'), + ('Oracle vs MariaDB database'), + ('PostgreSQL vs MariaDB database'), + ('MariaDB overview'), + ('Foreign keys'), + ('Primary keys'), + ('Indexes'), + ('Transactions'), + ('Triggers'); + +SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('database'); +DELETE FROM ft2 WHERE MATCH(copy) AGAINST('database'); +SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('database'); +drop table ft2; + diff --git a/mysql-test/include/delete_use_source_memory.inc b/mysql-test/include/delete_use_source_memory.inc new file mode 100644 index 00000000000..dbaae1a6120 --- /dev/null +++ b/mysql-test/include/delete_use_source_memory.inc @@ -0,0 +1,33 @@ +create table t1 (c1 integer, c2 integer, c3 integer); + +insert into t1(c1,c2,c3) + values (1,1,1),(1,2,2),(1,3,3), + (2,1,4),(2,2,5),(2,3,6), + (2,4,7),(2,5,8); +insert into t1 select c1+10,c2,c3+10 from t1; +insert into t1 select c1+20,c2+1,c3+20 from t1; +analyze table t1 persistent for all; + +create view v1 as select * from t1 where c2=2; + +--echo ####################################### +--echo # Test without any index # +--echo ####################################### +--source include/delete_use_source_cases_memory.inc + +--echo ####################################### +--echo # Test with an index # +--echo ####################################### +create index t1_c2 on t1 (c2,c1); +--source include/delete_use_source_cases_memory.inc + +--echo ####################################### +--echo # Test with a primary key # +--echo ####################################### +drop index t1_c2 on t1; +alter table t1 add primary key (c3); +--source include/delete_use_source_cases_memory.inc + +drop view v1; +drop table t1; + diff --git a/mysql-test/include/mix2.inc b/mysql-test/include/mix2.inc index 6a6fbcbc2ae..5ea4b79531c 100644 --- a/mysql-test/include/mix2.inc +++ b/mysql-test/include/mix2.inc @@ -776,7 +776,7 @@ eval create table t1 (id int unsigned not null auto_increment, code tinyint unsi BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; -SELECT @@tx_isolation,@@global.tx_isolation; +SELECT @@transaction_isolation,@@global.transaction_isolation; insert into t1 (code, name) values (1, 'Tim'), (1, 'Monty'), (2, 'David'); select id, code, name from t1 order by id; COMMIT; diff --git a/mysql-test/include/update_use_source.inc b/mysql-test/include/update_use_source.inc index 3c487704233..e1b66d2b996 100644 --- a/mysql-test/include/update_use_source.inc +++ b/mysql-test/include/update_use_source.inc @@ -1,150 +1,188 @@ # Include to test update with same table as source and target ---echo # ---echo # Update a with value from subquery on the same table, no search clause. ALL access ---echo # - -#Enable view protocol after fix MDEV-29207 ---disable_view_protocol -start transaction; +create table t1 (old_c1 integer, + old_c2 integer, + c1 integer, + c2 integer, + c3 integer); + +create view v1 as select * from t1 where c2=2; +delimiter /; +create trigger trg_t1 before update on t1 for each row +begin + set new.old_c1=old.c1; + set new.old_c2=old.c2; +end; +/ +delimiter ;/ + +insert into t1(c1,c2,c3) + values (1,1,1), (1,2,2), (1,3,3), + (2,1,4), (2,2,5), (2,3,6), + (2,4,7), (2,5,8); +insert into t1 select NULL, NULL, c1+10,c2,c3+10 from t1; +insert into t1 select NULL, NULL, c1+20,c2+1,c3+20 from t1; +analyze table t1 persistent for all; + +create table tmp as select * from t1; + +--echo ####################################### +--echo # Test without any index # +--echo ####################################### +--source include/update_use_source_cases.inc + +--echo ####################################### +--echo # Test with an index # +--echo ####################################### +create index t1_c2 on t1 (c2,c1); +analyze table t1; +--source include/update_use_source_cases.inc + +--echo ####################################### +--echo # Test with a primary key # +--echo ####################################### +drop index t1_c2 on t1; +alter table t1 add primary key (c3); +analyze table t1; +--source include/update_use_source_cases.inc + +--echo # Update with error "Subquery returns more than 1 row" +--error ER_SUBQUERY_NO_1_ROW +update t1 set c2=(select c2 from t1); +--sorted_result +select c1,c2,c3 from t1; + +--echo # Update with error "Subquery returns more than 1 row" +--echo # and order by +--error ER_SUBQUERY_NO_1_ROW +update t1 set c2=(select c2 from t1) order by c3; +--sorted_result +select c1,c2,c3 from t1; + +-- echo # Duplicate value on update a primary key +--error ER_DUP_ENTRY + +update t1 set c3=0 + where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +--sorted_result +select c1,c2,c3 from t1; +truncate table t1; +insert into t1 select * from tmp; + +-- echo # Duplicate value on update a primary key with ignore --enable_info ONCE -update t1 - set c1=(select a.c3 - from t1 a - where a.c3 = t1.c3); -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; -rollback; - ---echo # ---echo # Update with search clause on the same table ---echo # - -start transaction; +update ignore t1 set c3=0 + where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +--sorted_result +select c1,c2,c3 from t1; +truncate table t1; +insert into t1 select * from tmp; + +-- echo # Duplicate value on update a primary key and limit +--error ER_DUP_ENTRY +update t1 set c3=0 + where exists (select 'X' from t1 a where a.c2 = t1.c2) + and c2 >= 3 limit 2; +--sorted_result +select c1,c2,c3 from t1; +truncate table t1; +insert into t1 select * from tmp; + +-- echo # Duplicate value on update a primary key with ignore +-- echo # and limit --enable_info ONCE -update t1 - set c1=10 - where c1 <2 - and exists (select 'X' - from t1 a - where a.c1 = t1.c1); -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; -rollback; - ---echo # ---echo # Update via RANGE or INDEX access if an index or a primary key exists ---echo # - -explain update t1 set c1=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 > 3; -start transaction; +update ignore t1 set c3=0 + where exists (select 'X' from t1 a where a.c2 = t1.c2) + and c2 >= 3 limit 2; +--sorted_result +select c1,c2,c3 from t1; +truncate table t1; +insert into t1 select * from tmp; + +--echo # Update no rows found --enable_info ONCE -update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; -rollback; - ---echo # ---echo # Update with order by ---echo # - -start transaction; -update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3 order by c2; -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; -rollback; - ---echo # ---echo Update using a view in subquery ---echo # - -start transaction; +update t1 set c1=10 + where c1 <2 and exists (select 'X' from t1 a where a.c1 = t1.c1 + 10); +--sorted_result +select c1,c2,c3 from t1; +truncate table t1; +insert into t1 select * from tmp; + +--echo # Update no rows changed +drop trigger trg_t1; --enable_info ONCE -update t1 - set c1=c1 +(select max(a.c2) - from v1 a - where a.c1 = t1.c1) ; -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; -rollback; +update t1 set c1=c1 + where c1 <2 and exists (select 'X' from t1 a where a.c1 = t1.c1); +--sorted_result +select c1,c2,c3 from t1; +truncate table t1; +insert into t1 select * from tmp; --echo # ---echo # Update throw a view +--echo # Check call of after trigger --echo # -start transaction; ---enable_info ONCE -update v1 - set c1=c1 + (select max(a.c2) - from t1 a - where a.c1 = v1.c1) +10 -where c3 > 3; -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; -rollback; - ---echo # ---echo # Update through a view and using the view in subquery ---echo # +delimiter /; +create or replace trigger trg_t2 after update on t1 for each row +begin + declare msg varchar(100); + if (new.c3 = 5) then + set msg=concat('in after update trigger on ',new.c3); + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg; + end if; +end; +/ +delimiter ;/ +--error 1644 -start transaction; ---enable_info ONCE -update v1 - set c1=c1 + 1 - where c1 <2 - and exists (select 'X' - from v1 a - where a.c1 = v1.c1); -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; -rollback; +update t1 set c1=2 + where c3 in (select distinct a.c3 from t1 a where a.c1=t1.c1); +--sorted_result +select c1,c2,c3 from t1; +truncate table t1; +insert into t1 select * from tmp; --echo # ---echo # Update through a view and using the view in subquery +--echo # Check update with order by and after trigger --echo # -start transaction; ---enable_info ONCE -update v1 - set c1=(select max(a.c1)+10 - from v1 a - where a.c1 = v1.c1) - where c1 <10 - and exists (select 'X' - from v1 a - where a.c2 = v1.c2); -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; -rollback; +--error 1644 +update t1 set c1=2 + where c3 in (select distinct a.c3 from t1 a where a.c1=t1.c1) + order by t1.c2, t1.c1; +--sorted_result +select c1,c2,c3 from t1; +truncate table t1; +insert into t1 select * from tmp; + +drop view v1; --echo # ---echo # Update of the index or primary key (c3) +--echo # Check update on view with check option --echo # -start transaction; -explain update t1 set c3=c3+10 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); ---enable_info ONCE -update t1 set c3=c3+10 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); -select c3 from t1; -rollback; +create view v1 as select * from t1 where c2=2 with check option; ---echo # ---echo # update with a limit ---echo # +-- error 1369 +update v1 set c2=3 where c1=1; +--sorted_result +select c1,c2,c3 from t1; +truncate table t1; +insert into t1 select * from tmp; -start transaction; ---enable_info ONCE -update t1 - set c1=(select a.c3 - from t1 a - where a.c3 = t1.c3) - limit 2; -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; -rollback; +-- error 1369 +update v1 set c2=(select max(c3) from v1) where c1=1; +--sorted_result +select c1,c2,c3 from t1; +truncate table t1; +insert into t1 select * from tmp; ---echo # ---echo # update with a limit and an order by ---echo # +update v1 set c2=(select min(va.c3) from v1 va), c1=0 where c1=1; +--sorted_result +select c1,c2,c3 from t1; +truncate table t1; +insert into t1 select * from tmp; -start transaction; ---enable_info ONCE -update t1 - set c1=(select a.c3 - from t1 a - where a.c3 = t1.c3) - order by c3 desc limit 2; -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; -rollback; ---enable_view_protocol +drop table tmp; +drop view v1; +drop table t1; diff --git a/mysql-test/include/update_use_source_cases.inc b/mysql-test/include/update_use_source_cases.inc new file mode 100644 index 00000000000..f1025f75cb1 --- /dev/null +++ b/mysql-test/include/update_use_source_cases.inc @@ -0,0 +1,183 @@ +--echo # +--echo # Update with value from subquery on the same table +--echo # + +analyze table t1 persistent for all; +let $q = update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +eval explain select * from t1; +eval explain $q; +--enable_info ONCE +eval $q; +select concat(old_c1,'->',c1),c3, + case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +truncate table t1; +insert into t1 select * from tmp; + +--echo # +--echo # Update with EXISTS subquery over the updated table +--echo # in WHERE + possibly sargable condition +--echo # + +analyze table t1 persistent for all; +let $c = c1 <2 + and exists (select 'X' from t1 a where a.c1 = t1.c1); +let $q = update t1 set c1=10 where $c; +eval explain select * from t1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +select concat(old_c1,'->',c1),c3, + case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +truncate table t1; +insert into t1 select * from tmp; + +--echo # +--echo # Update with EXISTS subquery over the updated table +--echo # in WHERE + non-sargable condition +--echo # + +analyze table t1 persistent for all; +let $c = exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +let $q = update t1 set c1=c1+10 where $c; +eval explain select * from t1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +select concat(old_c1,'->',c1),c3, + case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +truncate table t1; +insert into t1 select * from tmp; + +--echo # +--echo # Update with order by +--echo # + +analyze table t1 persistent for all; +let $c = exists (select 'X' from t1 a where a.c2 = t1.c2) + and c2 >= 3 order by c2; +let $q = update t1 set c1=c1+10 where $c; +eval explain select * from t1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +select concat(old_c1,'->',c1),c3, + case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +truncate table t1; +insert into t1 select * from tmp; + +--echo # +--echo # Update with a reference to view in subquery +--echo # in settable value +--echo # + +analyze table t1 persistent for all; +let $q = update t1 set c1=c1 +(select max(a.c2) from v1 a + where a.c1 = t1.c1); +eval explain select * from t1; +eval explain $q; +--enable_info ONCE +eval $q; +select concat(old_c1,'->',c1),c3, + case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +truncate table t1; +insert into t1 select * from tmp; + +--echo # +--echo # Update view +--echo # + +analyze table t1 persistent for all; +let $q = update v1 set c1=c1 + (select max(a.c2) from t1 a + where a.c1 = v1.c1) +10 where c3 > 3; +eval explain select * from v1; +eval explain $q; +--enable_info ONCE +eval $q; +select concat(old_c1,'->',c1),c3, + case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +truncate table t1; +insert into t1 select * from tmp; + +--echo # +--echo # Update view with reference to the same view in subquery +--echo # + +analyze table t1 persistent for all; +let $c = c1 <2 + and exists (select 'X' from v1 a where a.c1 = v1.c1); +let $q = update v1 set c1=c1 + 1 where $c; +eval explain select * from v1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +select concat(old_c1,'->',c1),c3, + case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +truncate table t1; +insert into t1 select * from tmp; + +--echo # +--echo # Update view with EXISTS and reference to the same view in subquery +--echo # + +analyze table t1 persistent for all; +let $c = c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +let $q = update v1 + set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) + where $c; +eval explain select * from v1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +select concat(old_c1,'->',c1),c3, + case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +truncate table t1; +insert into t1 select * from tmp; + +--echo # +--echo # Update with IN predicand over the updated table in WHERE +--echo # + +analyze table t1 persistent for all; +let $c = c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +let $q = update t1 set c3=c3+110 where $c; +eval explain select * from t1 where $c; +eval explain $q; +--enable_info ONCE +eval $q; +--sorted_result +select c3 from t1; +truncate table t1; +insert into t1 select * from tmp; + +--echo # +--echo # Update with a limit +--echo # + +analyze table t1 persistent for all; +let $q = update t1 + set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +eval explain select * from t1 limit 2; +eval explain $q; +--enable_info ONCE +eval $q; +select concat(old_c1,'->',c1),c3, + case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +truncate table t1; +insert into t1 select * from tmp; + +--echo # +--echo # Update with a limit and an order by +--echo # + +analyze table t1 persistent for all; +let $q=update t1 + set c1=(select a.c3 from t1 a where a.c3 = t1.c3) + order by c3 desc limit 2; +eval explain select * from t1 order by c3 desc limit 2; +eval explain $q; +--enable_info ONCE +eval $q; +select concat(old_c1,'->',c1),c3, + case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +truncate table t1; +insert into t1 select * from tmp; diff --git a/mysql-test/include/update_use_source_ext.inc b/mysql-test/include/update_use_source_ext.inc new file mode 100644 index 00000000000..004f7a96fd5 --- /dev/null +++ b/mysql-test/include/update_use_source_ext.inc @@ -0,0 +1,59 @@ +--echo # +--echo # Test on dynamic columns (blob) +--echo # + +create table assets ( + item_name varchar(32) primary key, -- A common attribute for all items + dynamic_cols blob -- Dynamic columns will be stored here +); +INSERT INTO assets VALUES ('MariaDB T-shirt', + COLUMN_CREATE('color', 'blue', 'size', 'XL')); +INSERT INTO assets VALUES ('Thinkpad Laptop', + COLUMN_CREATE('color', 'black', 'price', 500)); +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color + FROM assets; +UPDATE assets + SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', '3 years') + WHERE item_name='Thinkpad Laptop'; +SELECT item_name, + COLUMN_GET(dynamic_cols, 'warranty' as char) AS color + FROM assets; +UPDATE assets + SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', '4 years') + WHERE item_name in + (select b.item_name from assets b + where COLUMN_GET(b.dynamic_cols, 'color' as char) ='black'); +SELECT item_name, + COLUMN_GET(dynamic_cols, 'warranty' as char) AS color + FROM assets; + +UPDATE assets SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', + (select COLUMN_GET(b.dynamic_cols, 'color' as char) + from assets b + where assets.item_name = item_name)); +SELECT item_name, + COLUMN_GET(dynamic_cols, 'warranty' as char) AS color + FROM assets; +drop table assets; + +--echo # +--echo # Test on fulltext columns +--echo # +CREATE TABLE ft2(copy TEXT,FULLTEXT(copy)); +INSERT INTO ft2(copy) VALUES + ('MySQL vs MariaDB database'), + ('Oracle vs MariaDB database'), + ('PostgreSQL vs MariaDB database'), + ('MariaDB overview'), + ('Foreign keys'), + ('Primary keys'), + ('Indexes'), + ('Transactions'), + ('Triggers'); +SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('database'); + +update ft2 set copy = (select max(concat('mykeyword ',substr(b.copy,1,5))) + from ft2 b WHERE MATCH(b.copy) AGAINST('database')) + where MATCH(copy) AGAINST('keys'); +SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('mykeyword'); +drop table ft2; diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index fe202279ac7..903b3e48324 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -67,8 +67,8 @@ if (-d '../sql') { @plugin_suitedirs= ('storage/*/mysql-test', 'plugin/*/mysql-test', 'storage/*/*/mysql-test', ); $overlay_regex= '\b(?:storage|plugin|storage[/][^/]*)/(\w+)/mysql-test\b'; } else { - @plugin_suitedirs= ('mysql-test/plugin/*'); - $overlay_regex= '\bmysql-test/plugin/(\w+)\b'; + @plugin_suitedirs= ('mariadb-test/plugin/*'); + $overlay_regex= '\bmariadb-test/plugin/(\w+)\b'; } $plugin_suitedir_regex= $overlay_regex; $plugin_suitedir_regex=~ s/\Q(\w+)\E/\\w+/; @@ -278,8 +278,8 @@ sub load_suite_object { sub suite_for_file($) { my ($file) = @_; return ($2, $1) if $file =~ m@^(.*/$plugin_suitedir_regex/(\w+))/@o; - return ($2, $1) if $file =~ m@^(.*/mysql-test/suite/(\w+))/@; - return ('main', $1) if $file =~ m@^(.*/mysql-test)/@; + return ($2, $1) if $file =~ m@^(.*/(?:mysql|mariadb)-test/suite/(\w+))/@; + return ('main', $1) if $file =~ m@^(.*/(?:mysql|mariadb)-test)/@; mtr_error("Cannot determine suite for $file"); } @@ -387,14 +387,14 @@ sub collect_suite_name($$) else { my @dirs = my_find_dir(dirname($::glob_mysql_test_dir), - ["mysql-test/suite", @plugin_suitedirs ], + ["mariadb-test/suite", "mysql-test/suite", @plugin_suitedirs ], $suitename); # # if $suitename contained wildcards, we'll have many suites and # their overlays here. Let's group them appropriately. # for (@dirs) { - m@^.*/(?:mysql-test/suite|$plugin_suitedir_regex)/(.*)$@o or confess $_; + m@^.*/(?:mariadb-test/suite|mysql-test/suite|$plugin_suitedir_regex)/(.*)$@o or confess $_; push @{$suites{$1}}, $_; } } diff --git a/mysql-test/main/analyze_stmt_privileges2.result b/mysql-test/main/analyze_stmt_privileges2.result index 3f09b1722b6..244fc5a739e 100644 --- a/mysql-test/main/analyze_stmt_privileges2.result +++ b/mysql-test/main/analyze_stmt_privileges2.result @@ -3016,6 +3016,7 @@ ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for unde ANALYZE UPDATE v1 SET a = 10; ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table UPDATE v1 SET a = a + 1; +ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v1' EXPLAIN UPDATE v1 SET a = a + 1; ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table ANALYZE UPDATE v1 SET a = a + 1; @@ -4743,6 +4744,7 @@ ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for unde ANALYZE UPDATE v2 SET a = 10; ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table UPDATE v2 SET a = a + 1; +ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2' EXPLAIN UPDATE v2 SET a = a + 1; ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table ANALYZE UPDATE v2 SET a = a + 1; @@ -4841,12 +4843,11 @@ ANALYZE UPDATE v2 SET a = 10; id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 43 43.00 100.00 6.98 Using where UPDATE v2 SET a = a + 1; +ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2' EXPLAIN UPDATE v2 SET a = a + 1; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 43 Using where +ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2' ANALYZE UPDATE v2 SET a = a + 1; -id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 43 43.00 100.00 6.98 Using where +ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2' UPDATE v2, t2 SET v2.a = v2.a + 1 WHERE v2.a = t2.a; ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2' EXPLAIN UPDATE v2, t2 SET v2.a = v2.a + 1 WHERE v2.a = t2.a; diff --git a/mysql-test/main/analyze_stmt_privileges2.test b/mysql-test/main/analyze_stmt_privileges2.test index a0f1f4908b6..8b011c2b592 100644 --- a/mysql-test/main/analyze_stmt_privileges2.test +++ b/mysql-test/main/analyze_stmt_privileges2.test @@ -2987,8 +2987,7 @@ EXPLAIN UPDATE v1 SET a = 10; --error ER_VIEW_NO_EXPLAIN ANALYZE UPDATE v1 SET a = 10; -# Wrong result due to MDEV-7042 -#--error ER_COLUMNACCESS_DENIED_ERROR +--error ER_COLUMNACCESS_DENIED_ERROR UPDATE v1 SET a = a + 1; # Strange error code due to MDEV-7042 #--error ER_COLUMNACCESS_DENIED_ERROR @@ -4891,8 +4890,7 @@ EXPLAIN UPDATE v2 SET a = 10; --error ER_VIEW_NO_EXPLAIN ANALYZE UPDATE v2 SET a = 10; -# Wrong result due to MDEV-7042 -# --error ER_COLUMNACCESS_DENIED_ERROR +--error ER_COLUMNACCESS_DENIED_ERROR UPDATE v2 SET a = a + 1; # Strange error code due to MDEV-7042 #--error ER_COLUMNACCESS_DENIED_ERROR @@ -5009,14 +5007,11 @@ UPDATE v2 SET a = 10; EXPLAIN UPDATE v2 SET a = 10; ANALYZE UPDATE v2 SET a = 10; -# Wrong result due to MDEV-7042 -# --error ER_COLUMNACCESS_DENIED_ERROR +--error ER_COLUMNACCESS_DENIED_ERROR UPDATE v2 SET a = a + 1; -# Wrong result due to MDEV-7042 -# --error ER_COLUMNACCESS_DENIED_ERROR +--error ER_COLUMNACCESS_DENIED_ERROR EXPLAIN UPDATE v2 SET a = a + 1; -# Wrong result due to MDEV-7042 -# --error ER_COLUMNACCESS_DENIED_ERROR +--error ER_COLUMNACCESS_DENIED_ERROR ANALYZE UPDATE v2 SET a = a + 1; --error ER_COLUMNACCESS_DENIED_ERROR diff --git a/mysql-test/main/backup_interaction.result b/mysql-test/main/backup_interaction.result index a6fe7cf448d..e5ddd140516 100644 --- a/mysql-test/main/backup_interaction.result +++ b/mysql-test/main/backup_interaction.result @@ -320,20 +320,20 @@ col1 HANDLER t1_myisam CLOSE; BACKUP STAGE END; drop table t1_innodb,t1_myisam; -# Show the fate and impact of some SET GLOBAL tx_read_only = 1/0 +# Show the fate and impact of some SET GLOBAL transaction_read_only = 1/0 # sliding through the sequence. BACKUP STAGE START; -SET GLOBAL tx_read_only = 1; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 1; +SET GLOBAL transaction_read_only = 0; BACKUP STAGE FLUSH; -SET GLOBAL tx_read_only = 1; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 1; +SET GLOBAL transaction_read_only = 0; BACKUP STAGE BLOCK_DDL; -SET GLOBAL tx_read_only = 1; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 1; +SET GLOBAL transaction_read_only = 0; BACKUP STAGE BLOCK_COMMIT; -SET GLOBAL tx_read_only = 1; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 1; +SET GLOBAL transaction_read_only = 0; BACKUP STAGE END; # Show the fate and impact of some SET SESSION sql_log_bin = 0/1 # sliding through the sequence. diff --git a/mysql-test/main/backup_interaction.test b/mysql-test/main/backup_interaction.test index c755bdf8f95..8744ef2c261 100644 --- a/mysql-test/main/backup_interaction.test +++ b/mysql-test/main/backup_interaction.test @@ -300,21 +300,21 @@ HANDLER t1_myisam CLOSE; BACKUP STAGE END; drop table t1_innodb,t1_myisam; ---echo # Show the fate and impact of some SET GLOBAL tx_read_only = 1/0 +--echo # Show the fate and impact of some SET GLOBAL transaction_read_only = 1/0 --echo # sliding through the sequence. BACKUP STAGE START; -SET GLOBAL tx_read_only = 1; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 1; +SET GLOBAL transaction_read_only = 0; BACKUP STAGE FLUSH; -SET GLOBAL tx_read_only = 1; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 1; +SET GLOBAL transaction_read_only = 0; BACKUP STAGE BLOCK_DDL; -SET GLOBAL tx_read_only = 1; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 1; +SET GLOBAL transaction_read_only = 0; BACKUP STAGE BLOCK_COMMIT; -SET GLOBAL tx_read_only = 1; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 1; +SET GLOBAL transaction_read_only = 0; BACKUP STAGE END; --echo # Show the fate and impact of some SET SESSION sql_log_bin = 0/1 diff --git a/mysql-test/main/backup_stages.result b/mysql-test/main/backup_stages.result index 823e5d7e462..045497dcd0b 100644 --- a/mysql-test/main/backup_stages.result +++ b/mysql-test/main/backup_stages.result @@ -221,11 +221,11 @@ SELECT * FROM t_permanent_myisam ORDER BY col1; col1 col2 3 NULL SET AUTOCOMMIT = 0; -SET GLOBAL tx_read_only = 1; +SET GLOBAL transaction_read_only = 1; connection con12; BACKUP STAGE START; BACKUP STAGE END; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 0; DROP VIEW v_some_view; DROP TABLE t_con1_innodb; DROP TABLE t_con1_myisam; @@ -241,8 +241,8 @@ LOCK TABLES t_permanent_myisam READ; LOCK TABLES t_permanent_innodb WRITE; LOCK TABLES t_permanent_myisam WRITE; UNLOCK TABLES; -SET GLOBAL tx_read_only = 1; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 1; +SET GLOBAL transaction_read_only = 0; connection backup; BACKUP STAGE FLUSH; connection con11; @@ -255,8 +255,8 @@ LOCK TABLES t_permanent_innodb WRITE; LOCK TABLES t_permanent_myisam WRITE; ERROR HY000: Lock wait timeout exceeded; try restarting transaction UNLOCK TABLES; -SET GLOBAL tx_read_only = 1; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 1; +SET GLOBAL transaction_read_only = 0; connection backup; BACKUP STAGE BLOCK_DDL; connection con11; @@ -270,8 +270,8 @@ ERROR HY000: Lock wait timeout exceeded; try restarting transaction LOCK TABLES t_permanent_myisam WRITE; ERROR HY000: Lock wait timeout exceeded; try restarting transaction UNLOCK TABLES; -SET GLOBAL tx_read_only = 1; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 1; +SET GLOBAL transaction_read_only = 0; connection backup; BACKUP STAGE BLOCK_COMMIT; connection con11; @@ -285,8 +285,8 @@ ERROR HY000: Lock wait timeout exceeded; try restarting transaction LOCK TABLES t_permanent_myisam WRITE; ERROR HY000: Lock wait timeout exceeded; try restarting transaction UNLOCK TABLES; -SET GLOBAL tx_read_only = 1; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 1; +SET GLOBAL transaction_read_only = 0; connection backup; BACKUP STAGE END; DROP TABLE t_permanent_innodb; diff --git a/mysql-test/main/backup_stages.test b/mysql-test/main/backup_stages.test index 77d410b6caf..7af65284bf4 100644 --- a/mysql-test/main/backup_stages.test +++ b/mysql-test/main/backup_stages.test @@ -254,11 +254,11 @@ COMMIT; SELECT * FROM t_permanent_innodb ORDER BY col1; SELECT * FROM t_permanent_myisam ORDER BY col1; SET AUTOCOMMIT = 0; -SET GLOBAL tx_read_only = 1; +SET GLOBAL transaction_read_only = 1; --connection con12 BACKUP STAGE START; BACKUP STAGE END; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 0; DROP VIEW v_some_view; DROP TABLE t_con1_innodb; DROP TABLE t_con1_myisam; @@ -276,8 +276,8 @@ LOCK TABLES t_permanent_myisam READ; LOCK TABLES t_permanent_innodb WRITE; LOCK TABLES t_permanent_myisam WRITE; UNLOCK TABLES; -SET GLOBAL tx_read_only = 1; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 1; +SET GLOBAL transaction_read_only = 0; --connection backup BACKUP STAGE FLUSH; --connection con11 @@ -290,8 +290,8 @@ LOCK TABLES t_permanent_innodb WRITE; --error ER_LOCK_WAIT_TIMEOUT LOCK TABLES t_permanent_myisam WRITE; UNLOCK TABLES; -SET GLOBAL tx_read_only = 1; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 1; +SET GLOBAL transaction_read_only = 0; --connection backup BACKUP STAGE BLOCK_DDL; --connection con11 @@ -305,8 +305,8 @@ LOCK TABLES t_permanent_innodb WRITE; --error ER_LOCK_WAIT_TIMEOUT LOCK TABLES t_permanent_myisam WRITE; UNLOCK TABLES; -SET GLOBAL tx_read_only = 1; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 1; +SET GLOBAL transaction_read_only = 0; --connection backup BACKUP STAGE BLOCK_COMMIT; --connection con11 @@ -320,8 +320,8 @@ LOCK TABLES t_permanent_innodb WRITE; --error ER_LOCK_WAIT_TIMEOUT LOCK TABLES t_permanent_myisam WRITE; UNLOCK TABLES; -SET GLOBAL tx_read_only = 1; -SET GLOBAL tx_read_only = 0; +SET GLOBAL transaction_read_only = 1; +SET GLOBAL transaction_read_only = 0; --connection backup BACKUP STAGE END; diff --git a/mysql-test/main/commit.result b/mysql-test/main/commit.result index 44d46900d38..bf12f3e0ea0 100644 --- a/mysql-test/main/commit.result +++ b/mysql-test/main/commit.result @@ -19,21 +19,21 @@ SET @@autocommit=0; COMMIT; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; START TRANSACTION; -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation REPEATABLE-READ Should be REPEATABLE READ SELECT * FROM t1; s1 1 2 -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation REPEATABLE-READ Should be REPEATABLE READ INSERT INTO t1 VALUES (-1); -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation REPEATABLE-READ Should be REPEATABLE READ COMMIT; @@ -310,20 +310,20 @@ COMMIT; # # Test 2: Check setting of variable. SET SESSION TRANSACTION READ WRITE; -SELECT @@tx_read_only; -@@tx_read_only +SELECT @@transaction_read_only; +@@transaction_read_only 0 SET SESSION TRANSACTION READ ONLY; -SELECT @@tx_read_only; -@@tx_read_only +SELECT @@transaction_read_only; +@@transaction_read_only 1 SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ WRITE; -SELECT @@tx_read_only; -@@tx_read_only +SELECT @@transaction_read_only; +@@transaction_read_only 0 SET SESSION TRANSACTION READ ONLY, ISOLATION LEVEL REPEATABLE READ; -SELECT @@tx_read_only; -@@tx_read_only +SELECT @@transaction_read_only; +@@transaction_read_only 1 START TRANSACTION; # Not allowed inside a transaction @@ -528,16 +528,16 @@ DROP TABLE t1; # Test 7: SET TRANSACTION inside stored routines CREATE PROCEDURE p1() SET SESSION TRANSACTION READ ONLY; CALL p1(); -SELECT @@tx_read_only; -@@tx_read_only +SELECT @@transaction_read_only; +@@transaction_read_only 1 SET SESSION TRANSACTION READ WRITE; DROP PROCEDURE p1; CREATE PROCEDURE p1() SET SESSION TRANSACTION READ ONLY, ISOLATION LEVEL SERIALIZABLE; CALL p1(); -SELECT @@tx_read_only; -@@tx_read_only +SELECT @@transaction_read_only; +@@transaction_read_only 1 SET SESSION TRANSACTION READ WRITE, ISOLATION LEVEL REPEATABLE READ; DROP PROCEDURE p1; @@ -549,8 +549,8 @@ END| SELECT f1(); f1() 1 -SELECT @@tx_read_only; -@@tx_read_only +SELECT @@transaction_read_only; +@@transaction_read_only 1 SET SESSION TRANSACTION READ WRITE; DROP FUNCTION f1; @@ -562,8 +562,8 @@ END| SELECT f1(); f1() 1 -SELECT @@tx_read_only; -@@tx_read_only +SELECT @@transaction_read_only; +@@transaction_read_only 1 SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ WRITE; DROP FUNCTION f1; diff --git a/mysql-test/main/commit.test b/mysql-test/main/commit.test index a0d4ddee152..4fb86f5e8bc 100644 --- a/mysql-test/main/commit.test +++ b/mysql-test/main/commit.test @@ -34,23 +34,23 @@ COMMIT; # # Verify consistent output from -# SELECT @@tx_isolation (Bug#20837) +# SELECT @@transaction_isolation (Bug#20837) # # The transaction will be in READ UNCOMMITTED mode, -# but SELECT @@tx_isolation should report the session +# but SELECT @@transaction_isolation should report the session # value, which is REPEATABLE READ # SET @@autocommit=0; COMMIT; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; START TRANSACTION; -SELECT @@tx_isolation; +SELECT @@transaction_isolation; --echo Should be REPEATABLE READ SELECT * FROM t1; -SELECT @@tx_isolation; +SELECT @@transaction_isolation; --echo Should be REPEATABLE READ INSERT INTO t1 VALUES (-1); -SELECT @@tx_isolation; +SELECT @@transaction_isolation; --echo Should be REPEATABLE READ COMMIT; @@ -370,16 +370,16 @@ COMMIT; --echo # Test 2: Check setting of variable. SET SESSION TRANSACTION READ WRITE; -SELECT @@tx_read_only; +SELECT @@transaction_read_only; SET SESSION TRANSACTION READ ONLY; -SELECT @@tx_read_only; +SELECT @@transaction_read_only; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ WRITE; -SELECT @@tx_read_only; +SELECT @@transaction_read_only; SET SESSION TRANSACTION READ ONLY, ISOLATION LEVEL REPEATABLE READ; -SELECT @@tx_read_only; +SELECT @@transaction_read_only; START TRANSACTION; --echo # Not allowed inside a transaction @@ -628,14 +628,14 @@ DROP TABLE t1; CREATE PROCEDURE p1() SET SESSION TRANSACTION READ ONLY; CALL p1(); -SELECT @@tx_read_only; +SELECT @@transaction_read_only; SET SESSION TRANSACTION READ WRITE; DROP PROCEDURE p1; CREATE PROCEDURE p1() SET SESSION TRANSACTION READ ONLY, ISOLATION LEVEL SERIALIZABLE; CALL p1(); -SELECT @@tx_read_only; +SELECT @@transaction_read_only; SET SESSION TRANSACTION READ WRITE, ISOLATION LEVEL REPEATABLE READ; DROP PROCEDURE p1; @@ -648,7 +648,7 @@ END| delimiter ;| SELECT f1(); -SELECT @@tx_read_only; +SELECT @@transaction_read_only; SET SESSION TRANSACTION READ WRITE; DROP FUNCTION f1; @@ -661,7 +661,7 @@ END| delimiter ;| SELECT f1(); -SELECT @@tx_read_only; +SELECT @@transaction_read_only; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ WRITE; DROP FUNCTION f1; diff --git a/mysql-test/main/concurrent_innodb_safelog.result b/mysql-test/main/concurrent_innodb_safelog.result index 40f89c7c65b..182e99256f8 100644 --- a/mysql-test/main/concurrent_innodb_safelog.result +++ b/mysql-test/main/concurrent_innodb_safelog.result @@ -3,8 +3,8 @@ SET GLOBAL innodb_lock_wait_timeout = 1; SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ; connection default; SET SQL_MODE=""; -SELECT @@global.tx_isolation; -@@global.tx_isolation +SELECT @@global.transaction_isolation; +@@global.transaction_isolation REPEATABLE-READ # keep_locks == 1 GRANT ALL ON test.* TO mysqltest@localhost; diff --git a/mysql-test/main/concurrent_innodb_unsafelog.result b/mysql-test/main/concurrent_innodb_unsafelog.result index 3771438bc66..b87a420b6c6 100644 --- a/mysql-test/main/concurrent_innodb_unsafelog.result +++ b/mysql-test/main/concurrent_innodb_unsafelog.result @@ -1,11 +1,11 @@ SET @save_timeout = @@GLOBAL.innodb_lock_wait_timeout; SET GLOBAL innodb_lock_wait_timeout = 1; -SET @save_isolation = @@GLOBAL.tx_isolation; +SET @save_isolation = @@GLOBAL.transaction_isolation; SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; connection default; SET SQL_MODE=""; -SELECT @@global.tx_isolation; -@@global.tx_isolation +SELECT @@global.transaction_isolation; +@@global.transaction_isolation READ-COMMITTED # keep_locks == 0 GRANT ALL ON test.* TO mysqltest@localhost; @@ -791,4 +791,4 @@ drop table t1; drop user mysqltest@localhost; SET SQL_MODE=default; SET GLOBAL innodb_lock_wait_timeout = @save_timeout; -SET GLOBAL tx_isolation = @save_isolation; +SET GLOBAL transaction_isolation = @save_isolation; diff --git a/mysql-test/main/concurrent_innodb_unsafelog.test b/mysql-test/main/concurrent_innodb_unsafelog.test index d9e5effaaf6..400d7ef8d87 100644 --- a/mysql-test/main/concurrent_innodb_unsafelog.test +++ b/mysql-test/main/concurrent_innodb_unsafelog.test @@ -18,10 +18,10 @@ let $engine_type= InnoDB; SET @save_timeout = @@GLOBAL.innodb_lock_wait_timeout; SET GLOBAL innodb_lock_wait_timeout = 1; -SET @save_isolation = @@GLOBAL.tx_isolation; +SET @save_isolation = @@GLOBAL.transaction_isolation; SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; --disable_service_connection --source include/concurrent.inc --enable_service_connection SET GLOBAL innodb_lock_wait_timeout = @save_timeout; -SET GLOBAL tx_isolation = @save_isolation; +SET GLOBAL transaction_isolation = @save_isolation; diff --git a/mysql-test/main/delete.result b/mysql-test/main/delete.result index 900c14c5578..c4bf335091a 100644 --- a/mysql-test/main/delete.result +++ b/mysql-test/main/delete.result @@ -564,3 +564,50 @@ having t3.a > any (select t2.b from t2 where t2.b*10 < sum(t3.b))); drop table t1,t2,t3; End of 10.4 tests +# +# MDEV-29428: DELETE with ORDER BY without LIMIT clause +# +create table t1 (c1 integer, c2 integer, c3 integer); +insert into t1 values +(1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,4,7), (2,5,8); +create temporary table t select * from t1; +explain delete from t1 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL 8 Deleting all rows +delete from t1 order by c2; +select *from t1; +c1 c2 c3 +delete from t1; +insert into t1 select * from t; +explain delete from t1 +where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 8 Using where; FirstMatch(t1) +delete from t1 +where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +select *from t1; +c1 c2 c3 +1 1 1 +1 2 2 +2 1 4 +2 2 5 +delete from t1; +insert into t1 select * from t; +explain delete from t1 +where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3 +order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 8 Using where; FirstMatch(t1) +delete from t1 +where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3 +order by c2; +select *from t1; +c1 c2 c3 +1 1 1 +1 2 2 +2 1 4 +2 2 5 +drop table t1; +End of 11.1 tests diff --git a/mysql-test/main/delete.test b/mysql-test/main/delete.test index 733384193e5..a4057666818 100644 --- a/mysql-test/main/delete.test +++ b/mysql-test/main/delete.test @@ -624,3 +624,45 @@ update t1 set t1.a=t1.a+10 drop table t1,t2,t3; --echo End of 10.4 tests + +--echo # +--echo # MDEV-29428: DELETE with ORDER BY without LIMIT clause +--echo # + +create table t1 (c1 integer, c2 integer, c3 integer); + +insert into t1 values + (1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,4,7), (2,5,8); + +create temporary table t select * from t1; + +let $q1= +delete from t1 order by c2; +eval explain $q1; +eval $q1; +select *from t1; + +delete from t1; +insert into t1 select * from t; + +let $q2= +delete from t1 + where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +eval explain $q2; +eval $q2; +select *from t1; + +delete from t1; +insert into t1 select * from t; + +let $q3= +delete from t1 + where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3 + order by c2; +eval explain $q3; +eval $q3; +select *from t1; + +drop table t1; + +--echo End of 11.1 tests diff --git a/mysql-test/main/delete_single_to_multi.result b/mysql-test/main/delete_single_to_multi.result new file mode 100644 index 00000000000..57cc224203a --- /dev/null +++ b/mysql-test/main/delete_single_to_multi.result @@ -0,0 +1,4252 @@ +DROP DATABASE IF EXISTS dbt3_s001; +CREATE DATABASE dbt3_s001; +use dbt3_s001; +create index i_n_name on nation(n_name); +analyze table +nation, lineitem, customer, orders, part, supplier, partsupp, region +persistent for all; +Table Op Msg_type Msg_text +dbt3_s001.nation analyze status Engine-independent statistics collected +dbt3_s001.nation analyze status OK +dbt3_s001.lineitem analyze status Engine-independent statistics collected +dbt3_s001.lineitem analyze status OK +dbt3_s001.customer analyze status Engine-independent statistics collected +dbt3_s001.customer analyze status OK +dbt3_s001.orders analyze status Engine-independent statistics collected +dbt3_s001.orders analyze status OK +dbt3_s001.part analyze status Engine-independent statistics collected +dbt3_s001.part analyze status OK +dbt3_s001.supplier analyze status Engine-independent statistics collected +dbt3_s001.supplier analyze status OK +dbt3_s001.partsupp analyze status Engine-independent statistics collected +dbt3_s001.partsupp analyze status OK +dbt3_s001.region analyze status Engine-independent statistics collected +dbt3_s001.region analyze status OK +# Pullout +# ======= +explain +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (7%) Using where; Using rowid filter +explain format=json +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.052271677, + "nested_loop": [ + { + "table": { + "table_name": "nation", + "access_type": "ref", + "possible_keys": ["PRIMARY", "i_n_name"], + "key": "i_n_name", + "key_length": "26", + "used_key_parts": ["n_name"], + "ref": ["const"], + "loops": 1, + "rows": 1, + "cost": 0.002024411, + "filtered": 100, + "index_condition": "nation.n_name = 'PERU'" + } + }, + { + "table": { + "table_name": "customer", + "access_type": "ref", + "possible_keys": ["PRIMARY", "i_c_nationkey"], + "key": "i_c_nationkey", + "key_length": "5", + "used_key_parts": ["c_nationkey"], + "ref": ["dbt3_s001.nation.n_nationkey"], + "loops": 1, + "rows": 6, + "cost": 0.008193756, + "filtered": 100 + } + }, + { + "table": { + "table_name": "orders", + "access_type": "ref", + "possible_keys": ["i_o_orderdate", "i_o_custkey"], + "key": "i_o_custkey", + "key_length": "5", + "used_key_parts": ["o_custkey"], + "ref": ["dbt3_s001.customer.c_custkey"], + "rowid_filter": { + "range": { + "key": "i_o_orderdate", + "used_key_parts": ["o_orderDATE"] + }, + "rows": 108, + "selectivity_pct": 7.2 + }, + "loops": 6, + "rows": 15, + "cost": 0.04205351, + "filtered": 7.199999809, + "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'" + } + } + ] + } +} +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +1729 12137.76 +2880 145761.99 +3142 16030.15 +5095 184583.99 +5121 150334.57 +5382 138423.03 +644 201268.06 +737 12984.85 +create table t as +select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +explain +delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (7%) Using where; Using rowid filter +explain format=json +delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.052271677, + "nested_loop": [ + { + "table": { + "table_name": "nation", + "access_type": "ref", + "possible_keys": ["PRIMARY", "i_n_name"], + "key": "i_n_name", + "key_length": "26", + "used_key_parts": ["n_name"], + "ref": ["const"], + "loops": 1, + "rows": 1, + "cost": 0.002024411, + "filtered": 100, + "index_condition": "nation.n_name = 'PERU'" + } + }, + { + "table": { + "table_name": "customer", + "access_type": "ref", + "possible_keys": ["PRIMARY", "i_c_nationkey"], + "key": "i_c_nationkey", + "key_length": "5", + "used_key_parts": ["c_nationkey"], + "ref": ["dbt3_s001.nation.n_nationkey"], + "loops": 1, + "rows": 6, + "cost": 0.008193756, + "filtered": 100 + } + }, + { + "table": { + "table_name": "orders", + "access_type": "ref", + "possible_keys": ["i_o_orderdate", "i_o_custkey"], + "key": "i_o_custkey", + "key_length": "5", + "used_key_parts": ["o_custkey"], + "ref": ["dbt3_s001.customer.c_custkey"], + "rowid_filter": { + "range": { + "key": "i_o_orderdate", + "used_key_parts": ["o_orderDATE"] + }, + "rows": 108, + "selectivity_pct": 7.2 + }, + "loops": 6, + "rows": 15, + "cost": 0.04205351, + "filtered": 7.199999809, + "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'" + } + } + ] + } +} +delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +insert into orders select * from t; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +1729 12137.76 +2880 145761.99 +3142 16030.15 +5095 184583.99 +5121 150334.57 +5382 138423.03 +644 201268.06 +737 12984.85 +drop table t; +explain +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 910 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 +1 PRIMARY part ALL PRIMARY NULL NULL NULL 200 Using where; Using join buffer (flat, BNL join) +1 PRIMARY partsupp eq_ref PRIMARY,i_ps_partkey,i_ps_suppkey PRIMARY 8 dbt3_s001.part.p_partkey,dbt3_s001.supplier.s_suppkey 1 +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 910 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +ps_partkey ps_suppkey ps_supplycost +1 8 357.84 +3 8 645.4 +4 1 444.37 +5 8 50.52 +6 1 642.13 +7 8 763.98 +8 1 957.34 +create table t as +select * from partsupp where (ps_partkey, ps_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 910 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +explain +delete from partsupp where (ps_partkey, ps_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 910 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 +1 PRIMARY part ALL PRIMARY NULL NULL NULL 200 Using where +1 PRIMARY partsupp eq_ref PRIMARY,i_ps_partkey,i_ps_suppkey PRIMARY 8 dbt3_s001.part.p_partkey,dbt3_s001.supplier.s_suppkey 1 +delete from partsupp where (ps_partkey, ps_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 910 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 910 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +ps_partkey ps_suppkey ps_supplycost +insert into partsupp select * from t; +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 910 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +ps_partkey ps_suppkey ps_supplycost +1 8 357.84 +3 8 645.4 +4 1 444.37 +5 8 50.52 +6 1 642.13 +7 8 763.98 +8 1 957.34 +drop table t; +explain +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part +where p_retailprice between 901 and 910) and +ps_suppkey in (select s_suppkey from supplier +where s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 +1 PRIMARY part ALL PRIMARY NULL NULL NULL 200 Using where; Using join buffer (flat, BNL join) +1 PRIMARY partsupp eq_ref PRIMARY,i_ps_partkey,i_ps_suppkey PRIMARY 8 dbt3_s001.part.p_partkey,dbt3_s001.supplier.s_suppkey 1 +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part +where p_retailprice between 901 and 910) and +ps_suppkey in (select s_suppkey from supplier +where s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +ps_partkey ps_suppkey ps_supplycost +1 8 357.84 +3 8 645.4 +4 1 444.37 +5 8 50.52 +6 1 642.13 +7 8 763.98 +8 1 957.34 +create table t as +select * from partsupp where ps_partkey in (select p_partkey from part +where p_retailprice between 901 and 910) and +ps_suppkey in (select s_suppkey from supplier +where s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +explain +delete from partsupp where ps_partkey in (select p_partkey from part +where p_retailprice between 901 and 910) and +ps_suppkey in (select s_suppkey from supplier +where s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 +1 PRIMARY part ALL PRIMARY NULL NULL NULL 200 Using where +1 PRIMARY partsupp eq_ref PRIMARY,i_ps_partkey,i_ps_suppkey PRIMARY 8 dbt3_s001.part.p_partkey,dbt3_s001.supplier.s_suppkey 1 +delete from partsupp where ps_partkey in (select p_partkey from part +where p_retailprice between 901 and 910) and +ps_suppkey in (select s_suppkey from supplier +where s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part +where p_retailprice between 901 and 910) and +ps_suppkey in (select s_suppkey from supplier +where s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +ps_partkey ps_suppkey ps_supplycost +insert into partsupp select * from t; +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part +where p_retailprice between 901 and 910) and +ps_suppkey in (select s_suppkey from supplier +where s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +ps_partkey ps_suppkey ps_supplycost +1 8 357.84 +3 8 645.4 +4 1 444.37 +5 8 50.52 +6 1 642.13 +7 8 763.98 +8 1 957.34 +drop table t; +explain +select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders +where o_custkey in +(select c_custkey from customer +where c_nationkey in +(select n_nationkey from nation +where n_name='PERU')) +and +o_orderDATE between '1992-06-30' and '1992-12-31') +and +(l_partkey, l_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 1000 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY orders ref|filter PRIMARY,i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (7%) Using where; Using rowid filter +1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 dbt3_s001.orders.o_orderkey 4 Using where +1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where +select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders +where o_custkey in +(select c_custkey from customer +where c_nationkey in +(select n_nationkey from nation +where n_name='PERU')) +and +o_orderDATE between '1992-06-30' and '1992-12-31') +and +(l_partkey, l_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 1000 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +l_orderkey l_linenumber l_tax +2500 2 0.02 +2500 4 0.02 +4996 1 0.01 +933 1 0.04 +create table t as +select * from lineitem where l_orderkey in (select o_orderkey from orders +where o_custkey in +(select c_custkey from customer +where c_nationkey in +(select n_nationkey from nation +where n_name='PERU')) +and +o_orderDATE between '1992-06-30' and '1992-12-31') +and +(l_partkey, l_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 1000 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +explain +delete from lineitem where l_orderkey in (select o_orderkey from orders +where o_custkey in +(select c_custkey from customer +where c_nationkey in +(select n_nationkey from nation +where n_name='PERU')) +and +o_orderDATE between '1992-06-30' and '1992-12-31') +and +(l_partkey, l_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 1000 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY orders ref|filter PRIMARY,i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (7%) Using where; Using rowid filter +1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 dbt3_s001.orders.o_orderkey 4 Using where +1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where +delete from lineitem where l_orderkey in (select o_orderkey from orders +where o_custkey in +(select c_custkey from customer +where c_nationkey in +(select n_nationkey from nation +where n_name='PERU')) +and +o_orderDATE between '1992-06-30' and '1992-12-31') +and +(l_partkey, l_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 1000 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders +where o_custkey in +(select c_custkey from customer +where c_nationkey in +(select n_nationkey from nation +where n_name='PERU')) +and +o_orderDATE between '1992-06-30' and '1992-12-31') +and +(l_partkey, l_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 1000 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +l_orderkey l_linenumber l_tax +insert into lineitem select * from t; +select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders +where o_custkey in +(select c_custkey from customer +where c_nationkey in +(select n_nationkey from nation +where n_name='PERU')) +and +o_orderDATE between '1992-06-30' and '1992-12-31') +and +(l_partkey, l_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 1000 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +l_orderkey l_linenumber l_tax +2500 2 0.02 +2500 4 0.02 +4996 1 0.01 +933 1 0.04 +drop table t; +# FirstMatch +# ========== +set optimizer_switch='materialization=off'; +explain +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ALL PRIMARY,i_n_regionkey NULL NULL NULL 25 Using where +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (9%) Using where; FirstMatch(customer); Using rowid filter +explain format=json +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.40015207, + "nested_loop": [ + { + "table": { + "table_name": "nation", + "access_type": "ALL", + "possible_keys": ["PRIMARY", "i_n_regionkey"], + "loops": 1, + "rows": 25, + "cost": 0.013945725, + "filtered": 40, + "attached_condition": "nation.n_regionkey in (1,2)" + } + }, + { + "table": { + "table_name": "customer", + "access_type": "ref", + "possible_keys": ["PRIMARY", "i_c_nationkey"], + "key": "i_c_nationkey", + "key_length": "5", + "used_key_parts": ["c_nationkey"], + "ref": ["dbt3_s001.nation.n_nationkey"], + "loops": 10, + "rows": 6, + "cost": 0.08009436, + "filtered": 100 + } + }, + { + "table": { + "table_name": "orders", + "access_type": "ref", + "possible_keys": ["i_o_orderdate", "i_o_custkey"], + "key": "i_o_custkey", + "key_length": "5", + "used_key_parts": ["o_custkey"], + "ref": ["dbt3_s001.customer.c_custkey"], + "rowid_filter": { + "range": { + "key": "i_o_orderdate", + "used_key_parts": ["o_orderDATE"] + }, + "rows": 140, + "selectivity_pct": 9.333333333 + }, + "loops": 60, + "rows": 15, + "cost": 0.306111985, + "filtered": 6.666666508, + "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-06-08'", + "first_match": "customer" + } + } + ] + } +} +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000037 -917.75 +Customer#000000040 1335.3 +Customer#000000047 274.58 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000064 -646.64 +Customer#000000067 8166.59 +Customer#000000077 1738.87 +Customer#000000082 9468.34 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000097 2164.48 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000106 3288.42 +Customer#000000115 7508.92 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000124 1842.49 +Customer#000000127 9280.71 +Customer#000000130 5073.58 +Customer#000000133 2314.67 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +create table t as +select * from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +explain +delete from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ALL PRIMARY,i_n_regionkey NULL NULL NULL 25 Using where +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (9%) Using where; FirstMatch(customer); Using rowid filter +explain format=json +delete from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.40015207, + "nested_loop": [ + { + "table": { + "table_name": "nation", + "access_type": "ALL", + "possible_keys": ["PRIMARY", "i_n_regionkey"], + "loops": 1, + "rows": 25, + "cost": 0.013945725, + "filtered": 40, + "attached_condition": "nation.n_regionkey in (1,2)" + } + }, + { + "table": { + "table_name": "customer", + "access_type": "ref", + "possible_keys": ["PRIMARY", "i_c_nationkey"], + "key": "i_c_nationkey", + "key_length": "5", + "used_key_parts": ["c_nationkey"], + "ref": ["dbt3_s001.nation.n_nationkey"], + "loops": 10, + "rows": 6, + "cost": 0.08009436, + "filtered": 100 + } + }, + { + "table": { + "table_name": "orders", + "access_type": "ref", + "possible_keys": ["i_o_orderdate", "i_o_custkey"], + "key": "i_o_custkey", + "key_length": "5", + "used_key_parts": ["o_custkey"], + "ref": ["dbt3_s001.customer.c_custkey"], + "rowid_filter": { + "range": { + "key": "i_o_orderdate", + "used_key_parts": ["o_orderDATE"] + }, + "rows": 140, + "selectivity_pct": 9.333333333 + }, + "loops": 60, + "rows": 15, + "cost": 0.306111985, + "filtered": 6.666666508, + "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-06-08'", + "first_match": "customer" + } + } + ] + } +} +delete from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +insert into customer select * from t; +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000037 -917.75 +Customer#000000040 1335.3 +Customer#000000047 274.58 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000064 -646.64 +Customer#000000067 8166.59 +Customer#000000077 1738.87 +Customer#000000082 9468.34 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000097 2164.48 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000106 3288.42 +Customer#000000115 7508.92 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000124 1842.49 +Customer#000000127 9280.71 +Customer#000000130 5073.58 +Customer#000000133 2314.67 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +drop table t; +set optimizer_switch='materialization=default'; +explain +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU') +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1993-01-08"); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (14%) Using where; FirstMatch(customer); Using rowid filter +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU') +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1993-01-08"); +c_name c_acctbal +Customer#000000008 6819.74 +Customer#000000035 1228.24 +Customer#000000061 1536.24 +Customer#000000097 2164.48 +Customer#000000121 6428.32 +Customer#000000133 2314.67 +create table t as +select * from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU') +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1993-01-08"); +explain +delete from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU') +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1993-01-08"); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (14%) Using where; FirstMatch(customer); Using rowid filter +delete from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU') +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1993-01-08"); +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU') +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1993-01-08"); +c_name c_acctbal +insert into customer select * from t; +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU') +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1993-01-08"); +c_name c_acctbal +Customer#000000008 6819.74 +Customer#000000035 1228.24 +Customer#000000061 1536.24 +Customer#000000097 2164.48 +Customer#000000121 6428.32 +Customer#000000133 2314.67 +drop table t; +# Materialization +# =============== +set optimizer_switch='firstmatch=off'; +explain +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where +n_name in ('JAPAN', 'INDONESIA', 'PERU', 'ARGENTINA')) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1995-01-08"); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation range PRIMARY,i_n_name i_n_name 26 NULL 4 Using index condition +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 +3 MATERIALIZED orders ALL i_o_orderdate,i_o_custkey NULL NULL NULL 1500 Using where +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where +n_name in ('JAPAN', 'INDONESIA', 'PERU', 'ARGENTINA')) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1995-01-08"); +c_name c_acctbal +Customer#000000008 6819.74 +Customer#000000014 5266.3 +Customer#000000025 7133.7 +Customer#000000035 1228.24 +Customer#000000038 6345.11 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000067 8166.59 +Customer#000000077 1738.87 +Customer#000000094 5500.11 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000103 2757.45 +Customer#000000106 3288.42 +Customer#000000113 2912 +Customer#000000121 6428.32 +Customer#000000130 5073.58 +Customer#000000133 2314.67 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +create table t as +select * from customer where c_nationkey in (select n_nationkey from nation where +n_name in ('JAPAN', 'INDONESIA', 'PERU', 'ARGENTINA')) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1995-01-08"); +explain +delete from customer where c_nationkey in (select n_nationkey from nation where +n_name in ('JAPAN', 'INDONESIA', 'PERU', 'ARGENTINA')) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1995-01-08"); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation range PRIMARY,i_n_name i_n_name 26 NULL 4 Using index condition +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 +3 MATERIALIZED orders ALL i_o_orderdate,i_o_custkey NULL NULL NULL 1500 Using where +delete from customer where c_nationkey in (select n_nationkey from nation where +n_name in ('JAPAN', 'INDONESIA', 'PERU', 'ARGENTINA')) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1995-01-08"); +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where +n_name in ('JAPAN', 'INDONESIA', 'PERU', 'ARGENTINA')) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1995-01-08"); +c_name c_acctbal +insert into customer select * from t; +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where +n_name in ('JAPAN', 'INDONESIA', 'PERU', 'ARGENTINA')) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1995-01-08"); +c_name c_acctbal +Customer#000000008 6819.74 +Customer#000000014 5266.3 +Customer#000000025 7133.7 +Customer#000000035 1228.24 +Customer#000000038 6345.11 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000067 8166.59 +Customer#000000077 1738.87 +Customer#000000094 5500.11 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000103 2757.45 +Customer#000000106 3288.42 +Customer#000000113 2912 +Customer#000000121 6428.32 +Customer#000000130 5073.58 +Customer#000000133 2314.67 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +drop table t; +set optimizer_switch='firstmatch=default'; +explain +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED orders ALL i_o_orderdate,i_o_custkey NULL NULL NULL 1500 Using where +explain format=json +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.382051418, + "nested_loop": [ + { + "table": { + "table_name": "customer", + "access_type": "ALL", + "possible_keys": ["PRIMARY"], + "loops": 1, + "rows": 150, + "cost": 0.03493875, + "filtered": 100 + } + }, + { + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "4", + "used_key_parts": ["o_custkey"], + "ref": ["func"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "nested_loop": [ + { + "table": { + "table_name": "orders", + "access_type": "ALL", + "possible_keys": ["i_o_orderdate", "i_o_custkey"], + "loops": 1, + "rows": 1500, + "cost": 0.2532975, + "filtered": 16.13333321, + "attached_condition": "orders.o_orderDATE between '1992-01-09' and '1993-03-08'" + } + } + ] + } + } + } + } + ] + } +} +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000005 794.47 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000013 3857.34 +Customer#000000014 5266.3 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000032 3471.53 +Customer#000000034 8589.7 +Customer#000000035 1228.24 +Customer#000000037 -917.75 +Customer#000000038 6345.11 +Customer#000000040 1335.3 +Customer#000000041 270.95 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000052 5630.28 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000056 6530.86 +Customer#000000058 6478.46 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000062 595.61 +Customer#000000064 -646.64 +Customer#000000065 8795.16 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000089 1530.76 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000107 2514.15 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000115 7508.92 +Customer#000000116 8403.99 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000128 -986.96 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000140 9963.15 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000145 9748.93 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +create table t as +select * from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +explain +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED orders ALL i_o_orderdate,i_o_custkey NULL NULL NULL 1500 Using where +explain format=json +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.37364371, + "nested_loop": [ + { + "table": { + "table_name": "customer", + "access_type": "ALL", + "possible_keys": ["PRIMARY"], + "loops": 1, + "rows": 150, + "cost": 0.026531042, + "filtered": 100 + } + }, + { + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "4", + "used_key_parts": ["o_custkey"], + "ref": ["func"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "nested_loop": [ + { + "table": { + "table_name": "orders", + "access_type": "ALL", + "possible_keys": ["i_o_orderdate", "i_o_custkey"], + "loops": 1, + "rows": 1500, + "cost": 0.2532975, + "filtered": 16.13333321, + "attached_condition": "orders.o_orderDATE between '1992-01-09' and '1993-03-08'" + } + } + ] + } + } + } + } + ] + } +} +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +insert into customer select * from t; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000005 794.47 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000013 3857.34 +Customer#000000014 5266.3 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000032 3471.53 +Customer#000000034 8589.7 +Customer#000000035 1228.24 +Customer#000000037 -917.75 +Customer#000000038 6345.11 +Customer#000000040 1335.3 +Customer#000000041 270.95 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000052 5630.28 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000056 6530.86 +Customer#000000058 6478.46 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000062 595.61 +Customer#000000064 -646.64 +Customer#000000065 8795.16 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000089 1530.76 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000107 2514.15 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000115 7508.92 +Customer#000000116 8403.99 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000128 -986.96 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000140 9963.15 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000145 9748.93 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +drop table t; +explain +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-06-09' and '1993-01-08'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-06-09' and '1993-01-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000034 8589.7 +Customer#000000037 -917.75 +Customer#000000040 1335.3 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000061 1536.24 +Customer#000000064 -646.64 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +create table t as +select * from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-06-09' and '1993-01-08'); +explain +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-06-09' and '1993-01-08'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-06-09' and '1993-01-08'); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-06-09' and '1993-01-08'); +c_name c_acctbal +insert into customer select * from t; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-06-09' and '1993-01-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000034 8589.7 +Customer#000000037 -917.75 +Customer#000000040 1335.3 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000061 1536.24 +Customer#000000064 -646.64 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +drop table t; +# Materialization SJM +# =================== +explain +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28 +1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1 +2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary +explain format=json +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.085533248, + "nested_loop": [ + { + "table": { + "table_name": "<subquery2>", + "access_type": "ALL", + "possible_keys": ["distinct_key"], + "loops": 1, + "rows": 28, + "cost": 0.03691572, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "cost": 0.053826401, + "having_condition": "count(orders.o_custkey) > 1", + "temporary_table": { + "nested_loop": [ + { + "table": { + "table_name": "orders", + "access_type": "range", + "possible_keys": ["i_o_orderdate"], + "key": "i_o_orderdate", + "key_length": "4", + "used_key_parts": ["o_orderDATE"], + "loops": 1, + "rows": 28, + "cost": 0.035889016, + "filtered": 100, + "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'" + } + } + ] + } + } + } + } + }, + { + "table": { + "table_name": "customer", + "access_type": "eq_ref", + "possible_keys": ["PRIMARY"], + "key": "PRIMARY", + "key_length": "4", + "used_key_parts": ["c_custkey"], + "ref": ["<subquery2>.o_custkey"], + "loops": 28, + "rows": 1, + "cost": 0.048617528, + "filtered": 100 + } + } + ] + } +} +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3857.34 +Customer#000000032 3471.53 +Customer#000000037 -917.75 +Customer#000000056 6530.86 +Customer#000000118 3582.37 +create table t as +select * from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +explain +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28 +1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1 +2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary +explain format=json +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.054856476, + "nested_loop": [ + { + "table": { + "table_name": "<subquery2>", + "access_type": "ALL", + "possible_keys": ["distinct_key"], + "loops": 1, + "rows": 28, + "cost": 0.03691572, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "cost": 0.053826401, + "having_condition": "count(orders.o_custkey) > 1", + "temporary_table": { + "nested_loop": [ + { + "table": { + "table_name": "orders", + "access_type": "range", + "possible_keys": ["i_o_orderdate"], + "key": "i_o_orderdate", + "key_length": "4", + "used_key_parts": ["o_orderDATE"], + "loops": 1, + "rows": 28, + "cost": 0.035889016, + "filtered": 100, + "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'" + } + } + ] + } + } + } + } + }, + { + "table": { + "table_name": "customer", + "access_type": "eq_ref", + "possible_keys": ["PRIMARY"], + "key": "PRIMARY", + "key_length": "4", + "used_key_parts": ["c_custkey"], + "ref": ["<subquery2>.o_custkey"], + "loops": 28, + "rows": 1, + "cost": 0.017940756, + "filtered": 100 + } + } + ] + } +} +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +insert into customer select * from t; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3857.34 +Customer#000000032 3471.53 +Customer#000000037 -917.75 +Customer#000000056 6530.86 +Customer#000000118 3582.37 +drop table t; +explain +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08' + group by o_custkey having count(o_custkey) > 5); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1 +2 MATERIALIZED orders ALL i_o_orderdate NULL NULL NULL 1500 Using where; Using temporary +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08' + group by o_custkey having count(o_custkey) > 5); +c_name c_acctbal +Customer#000000007 9561.95 +Customer#000000016 4681.03 +Customer#000000037 -917.75 +Customer#000000046 5744.59 +Customer#000000091 4643.14 +Customer#000000103 2757.45 +Customer#000000118 3582.37 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +create table t as +select * from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08' + group by o_custkey having count(o_custkey) > 5); +explain +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08' + group by o_custkey having count(o_custkey) > 5); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1 +2 MATERIALIZED orders ALL i_o_orderdate NULL NULL NULL 1500 Using where; Using temporary +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08' + group by o_custkey having count(o_custkey) > 5); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08' + group by o_custkey having count(o_custkey) > 5); +c_name c_acctbal +insert into customer select * from t; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08' + group by o_custkey having count(o_custkey) > 5); +c_name c_acctbal +Customer#000000007 9561.95 +Customer#000000016 4681.03 +Customer#000000037 -917.75 +Customer#000000046 5744.59 +Customer#000000091 4643.14 +Customer#000000103 2757.45 +Customer#000000118 3582.37 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +drop table t; +# Pullout PS +# ========== +prepare stmt from " +delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +"; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +1729 12137.76 +2880 145761.99 +3142 16030.15 +5095 184583.99 +5121 150334.57 +5382 138423.03 +644 201268.06 +737 12984.85 +create table t as +select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +execute stmt; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +insert into orders select * from t; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +1729 12137.76 +2880 145761.99 +3142 16030.15 +5095 184583.99 +5121 150334.57 +5382 138423.03 +644 201268.06 +737 12984.85 +create table r as +select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +execute stmt; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +insert into orders select * from r; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +1729 12137.76 +2880 145761.99 +3142 16030.15 +5095 184583.99 +5121 150334.57 +5382 138423.03 +644 201268.06 +737 12984.85 +drop table t,r; +deallocate prepare stmt; +# FirstMatch PS +# ============= +set optimizer_switch='materialization=off'; +prepare stmt from " +delete from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +"; +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000037 -917.75 +Customer#000000040 1335.3 +Customer#000000047 274.58 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000064 -646.64 +Customer#000000067 8166.59 +Customer#000000077 1738.87 +Customer#000000082 9468.34 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000097 2164.48 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000106 3288.42 +Customer#000000115 7508.92 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000124 1842.49 +Customer#000000127 9280.71 +Customer#000000130 5073.58 +Customer#000000133 2314.67 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +create table t as +select * from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +execute stmt; +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +insert into customer select * from t; +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000037 -917.75 +Customer#000000040 1335.3 +Customer#000000047 274.58 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000064 -646.64 +Customer#000000067 8166.59 +Customer#000000077 1738.87 +Customer#000000082 9468.34 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000097 2164.48 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000106 3288.42 +Customer#000000115 7508.92 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000124 1842.49 +Customer#000000127 9280.71 +Customer#000000130 5073.58 +Customer#000000133 2314.67 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +create table r as +select * from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +execute stmt; +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +insert into customer select * from r; +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000037 -917.75 +Customer#000000040 1335.3 +Customer#000000047 274.58 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000064 -646.64 +Customer#000000067 8166.59 +Customer#000000077 1738.87 +Customer#000000082 9468.34 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000097 2164.48 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000106 3288.42 +Customer#000000115 7508.92 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000124 1842.49 +Customer#000000127 9280.71 +Customer#000000130 5073.58 +Customer#000000133 2314.67 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +drop table t,r; +deallocate prepare stmt; +set optimizer_switch='materialization=default'; +# Materialization PS +# ================== +prepare stmt from " +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08') and c_name like ?; +"; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000005 794.47 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000013 3857.34 +Customer#000000014 5266.3 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000032 3471.53 +Customer#000000034 8589.7 +Customer#000000035 1228.24 +Customer#000000037 -917.75 +Customer#000000038 6345.11 +Customer#000000040 1335.3 +Customer#000000041 270.95 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000052 5630.28 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000056 6530.86 +Customer#000000058 6478.46 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000062 595.61 +Customer#000000064 -646.64 +Customer#000000065 8795.16 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000089 1530.76 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000107 2514.15 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000115 7508.92 +Customer#000000116 8403.99 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000128 -986.96 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000140 9963.15 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000145 9748.93 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +set @a1='Customer#%1_'; +create table t as +select * from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08') and c_name like @a1; +execute stmt using @a1; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000005 794.47 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000032 3471.53 +Customer#000000034 8589.7 +Customer#000000035 1228.24 +Customer#000000037 -917.75 +Customer#000000038 6345.11 +Customer#000000040 1335.3 +Customer#000000041 270.95 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000052 5630.28 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000056 6530.86 +Customer#000000058 6478.46 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000062 595.61 +Customer#000000064 -646.64 +Customer#000000065 8795.16 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000089 1530.76 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000107 2514.15 +Customer#000000109 -716.1 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000128 -986.96 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000140 9963.15 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000145 9748.93 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +insert into customer select * from t; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000005 794.47 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000013 3857.34 +Customer#000000014 5266.3 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000032 3471.53 +Customer#000000034 8589.7 +Customer#000000035 1228.24 +Customer#000000037 -917.75 +Customer#000000038 6345.11 +Customer#000000040 1335.3 +Customer#000000041 270.95 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000052 5630.28 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000056 6530.86 +Customer#000000058 6478.46 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000062 595.61 +Customer#000000064 -646.64 +Customer#000000065 8795.16 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000089 1530.76 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000107 2514.15 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000115 7508.92 +Customer#000000116 8403.99 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000128 -986.96 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000140 9963.15 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000145 9748.93 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +set @a2='Customer#%3_'; +create table r as +select * from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08') and c_name like @a2; +execute stmt using @a2; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000005 794.47 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000013 3857.34 +Customer#000000014 5266.3 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000029 7618.27 +Customer#000000040 1335.3 +Customer#000000041 270.95 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000052 5630.28 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000056 6530.86 +Customer#000000058 6478.46 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000062 595.61 +Customer#000000064 -646.64 +Customer#000000065 8795.16 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000089 1530.76 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000107 2514.15 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000115 7508.92 +Customer#000000116 8403.99 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000128 -986.96 +Customer#000000140 9963.15 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000145 9748.93 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +insert into customer select * from r; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000005 794.47 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000013 3857.34 +Customer#000000014 5266.3 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000032 3471.53 +Customer#000000034 8589.7 +Customer#000000035 1228.24 +Customer#000000037 -917.75 +Customer#000000038 6345.11 +Customer#000000040 1335.3 +Customer#000000041 270.95 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000052 5630.28 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000056 6530.86 +Customer#000000058 6478.46 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000062 595.61 +Customer#000000064 -646.64 +Customer#000000065 8795.16 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000089 1530.76 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000107 2514.15 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000115 7508.92 +Customer#000000116 8403.99 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000128 -986.96 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000140 9963.15 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000145 9748.93 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +drop table t,r; +deallocate prepare stmt; +# Materialization SJM PS +# ====================== +prepare stmt from " +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1) and c_acctbal between ? and ?; +"; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3857.34 +Customer#000000032 3471.53 +Customer#000000037 -917.75 +Customer#000000056 6530.86 +Customer#000000118 3582.37 +set @a1=3500; +set @a2=4000; +create table t as +select * from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1) and c_acctbal between @a1 and @a2; +execute stmt using @a1, @a2; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000032 3471.53 +Customer#000000037 -917.75 +Customer#000000056 6530.86 +insert into customer select * from t; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3857.34 +Customer#000000032 3471.53 +Customer#000000037 -917.75 +Customer#000000056 6530.86 +Customer#000000118 3582.37 +set @a3=-1000; +set @a4=3500; +create table r as +select * from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1) and c_acctbal between @a3 and @a4; +execute stmt using @a3, @a4; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3857.34 +Customer#000000056 6530.86 +Customer#000000118 3582.37 +insert into customer select * from r; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3857.34 +Customer#000000032 3471.53 +Customer#000000037 -917.75 +Customer#000000056 6530.86 +Customer#000000118 3582.37 +drop table t,r; +deallocate prepare stmt; +# Pullout SP +# ========== +create procedure p(a1 int, a2 int) +delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')) and o_totalprice between a1 and a2; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +1729 12137.76 +2880 145761.99 +3142 16030.15 +5095 184583.99 +5121 150334.57 +5382 138423.03 +644 201268.06 +737 12984.85 +create table t as +select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')) and o_totalprice between 150000 and 200000; +call p(150000, 200000); +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +1729 12137.76 +2880 145761.99 +3142 16030.15 +5382 138423.03 +644 201268.06 +737 12984.85 +insert into orders select * from t; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +1729 12137.76 +2880 145761.99 +3142 16030.15 +5095 184583.99 +5121 150334.57 +5382 138423.03 +644 201268.06 +737 12984.85 +create table r as +select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')) and o_totalprice between 180000 and 210000; +call p(180000, 210000); +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +1729 12137.76 +2880 145761.99 +3142 16030.15 +5121 150334.57 +5382 138423.03 +737 12984.85 +insert into orders select * from r; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +1729 12137.76 +2880 145761.99 +3142 16030.15 +5095 184583.99 +5121 150334.57 +5382 138423.03 +644 201268.06 +737 12984.85 +drop table t,r; +drop procedure p; +# FirstMatch SP +# ============= +set optimizer_switch='materialization=off'; +create procedure p(a int) +delete from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08') and c_acctbal > a; +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000037 -917.75 +Customer#000000040 1335.3 +Customer#000000047 274.58 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000064 -646.64 +Customer#000000067 8166.59 +Customer#000000077 1738.87 +Customer#000000082 9468.34 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000097 2164.48 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000106 3288.42 +Customer#000000115 7508.92 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000124 1842.49 +Customer#000000127 9280.71 +Customer#000000130 5073.58 +Customer#000000133 2314.67 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +create table t as +select * from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08') and c_acctbal > 4000; +call p(4000); +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000017 6.34 +Customer#000000022 591.98 +Customer#000000028 1007.18 +Customer#000000037 -917.75 +Customer#000000040 1335.3 +Customer#000000047 274.58 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000064 -646.64 +Customer#000000077 1738.87 +Customer#000000092 1182.91 +Customer#000000097 2164.48 +Customer#000000103 2757.45 +Customer#000000106 3288.42 +Customer#000000124 1842.49 +Customer#000000133 2314.67 +Customer#000000142 2209.81 +insert into customer select * from t; +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000037 -917.75 +Customer#000000040 1335.3 +Customer#000000047 274.58 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000064 -646.64 +Customer#000000067 8166.59 +Customer#000000077 1738.87 +Customer#000000082 9468.34 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000097 2164.48 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000106 3288.42 +Customer#000000115 7508.92 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000124 1842.49 +Customer#000000127 9280.71 +Customer#000000130 5073.58 +Customer#000000133 2314.67 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +create table r as +select * from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08') and c_acctbal > 2000; +call p(2000); +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000017 6.34 +Customer#000000022 591.98 +Customer#000000028 1007.18 +Customer#000000037 -917.75 +Customer#000000040 1335.3 +Customer#000000047 274.58 +Customer#000000061 1536.24 +Customer#000000064 -646.64 +Customer#000000077 1738.87 +Customer#000000092 1182.91 +Customer#000000124 1842.49 +insert into customer select * from r; +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000037 -917.75 +Customer#000000040 1335.3 +Customer#000000047 274.58 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000064 -646.64 +Customer#000000067 8166.59 +Customer#000000077 1738.87 +Customer#000000082 9468.34 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000097 2164.48 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000106 3288.42 +Customer#000000115 7508.92 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000124 1842.49 +Customer#000000127 9280.71 +Customer#000000130 5073.58 +Customer#000000133 2314.67 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +drop table t,r; +drop procedure p; +set optimizer_switch='materialization=default'; +# Materialization SP +# ================== +create procedure p() +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000005 794.47 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000013 3857.34 +Customer#000000014 5266.3 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000032 3471.53 +Customer#000000034 8589.7 +Customer#000000035 1228.24 +Customer#000000037 -917.75 +Customer#000000038 6345.11 +Customer#000000040 1335.3 +Customer#000000041 270.95 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000052 5630.28 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000056 6530.86 +Customer#000000058 6478.46 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000062 595.61 +Customer#000000064 -646.64 +Customer#000000065 8795.16 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000089 1530.76 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000107 2514.15 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000115 7508.92 +Customer#000000116 8403.99 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000128 -986.96 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000140 9963.15 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000145 9748.93 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +create table t as +select * from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +call p(); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +insert into customer select * from t; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000005 794.47 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000013 3857.34 +Customer#000000014 5266.3 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000032 3471.53 +Customer#000000034 8589.7 +Customer#000000035 1228.24 +Customer#000000037 -917.75 +Customer#000000038 6345.11 +Customer#000000040 1335.3 +Customer#000000041 270.95 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000052 5630.28 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000056 6530.86 +Customer#000000058 6478.46 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000062 595.61 +Customer#000000064 -646.64 +Customer#000000065 8795.16 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000089 1530.76 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000107 2514.15 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000115 7508.92 +Customer#000000116 8403.99 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000128 -986.96 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000140 9963.15 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000145 9748.93 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +create table r as +select * from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +call p(); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +insert into customer select * from r; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000005 794.47 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000013 3857.34 +Customer#000000014 5266.3 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000032 3471.53 +Customer#000000034 8589.7 +Customer#000000035 1228.24 +Customer#000000037 -917.75 +Customer#000000038 6345.11 +Customer#000000040 1335.3 +Customer#000000041 270.95 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000052 5630.28 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000056 6530.86 +Customer#000000058 6478.46 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000062 595.61 +Customer#000000064 -646.64 +Customer#000000065 8795.16 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000089 1530.76 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000107 2514.15 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000115 7508.92 +Customer#000000116 8403.99 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000128 -986.96 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000140 9963.15 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000145 9748.93 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +drop table t,r; +drop procedure p; +# Materialization SJM SP +# ====================== +create procedure p() +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3857.34 +Customer#000000032 3471.53 +Customer#000000037 -917.75 +Customer#000000056 6530.86 +Customer#000000118 3582.37 +create table t as +select * from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +call p(); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +insert into customer select * from t; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3857.34 +Customer#000000032 3471.53 +Customer#000000037 -917.75 +Customer#000000056 6530.86 +Customer#000000118 3582.37 +create table r as +select * from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +call p(); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +insert into customer select * from r; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3857.34 +Customer#000000032 3471.53 +Customer#000000037 -917.75 +Customer#000000056 6530.86 +Customer#000000118 3582.37 +drop table t,r; +drop procedure p; +# Checking limitations +# ==================== +# Check for DELETE ... RETURNING with SJ subquery in WHERE +select c_name from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name +Customer#000000001 +Customer#000000002 +Customer#000000005 +Customer#000000007 +Customer#000000008 +Customer#000000010 +Customer#000000011 +Customer#000000013 +Customer#000000014 +Customer#000000016 +Customer#000000017 +Customer#000000019 +Customer#000000022 +Customer#000000023 +Customer#000000025 +Customer#000000028 +Customer#000000029 +Customer#000000031 +Customer#000000032 +Customer#000000034 +Customer#000000035 +Customer#000000037 +Customer#000000038 +Customer#000000040 +Customer#000000041 +Customer#000000043 +Customer#000000044 +Customer#000000046 +Customer#000000047 +Customer#000000049 +Customer#000000052 +Customer#000000053 +Customer#000000055 +Customer#000000056 +Customer#000000058 +Customer#000000059 +Customer#000000061 +Customer#000000062 +Customer#000000064 +Customer#000000065 +Customer#000000067 +Customer#000000070 +Customer#000000071 +Customer#000000073 +Customer#000000074 +Customer#000000076 +Customer#000000079 +Customer#000000080 +Customer#000000082 +Customer#000000083 +Customer#000000085 +Customer#000000086 +Customer#000000088 +Customer#000000089 +Customer#000000091 +Customer#000000092 +Customer#000000094 +Customer#000000095 +Customer#000000097 +Customer#000000098 +Customer#000000100 +Customer#000000101 +Customer#000000103 +Customer#000000104 +Customer#000000106 +Customer#000000107 +Customer#000000109 +Customer#000000110 +Customer#000000112 +Customer#000000115 +Customer#000000116 +Customer#000000118 +Customer#000000121 +Customer#000000122 +Customer#000000127 +Customer#000000128 +Customer#000000130 +Customer#000000131 +Customer#000000133 +Customer#000000134 +Customer#000000136 +Customer#000000137 +Customer#000000139 +Customer#000000140 +Customer#000000142 +Customer#000000143 +Customer#000000145 +Customer#000000148 +Customer#000000149 +create table t as +select * from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +explain +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08') returning c_name; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY customer ALL NULL NULL NULL NULL 150 Using where +2 DEPENDENT SUBQUERY orders index_subquery i_o_orderdate,i_o_custkey i_o_custkey 5 func 15 Using where +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08') returning c_name; +c_name +Customer#000000001 +Customer#000000002 +Customer#000000005 +Customer#000000007 +Customer#000000008 +Customer#000000010 +Customer#000000011 +Customer#000000013 +Customer#000000014 +Customer#000000016 +Customer#000000017 +Customer#000000019 +Customer#000000022 +Customer#000000023 +Customer#000000025 +Customer#000000028 +Customer#000000029 +Customer#000000031 +Customer#000000032 +Customer#000000034 +Customer#000000035 +Customer#000000037 +Customer#000000038 +Customer#000000040 +Customer#000000041 +Customer#000000043 +Customer#000000044 +Customer#000000046 +Customer#000000047 +Customer#000000049 +Customer#000000052 +Customer#000000053 +Customer#000000055 +Customer#000000056 +Customer#000000058 +Customer#000000059 +Customer#000000061 +Customer#000000062 +Customer#000000064 +Customer#000000065 +Customer#000000067 +Customer#000000070 +Customer#000000071 +Customer#000000073 +Customer#000000074 +Customer#000000076 +Customer#000000079 +Customer#000000080 +Customer#000000082 +Customer#000000083 +Customer#000000085 +Customer#000000086 +Customer#000000088 +Customer#000000089 +Customer#000000091 +Customer#000000092 +Customer#000000094 +Customer#000000095 +Customer#000000097 +Customer#000000098 +Customer#000000100 +Customer#000000101 +Customer#000000103 +Customer#000000104 +Customer#000000106 +Customer#000000107 +Customer#000000109 +Customer#000000110 +Customer#000000112 +Customer#000000115 +Customer#000000116 +Customer#000000118 +Customer#000000121 +Customer#000000122 +Customer#000000127 +Customer#000000128 +Customer#000000130 +Customer#000000131 +Customer#000000133 +Customer#000000134 +Customer#000000136 +Customer#000000137 +Customer#000000139 +Customer#000000140 +Customer#000000142 +Customer#000000143 +Customer#000000145 +Customer#000000148 +Customer#000000149 +select c_name from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name +insert into customer select * from t; +select c_name from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name +Customer#000000001 +Customer#000000002 +Customer#000000005 +Customer#000000007 +Customer#000000008 +Customer#000000010 +Customer#000000011 +Customer#000000013 +Customer#000000014 +Customer#000000016 +Customer#000000017 +Customer#000000019 +Customer#000000022 +Customer#000000023 +Customer#000000025 +Customer#000000028 +Customer#000000029 +Customer#000000031 +Customer#000000032 +Customer#000000034 +Customer#000000035 +Customer#000000037 +Customer#000000038 +Customer#000000040 +Customer#000000041 +Customer#000000043 +Customer#000000044 +Customer#000000046 +Customer#000000047 +Customer#000000049 +Customer#000000052 +Customer#000000053 +Customer#000000055 +Customer#000000056 +Customer#000000058 +Customer#000000059 +Customer#000000061 +Customer#000000062 +Customer#000000064 +Customer#000000065 +Customer#000000067 +Customer#000000070 +Customer#000000071 +Customer#000000073 +Customer#000000074 +Customer#000000076 +Customer#000000079 +Customer#000000080 +Customer#000000082 +Customer#000000083 +Customer#000000085 +Customer#000000086 +Customer#000000088 +Customer#000000089 +Customer#000000091 +Customer#000000092 +Customer#000000094 +Customer#000000095 +Customer#000000097 +Customer#000000098 +Customer#000000100 +Customer#000000101 +Customer#000000103 +Customer#000000104 +Customer#000000106 +Customer#000000107 +Customer#000000109 +Customer#000000110 +Customer#000000112 +Customer#000000115 +Customer#000000116 +Customer#000000118 +Customer#000000121 +Customer#000000122 +Customer#000000127 +Customer#000000128 +Customer#000000130 +Customer#000000131 +Customer#000000133 +Customer#000000134 +Customer#000000136 +Customer#000000137 +Customer#000000139 +Customer#000000140 +Customer#000000142 +Customer#000000143 +Customer#000000145 +Customer#000000148 +Customer#000000149 +drop table t; +select c_name from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name +Customer#000000013 +Customer#000000032 +Customer#000000037 +Customer#000000056 +Customer#000000118 +create table t as +select * from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +explain +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1) returning c_name; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY customer ALL NULL NULL NULL NULL 150 Using where +2 DEPENDENT SUBQUERY orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary +delete from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1) returning c_name; +c_name +Customer#000000013 +Customer#000000032 +Customer#000000037 +Customer#000000056 +Customer#000000118 +select c_name from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name +insert into customer select * from t; +select c_name from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name +Customer#000000013 +Customer#000000032 +Customer#000000037 +Customer#000000056 +Customer#000000118 +drop table t; +# Check for DELETE ... ORDER BY ...LIMIT with SJ subquery in WHERE +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +o_orderkey o_totalprice +1221 117397.16 +1344 43809.37 +1856 189361.42 +1925 146382.71 +3139 40975.96 +324 26868.85 +4903 34363.63 +5607 24660.06 +# Should not use semi-join conversion because has ORDER BY ... LIMIT +explain +delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)) +order by o_totalprice limit 500; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY orders range i_o_orderdate i_o_orderdate 4 NULL 108 Using where; Using filesort +2 DEPENDENT SUBQUERY customer unique_subquery PRIMARY,i_c_nationkey PRIMARY 4 func 1 Using where +create table t as +select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +select o_orderkey, o_totalprice from t; +o_orderkey o_totalprice +1221 117397.16 +324 26868.85 +1856 189361.42 +4903 34363.63 +5607 24660.06 +1344 43809.37 +1925 146382.71 +3139 40975.96 +delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)) +order by o_totalprice limit 500; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +o_orderkey o_totalprice +insert into orders select * from t; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +o_orderkey o_totalprice +1221 117397.16 +1344 43809.37 +1856 189361.42 +1925 146382.71 +3139 40975.96 +324 26868.85 +4903 34363.63 +5607 24660.06 +drop table t; +# Should use semi-join converion +explain +delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY customer range PRIMARY,i_c_nationkey i_c_nationkey 5 NULL 13 Using index condition +1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (7%) Using where; Using rowid filter +create table t as +select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +select o_orderkey, o_totalprice from t; +o_orderkey o_totalprice +1221 117397.16 +324 26868.85 +1856 189361.42 +4903 34363.63 +5607 24660.06 +1344 43809.37 +1925 146382.71 +3139 40975.96 +delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +o_orderkey o_totalprice +insert into orders select * from t; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +o_orderkey o_totalprice +1221 117397.16 +1344 43809.37 +1856 189361.42 +1925 146382.71 +3139 40975.96 +324 26868.85 +4903 34363.63 +5607 24660.06 +drop table t; +CREATE TABLE partsupp_small ( +ps_partkey int(11) NOT NULL DEFAULT '0', +ps_suppkey int(11) NOT NULL DEFAULT '0', +ps_availqty int(11) DEFAULT NULL, +ps_supplycost double DEFAULT NULL, +ps_comment varchar(199) DEFAULT NULL, +PRIMARY KEY (ps_partkey,ps_suppkey), +KEY i_ps_partkey (ps_partkey), +KEY i_ps_suppkey (ps_suppkey) +); +create index i_ps_sup_part on partsupp_small(ps_suppkey, ps_partkey); +insert into partsupp_small select * from partsupp where ps_partkey <50; +analyze table partsupp_small persistent for all; +Table Op Msg_type Msg_text +dbt3_s001.partsupp_small analyze status Engine-independent statistics collected +dbt3_s001.partsupp_small analyze status OK +# LooseScan +# ========= +explain +select count(*) from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY partsupp_small index PRIMARY,i_ps_partkey,i_ps_suppkey,i_ps_sup_part PRIMARY 8 NULL 176 Using where; Using index; LooseScan +1 PRIMARY lineitem ref i_l_suppkey_partkey,i_l_partkey i_l_partkey 5 dbt3_s001.partsupp_small.ps_partkey 30 Using index +explain format=json +select count(*) from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.222764041, + "nested_loop": [ + { + "table": { + "table_name": "partsupp_small", + "access_type": "index", + "possible_keys": [ + "PRIMARY", + "i_ps_partkey", + "i_ps_suppkey", + "i_ps_sup_part" + ], + "key": "PRIMARY", + "key_length": "8", + "used_key_parts": ["ps_partkey", "ps_suppkey"], + "loops": 1, + "rows": 176, + "cost": 0.019403477, + "filtered": 23.86363602, + "attached_condition": "partsupp_small.ps_suppkey in (1,2,3)", + "using_index": true, + "loose_scan": true + } + }, + { + "table": { + "table_name": "lineitem", + "access_type": "ref", + "possible_keys": ["i_l_suppkey_partkey", "i_l_partkey"], + "key": "i_l_partkey", + "key_length": "5", + "used_key_parts": ["l_partkey"], + "ref": ["dbt3_s001.partsupp_small.ps_partkey"], + "loops": 42, + "rows": 30, + "cost": 0.203360564, + "filtered": 2.380952358, + "using_index": true + } + } + ] + } +} +explain +select l_partkey from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY partsupp_small index PRIMARY,i_ps_partkey,i_ps_suppkey,i_ps_sup_part PRIMARY 8 NULL 176 Using where; Using index; LooseScan +1 PRIMARY lineitem ref i_l_suppkey_partkey,i_l_partkey i_l_partkey 5 dbt3_s001.partsupp_small.ps_partkey 30 Using index +explain format=json +select l_partkey from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.222764041, + "nested_loop": [ + { + "table": { + "table_name": "partsupp_small", + "access_type": "index", + "possible_keys": [ + "PRIMARY", + "i_ps_partkey", + "i_ps_suppkey", + "i_ps_sup_part" + ], + "key": "PRIMARY", + "key_length": "8", + "used_key_parts": ["ps_partkey", "ps_suppkey"], + "loops": 1, + "rows": 176, + "cost": 0.019403477, + "filtered": 23.86363602, + "attached_condition": "partsupp_small.ps_suppkey in (1,2,3)", + "using_index": true, + "loose_scan": true + } + }, + { + "table": { + "table_name": "lineitem", + "access_type": "ref", + "possible_keys": ["i_l_suppkey_partkey", "i_l_partkey"], + "key": "i_l_partkey", + "key_length": "5", + "used_key_parts": ["l_partkey"], + "ref": ["dbt3_s001.partsupp_small.ps_partkey"], + "loops": 42, + "rows": 30, + "cost": 0.203360564, + "filtered": 2.380952358, + "using_index": true + } + } + ] + } +} +select count(*) from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +count(*) +1175 +create table t as +select * from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +explain +delete from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY partsupp_small index PRIMARY,i_ps_partkey,i_ps_suppkey,i_ps_sup_part PRIMARY 8 NULL 176 Using where; Using index; LooseScan +1 PRIMARY lineitem ref i_l_suppkey_partkey,i_l_partkey i_l_partkey 5 dbt3_s001.partsupp_small.ps_partkey 30 +explain format=json +delete from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.222764041, + "nested_loop": [ + { + "table": { + "table_name": "partsupp_small", + "access_type": "index", + "possible_keys": [ + "PRIMARY", + "i_ps_partkey", + "i_ps_suppkey", + "i_ps_sup_part" + ], + "key": "PRIMARY", + "key_length": "8", + "used_key_parts": ["ps_partkey", "ps_suppkey"], + "loops": 1, + "rows": 176, + "cost": 0.019403477, + "filtered": 23.86363602, + "attached_condition": "partsupp_small.ps_suppkey in (1,2,3)", + "using_index": true, + "loose_scan": true + } + }, + { + "table": { + "table_name": "lineitem", + "access_type": "ref", + "possible_keys": ["i_l_suppkey_partkey", "i_l_partkey"], + "key": "i_l_partkey", + "key_length": "5", + "used_key_parts": ["l_partkey"], + "ref": ["dbt3_s001.partsupp_small.ps_partkey"], + "loops": 42, + "rows": 30, + "cost": 0.203360564, + "filtered": 2.380952358 + } + } + ] + } +} +delete from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +select count(*) from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +count(*) +0 +insert into lineitem select * from t; +select count(*) from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +count(*) +1175 +drop table t; +# LooseScan PS +# ============ +prepare stmt from " +delete from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +"; +select count(*) from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +count(*) +1175 +create table t as +select * from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +execute stmt; +select count(*) from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +count(*) +0 +insert into lineitem select * from t; +select count(*) from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +count(*) +1175 +create table r as +select * from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +execute stmt; +select count(*) from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +count(*) +0 +insert into lineitem select * from r; +select count(*) from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +count(*) +1175 +drop tables r, t; +deallocate prepare stmt; +# LooseScan SP +# ============ +create procedure p() +delete from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +select count(*) from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +count(*) +1175 +create table t as +select * from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +call p(); +select count(*) from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +count(*) +0 +insert into lineitem select * from t; +select count(*) from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +count(*) +1175 +create table r as +select * from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +call p(); +select count(*) from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +count(*) +0 +insert into lineitem select * from r; +select count(*) from lineitem where l_partkey in +(select ps_partkey from partsupp_small +where ps_suppkey in (1,2,3)); +count(*) +1175 +drop tables r, t; +drop procedure p; +# DuplicateWeedout +# ================ +set @tmp_optimizer_switch= @@optimizer_switch; +set optimizer_switch='materialization=off'; +analyze table lineitem; +Table Op Msg_type Msg_text +dbt3_s001.lineitem analyze status Engine-independent statistics collected +dbt3_s001.lineitem analyze status OK +analyze table orders; +Table Op Msg_type Msg_text +dbt3_s001.orders analyze status Engine-independent statistics collected +dbt3_s001.orders analyze status OK +explain +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY supplier range PRIMARY PRIMARY 4 NULL 1 Using where; Using index; Start temporary +1 PRIMARY partsupp_small ref PRIMARY,i_ps_partkey,i_ps_suppkey,i_ps_sup_part i_ps_sup_part 4 dbt3_s001.supplier.s_suppkey 17 Using where; Using index +1 PRIMARY lineitem ref i_l_suppkey_partkey,i_l_partkey i_l_suppkey_partkey 5 dbt3_s001.partsupp_small.ps_partkey 30 Using index +1 PRIMARY lineitem ref i_l_suppkey_partkey,i_l_partkey i_l_partkey 5 dbt3_s001.partsupp_small.ps_partkey 30 Using index; End temporary +explain format=json +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 4.129940741, + "nested_loop": [ + { + "duplicates_removal": [ + { + "table": { + "table_name": "supplier", + "access_type": "range", + "possible_keys": ["PRIMARY"], + "key": "PRIMARY", + "key_length": "4", + "used_key_parts": ["s_suppkey"], + "loops": 1, + "rows": 1, + "cost": 0.001478954, + "filtered": 100, + "attached_condition": "supplier.s_suppkey < 2", + "using_index": true + } + }, + { + "table": { + "table_name": "partsupp_small", + "access_type": "ref", + "possible_keys": [ + "PRIMARY", + "i_ps_partkey", + "i_ps_suppkey", + "i_ps_sup_part" + ], + "key": "i_ps_sup_part", + "key_length": "4", + "used_key_parts": ["ps_suppkey"], + "ref": ["dbt3_s001.supplier.s_suppkey"], + "loops": 1, + "rows": 17, + "cost": 0.003160332, + "filtered": 79.54545593, + "attached_condition": "partsupp_small.ps_partkey is not null", + "using_index": true + } + }, + { + "table": { + "table_name": "lineitem", + "access_type": "ref", + "possible_keys": ["i_l_suppkey_partkey", "i_l_partkey"], + "key": "i_l_suppkey_partkey", + "key_length": "5", + "used_key_parts": ["l_partkey"], + "ref": ["dbt3_s001.partsupp_small.ps_partkey"], + "loops": 14, + "rows": 30, + "cost": 0.069152188, + "filtered": 100, + "using_index": true + } + }, + { + "table": { + "table_name": "lineitem", + "access_type": "ref", + "possible_keys": ["i_l_suppkey_partkey", "i_l_partkey"], + "key": "i_l_partkey", + "key_length": "5", + "used_key_parts": ["l_partkey"], + "ref": ["dbt3_s001.partsupp_small.ps_partkey"], + "loops": 420.35, + "rows": 30, + "cost": 1.994712365, + "filtered": 0.237896994, + "using_index": true + } + } + ] + } + ] + } +} +explain +select l_partkey from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY supplier range PRIMARY PRIMARY 4 NULL 1 Using where; Using index; Start temporary +1 PRIMARY partsupp_small ref PRIMARY,i_ps_partkey,i_ps_suppkey,i_ps_sup_part i_ps_sup_part 4 dbt3_s001.supplier.s_suppkey 17 Using where; Using index +1 PRIMARY lineitem ref i_l_suppkey_partkey,i_l_partkey i_l_suppkey_partkey 5 dbt3_s001.partsupp_small.ps_partkey 30 Using index +1 PRIMARY lineitem ref i_l_suppkey_partkey,i_l_partkey i_l_partkey 5 dbt3_s001.partsupp_small.ps_partkey 30 Using index; End temporary +explain format=json +select l_partkey from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 4.129940741, + "nested_loop": [ + { + "duplicates_removal": [ + { + "table": { + "table_name": "supplier", + "access_type": "range", + "possible_keys": ["PRIMARY"], + "key": "PRIMARY", + "key_length": "4", + "used_key_parts": ["s_suppkey"], + "loops": 1, + "rows": 1, + "cost": 0.001478954, + "filtered": 100, + "attached_condition": "supplier.s_suppkey < 2", + "using_index": true + } + }, + { + "table": { + "table_name": "partsupp_small", + "access_type": "ref", + "possible_keys": [ + "PRIMARY", + "i_ps_partkey", + "i_ps_suppkey", + "i_ps_sup_part" + ], + "key": "i_ps_sup_part", + "key_length": "4", + "used_key_parts": ["ps_suppkey"], + "ref": ["dbt3_s001.supplier.s_suppkey"], + "loops": 1, + "rows": 17, + "cost": 0.003160332, + "filtered": 79.54545593, + "attached_condition": "partsupp_small.ps_partkey is not null", + "using_index": true + } + }, + { + "table": { + "table_name": "lineitem", + "access_type": "ref", + "possible_keys": ["i_l_suppkey_partkey", "i_l_partkey"], + "key": "i_l_suppkey_partkey", + "key_length": "5", + "used_key_parts": ["l_partkey"], + "ref": ["dbt3_s001.partsupp_small.ps_partkey"], + "loops": 14, + "rows": 30, + "cost": 0.069152188, + "filtered": 100, + "using_index": true + } + }, + { + "table": { + "table_name": "lineitem", + "access_type": "ref", + "possible_keys": ["i_l_suppkey_partkey", "i_l_partkey"], + "key": "i_l_partkey", + "key_length": "5", + "used_key_parts": ["l_partkey"], + "ref": ["dbt3_s001.partsupp_small.ps_partkey"], + "loops": 420.35, + "rows": 30, + "cost": 1.994712365, + "filtered": 0.237896994, + "using_index": true + } + } + ] + } + ] + } +} +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +count(*) +471 +create table t as +select * from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +explain +delete from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY supplier range PRIMARY PRIMARY 4 NULL 1 Using where; Using index; Start temporary +1 PRIMARY partsupp_small ref PRIMARY,i_ps_partkey,i_ps_suppkey,i_ps_sup_part i_ps_sup_part 4 dbt3_s001.supplier.s_suppkey 17 Using where; Using index +1 PRIMARY lineitem ref i_l_suppkey_partkey,i_l_partkey i_l_suppkey_partkey 5 dbt3_s001.partsupp_small.ps_partkey 30 +1 PRIMARY lineitem ref i_l_suppkey_partkey,i_l_partkey i_l_partkey 5 dbt3_s001.partsupp_small.ps_partkey 30 Using index; End temporary +explain format=json +delete from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 4.129940741, + "nested_loop": [ + { + "duplicates_removal": [ + { + "table": { + "table_name": "supplier", + "access_type": "range", + "possible_keys": ["PRIMARY"], + "key": "PRIMARY", + "key_length": "4", + "used_key_parts": ["s_suppkey"], + "loops": 1, + "rows": 1, + "cost": 0.001478954, + "filtered": 100, + "attached_condition": "supplier.s_suppkey < 2", + "using_index": true + } + }, + { + "table": { + "table_name": "partsupp_small", + "access_type": "ref", + "possible_keys": [ + "PRIMARY", + "i_ps_partkey", + "i_ps_suppkey", + "i_ps_sup_part" + ], + "key": "i_ps_sup_part", + "key_length": "4", + "used_key_parts": ["ps_suppkey"], + "ref": ["dbt3_s001.supplier.s_suppkey"], + "loops": 1, + "rows": 17, + "cost": 0.003160332, + "filtered": 79.54545593, + "attached_condition": "partsupp_small.ps_partkey is not null", + "using_index": true + } + }, + { + "table": { + "table_name": "lineitem", + "access_type": "ref", + "possible_keys": ["i_l_suppkey_partkey", "i_l_partkey"], + "key": "i_l_suppkey_partkey", + "key_length": "5", + "used_key_parts": ["l_partkey"], + "ref": ["dbt3_s001.partsupp_small.ps_partkey"], + "loops": 14, + "rows": 30, + "cost": 0.069152188, + "filtered": 100 + } + }, + { + "table": { + "table_name": "lineitem", + "access_type": "ref", + "possible_keys": ["i_l_suppkey_partkey", "i_l_partkey"], + "key": "i_l_partkey", + "key_length": "5", + "used_key_parts": ["l_partkey"], + "ref": ["dbt3_s001.partsupp_small.ps_partkey"], + "loops": 420.35, + "rows": 30, + "cost": 1.994712365, + "filtered": 0.237896994, + "using_index": true + } + } + ] + } + ] + } +} +delete from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +count(*) +0 +insert into lineitem select * from t; +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +count(*) +471 +drop table t; +# DuplicateWeedout PS +# =================== +prepare stmt from " +delete from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +"; +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +count(*) +471 +create table t as +select * from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +execute stmt; +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +count(*) +0 +insert into lineitem select * from t; +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +count(*) +471 +create table r as +select * from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +execute stmt; +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +count(*) +0 +insert into lineitem select * from r; +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +count(*) +471 +drop tables r, t; +deallocate prepare stmt; +# DuplicateWeedout SP +# =================== +create procedure p() +delete from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +count(*) +471 +create table t as +select * from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +call p(); +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +count(*) +0 +insert into lineitem select * from t; +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +count(*) +471 +create table r as +select * from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +call p(); +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +count(*) +0 +insert into lineitem select * from r; +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +count(*) +471 +drop tables r, t; +drop procedure p; +set @@optimizer_switch=@tmp_optimizer_switch; +drop table partsupp_small; +DROP DATABASE dbt3_s001; diff --git a/mysql-test/main/delete_single_to_multi.test b/mysql-test/main/delete_single_to_multi.test new file mode 100644 index 00000000000..31f1d157096 --- /dev/null +++ b/mysql-test/main/delete_single_to_multi.test @@ -0,0 +1,1069 @@ +--disable_warnings +DROP DATABASE IF EXISTS dbt3_s001; +--enable_warnings + +CREATE DATABASE dbt3_s001; + +use dbt3_s001; + +--disable_query_log +--disable_result_log +--disable_warnings +--source include/dbt3_s001.inc +--enable_warnings +--enable_result_log +--enable_query_log + +create index i_n_name on nation(n_name); +analyze table + nation, lineitem, customer, orders, part, supplier, partsupp, region +persistent for all; + + +--echo # Pullout +--echo # ======= + +let $c1= + o_orderDATE between '1992-01-01' and '1992-06-30' and + o_custkey in (select c_custkey from customer + where c_nationkey in (select n_nationkey from nation + where n_name='PERU')); + +eval +explain +select o_orderkey, o_totalprice from orders where $c1; +eval +explain format=json +select o_orderkey, o_totalprice from orders where $c1; +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c1; +eval +create table t as +select * from orders where $c1; + +eval +explain +delete from orders where $c1; +eval +explain format=json +delete from orders where $c1; +eval +delete from orders where $c1; +eval +select o_orderkey, o_totalprice from orders where $c1; + + +insert into orders select * from t; +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c1; +drop table t; + + +let $c2= + (ps_partkey, ps_suppkey) in + (select p_partkey, s_suppkey from part, supplier + where p_retailprice between 901 and 910 and + s_nationkey in (select n_nationkey from nation + where n_name='PERU')); + +eval +explain +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2; +--sorted_result +eval +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2; +eval +create table t as +select * from partsupp where $c2; + +eval +explain +delete from partsupp where $c2; +eval +delete from partsupp where $c2; +eval +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2; + +insert into partsupp select * from t; +--sorted_result +eval +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2; +drop table t; + + +let $c3= + ps_partkey in (select p_partkey from part + where p_retailprice between 901 and 910) and + ps_suppkey in (select s_suppkey from supplier + where s_nationkey in (select n_nationkey from nation + where n_name='PERU')); +eval +explain +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3; +--sorted_result +eval +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3; +eval +create table t as +select * from partsupp where $c3; + +eval +explain +delete from partsupp where $c3; +eval +delete from partsupp where $c3; +eval +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3; + +insert into partsupp select * from t; +--sorted_result +eval +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3; +drop table t; + + +let $c4= + l_orderkey in (select o_orderkey from orders + where o_custkey in + (select c_custkey from customer + where c_nationkey in + (select n_nationkey from nation + where n_name='PERU')) + and + o_orderDATE between '1992-06-30' and '1992-12-31') + and + (l_partkey, l_suppkey) in + (select p_partkey, s_suppkey from part, supplier + where p_retailprice between 901 and 1000 and + s_nationkey in (select n_nationkey from nation + where n_name='PERU')); + +eval +explain +select l_orderkey, l_linenumber, l_tax from lineitem where $c4; +--sorted_result +eval +select l_orderkey, l_linenumber, l_tax from lineitem where $c4; +eval +create table t as +select * from lineitem where $c4; + +eval +explain +delete from lineitem where $c4; +eval +delete from lineitem where $c4; +eval +select l_orderkey, l_linenumber, l_tax from lineitem where $c4; + +insert into lineitem select * from t; +--sorted_result +eval +select l_orderkey, l_linenumber, l_tax from lineitem where $c4; +drop table t; + + +--echo # FirstMatch +--echo # ========== + +set optimizer_switch='materialization=off'; + +let $c5= + c_nationkey in (select n_nationkey from nation + where n_regionkey in (1,2)) + and + c_custkey in (select o_custkey from orders + where o_orderDATE between '1992-10-09' and '1993-06-08'); + +eval +explain +select c_name, c_acctbal from customer where $c5; +eval +explain format=json +select c_name, c_acctbal from customer where $c5; +--sorted_result +eval +select c_name, c_acctbal from customer where $c5; +eval +create table t as +select * from customer where $c5; + +eval +explain +delete from customer where $c5; +eval +explain format=json +delete from customer where $c5; +eval +delete from customer where $c5; +eval +select c_name, c_acctbal from customer where $c5; + +insert into customer select * from t; +--sorted_result +eval +select c_name, c_acctbal from customer where $c5; +drop table t; + +set optimizer_switch='materialization=default'; + + +let $c6= + c_nationkey in (select n_nationkey from nation where n_name='PERU') + and + c_custkey in (select o_custkey from orders + where o_orderDATE between "1992-01-09" and "1993-01-08"); + +eval +explain +select c_name, c_acctbal from customer where $c6; +--sorted_result +eval +select c_name, c_acctbal from customer where $c6; +eval +create table t as +select * from customer where $c6; + +eval +explain +delete from customer where $c6; +eval +delete from customer where $c6; +eval +select c_name, c_acctbal from customer where $c6; + +insert into customer select * from t; +--sorted_result +eval +select c_name, c_acctbal from customer where $c6; +drop table t; + + +--echo # Materialization +--echo # =============== + +set optimizer_switch='firstmatch=off'; + +let $c7= + c_nationkey in (select n_nationkey from nation where + n_name in ('JAPAN', 'INDONESIA', 'PERU', 'ARGENTINA')) + and + c_custkey in (select o_custkey from orders + where o_orderDATE between "1992-01-09" and "1995-01-08"); + +eval +explain +select c_name, c_acctbal from customer where $c7; +--sorted_result +eval +select c_name, c_acctbal from customer where $c7; +eval +create table t as +select * from customer where $c7; + +eval +explain +delete from customer where $c7; +eval +delete from customer where $c7; +eval +select c_name, c_acctbal from customer where $c7; + +insert into customer select * from t; +--sorted_result +eval +select c_name, c_acctbal from customer where $c7; +drop table t; + +set optimizer_switch='firstmatch=default'; + +let $c8= + c_custkey in (select o_custkey from orders + where o_orderDATE between '1992-01-09' and '1993-03-08'); + +eval +explain +select c_name, c_acctbal from customer where $c8; +eval +explain format=json +select c_name, c_acctbal from customer where $c8; +--sorted_result +eval +select c_name, c_acctbal from customer where $c8; +eval +create table t as +select * from customer where $c8; + +eval +explain +delete from customer where $c8; +eval +explain format=json +delete from customer where $c8; +eval +delete from customer where $c8; +eval +select c_name, c_acctbal from customer where $c8; + +insert into customer select * from t; +--sorted_result +eval +select c_name, c_acctbal from customer where $c8; +drop table t; + + +let $c9= + c_custkey in (select o_custkey from orders + where o_orderDATE between '1992-06-09' and '1993-01-08'); + +eval +explain +select c_name, c_acctbal from customer where $c9; +--sorted_result +eval +select c_name, c_acctbal from customer where $c9; +eval +create table t as +select * from customer where $c9; + +eval +explain +delete from customer where $c9; +eval +delete from customer where $c9; +eval +select c_name, c_acctbal from customer where $c9; + +insert into customer select * from t; +--sorted_result +eval +select c_name, c_acctbal from customer where $c9; +drop table t; + + +--echo # Materialization SJM +--echo # =================== + +let $c10= + c_custkey in (select o_custkey from orders + where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); + +eval +explain +select c_name, c_acctbal from customer where $c10; +eval +explain format=json +select c_name, c_acctbal from customer where $c10; +--sorted_result +eval +select c_name, c_acctbal from customer where $c10; +eval +create table t as +select * from customer where $c10; + +eval +explain +delete from customer where $c10; +eval +explain format=json +delete from customer where $c10; +eval +delete from customer where $c10; +eval +select c_name, c_acctbal from customer where $c10; + +insert into customer select * from t; +--sorted_result +eval +select c_name, c_acctbal from customer where $c10; +drop table t; + + +let $c11= + c_custkey in (select o_custkey from orders + where o_orderDATE between '1992-01-09' and '1993-03-08' + group by o_custkey having count(o_custkey) > 5); + +eval +explain +select c_name, c_acctbal from customer where $c11; +--sorted_result +eval +select c_name, c_acctbal from customer where $c11; +eval +create table t as +select * from customer where $c11; + +eval +explain +delete from customer where $c11; +eval +delete from customer where $c11; +eval +select c_name, c_acctbal from customer where $c11; + +insert into customer select * from t; +--sorted_result +eval +select c_name, c_acctbal from customer where $c11; +drop table t; + + +--echo # Pullout PS +--echo # ========== + +eval +prepare stmt from " +delete from orders where $c1; +"; + +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c1; +eval +create table t as +select * from orders where $c1; +execute stmt; +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c1; +insert into orders select * from t; +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c1; +eval +create table r as +select * from orders where $c1; +execute stmt; +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c1; +insert into orders select * from r; +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c1; +drop table t,r; + +deallocate prepare stmt; + + +--echo # FirstMatch PS +--echo # ============= + +set optimizer_switch='materialization=off'; + +eval +prepare stmt from " +delete from customer where $c5; +"; + +--sorted_result +eval +select c_name, c_acctbal from customer where $c5; +eval +create table t as +select * from customer where $c5; +execute stmt; +--sorted_result +eval +select c_name, c_acctbal from customer where $c5; +insert into customer select * from t; +--sorted_result +eval +select c_name, c_acctbal from customer where $c5; +eval +create table r as +select * from customer where $c5; +execute stmt; +--sorted_result +eval +select c_name, c_acctbal from customer where $c5; +insert into customer select * from r; +--sorted_result +eval +select c_name, c_acctbal from customer where $c5; +drop table t,r; + +deallocate prepare stmt; + +set optimizer_switch='materialization=default'; + +--echo # Materialization PS +--echo # ================== + +eval +prepare stmt from " +delete from customer where $c8 and c_name like ?; +"; + +--sorted_result +eval +select c_name, c_acctbal from customer where $c8; +set @a1='Customer#%1_'; +eval +create table t as +select * from customer where $c8 and c_name like @a1; +execute stmt using @a1; +--sorted_result +eval +select c_name, c_acctbal from customer where $c8; +insert into customer select * from t; +--sorted_result +eval +select c_name, c_acctbal from customer where $c8; +set @a2='Customer#%3_'; +eval +create table r as +select * from customer where $c8 and c_name like @a2; +execute stmt using @a2; +--sorted_result +eval +select c_name, c_acctbal from customer where $c8; +insert into customer select * from r; +--sorted_result +eval +select c_name, c_acctbal from customer where $c8; +drop table t,r; + +deallocate prepare stmt; + + +--echo # Materialization SJM PS +--echo # ====================== + +eval +prepare stmt from " +delete from customer where $c10 and c_acctbal between ? and ?; +"; + +--sorted_result +eval +select c_name, c_acctbal from customer where $c10; +set @a1=3500; +set @a2=4000; +eval +create table t as +select * from customer where $c10 and c_acctbal between @a1 and @a2; +execute stmt using @a1, @a2; +--sorted_result +eval +select c_name, c_acctbal from customer where $c10; +insert into customer select * from t; +--sorted_result +eval +select c_name, c_acctbal from customer where $c10; +set @a3=-1000; +set @a4=3500; +eval +create table r as +select * from customer where $c10 and c_acctbal between @a3 and @a4; +execute stmt using @a3, @a4; +--sorted_result +eval +select c_name, c_acctbal from customer where $c10; +insert into customer select * from r; +--sorted_result +eval +select c_name, c_acctbal from customer where $c10; +drop table t,r; + +deallocate prepare stmt; + + +--echo # Pullout SP +--echo # ========== + +eval +create procedure p(a1 int, a2 int) +delete from orders where $c1 and o_totalprice between a1 and a2; + +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c1; +eval +create table t as +select * from orders where $c1 and o_totalprice between 150000 and 200000; +call p(150000, 200000); +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c1; +insert into orders select * from t; +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c1; +eval +create table r as +select * from orders where $c1 and o_totalprice between 180000 and 210000; +call p(180000, 210000); +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c1; +insert into orders select * from r; +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c1; +drop table t,r; + +drop procedure p; + + +--echo # FirstMatch SP +--echo # ============= + +set optimizer_switch='materialization=off'; + +eval +create procedure p(a int) +delete from customer where $c5 and c_acctbal > a; + +--sorted_result +eval +select c_name, c_acctbal from customer where $c5; +eval +create table t as +select * from customer where $c5 and c_acctbal > 4000; +call p(4000); +--sorted_result +eval +select c_name, c_acctbal from customer where $c5; +insert into customer select * from t; +--sorted_result +eval +select c_name, c_acctbal from customer where $c5; +eval +create table r as +select * from customer where $c5 and c_acctbal > 2000; +call p(2000); +--sorted_result +eval +select c_name, c_acctbal from customer where $c5; +insert into customer select * from r; +--sorted_result +eval +select c_name, c_acctbal from customer where $c5; +drop table t,r; + +drop procedure p; + +set optimizer_switch='materialization=default'; + + +--echo # Materialization SP +--echo # ================== + +eval +create procedure p() +delete from customer where $c8; + +--sorted_result +eval +select c_name, c_acctbal from customer where $c8; +eval +create table t as +select * from customer where $c8; +call p(); +--sorted_result +eval +select c_name, c_acctbal from customer where $c8; +insert into customer select * from t; +--sorted_result +eval +select c_name, c_acctbal from customer where $c8; +eval +create table r as +select * from customer where $c8; +call p(); +--sorted_result +eval +select c_name, c_acctbal from customer where $c8; +insert into customer select * from r; +--sorted_result +eval +select c_name, c_acctbal from customer where $c8; +drop table t,r; + +drop procedure p; + + +--echo # Materialization SJM SP +--echo # ====================== + +eval +create procedure p() +delete from customer where $c10; + +--sorted_result +eval +select c_name, c_acctbal from customer where $c10; +eval +create table t as +select * from customer where $c10; +call p(); +--sorted_result +eval +select c_name, c_acctbal from customer where $c10; +insert into customer select * from t; +--sorted_result +eval +select c_name, c_acctbal from customer where $c10; +eval +create table r as +select * from customer where $c10; +call p(); +--sorted_result +eval +select c_name, c_acctbal from customer where $c10; +insert into customer select * from r; +--sorted_result +eval +select c_name, c_acctbal from customer where $c10; +drop table t,r; + +drop procedure p; + +--echo # Checking limitations +--echo # ==================== + +--echo # Check for DELETE ... RETURNING with SJ subquery in WHERE + +--sorted_result +eval +select c_name from customer where $c8; +eval +create table t as +select * from customer where $c8; +eval +explain +delete from customer where $c8 returning c_name; +--sorted_result +eval +delete from customer where $c8 returning c_name; +--sorted_result +eval +select c_name from customer where $c8; +insert into customer select * from t; +--sorted_result +eval +select c_name from customer where $c8; +drop table t; + +--sorted_result +eval +select c_name from customer where $c10; +eval +create table t as +select * from customer where $c10; +eval +explain +delete from customer where $c10 returning c_name; +--sorted_result +eval +delete from customer where $c10 returning c_name; +--sorted_result +eval +select c_name from customer where $c10; +insert into customer select * from t; +--sorted_result +eval +select c_name from customer where $c10; +drop table t; + +--echo # Check for DELETE ... ORDER BY ...LIMIT with SJ subquery in WHERE + +let $c11= + o_orderDATE between '1992-01-01' and '1992-06-30' and + o_custkey in (select c_custkey from customer + where c_nationkey in (1,2)); + +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c11; + +--echo # Should not use semi-join conversion because has ORDER BY ... LIMIT +eval +explain +delete from orders where $c11 +order by o_totalprice limit 500; +eval +create table t as +select * from orders where $c11; +select o_orderkey, o_totalprice from t; +eval +delete from orders where $c11 +order by o_totalprice limit 500; +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c11; +insert into orders select * from t; +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c11; +drop table t; + +--echo # Should use semi-join converion +eval +explain +delete from orders where $c11; +eval +create table t as +select * from orders where $c11; +select o_orderkey, o_totalprice from t; +eval +delete from orders where $c11; +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c11; +insert into orders select * from t; +--sorted_result +eval +select o_orderkey, o_totalprice from orders where $c11; +drop table t; + + +CREATE TABLE partsupp_small ( + ps_partkey int(11) NOT NULL DEFAULT '0', + ps_suppkey int(11) NOT NULL DEFAULT '0', + ps_availqty int(11) DEFAULT NULL, + ps_supplycost double DEFAULT NULL, + ps_comment varchar(199) DEFAULT NULL, + PRIMARY KEY (ps_partkey,ps_suppkey), + KEY i_ps_partkey (ps_partkey), + KEY i_ps_suppkey (ps_suppkey) +); + +create index i_ps_sup_part on partsupp_small(ps_suppkey, ps_partkey); +insert into partsupp_small select * from partsupp where ps_partkey <50; +analyze table partsupp_small persistent for all; + +--echo # LooseScan +--echo # ========= + +let $c12 = l_partkey in + (select ps_partkey from partsupp_small + where ps_suppkey in (1,2,3)); + +eval +explain +select count(*) from lineitem where $c12; +eval +explain format=json +select count(*) from lineitem where $c12; +eval +explain +select l_partkey from lineitem where $c12; +eval +explain format=json +select l_partkey from lineitem where $c12; +eval +select count(*) from lineitem where $c12; +eval +create table t as +select * from lineitem where $c12; + +eval +explain +delete from lineitem where $c12; +eval +explain format=json +delete from lineitem where $c12; +eval +delete from lineitem where $c12; +eval +select count(*) from lineitem where $c12; + +insert into lineitem select * from t; +eval +select count(*) from lineitem where $c12; + +drop table t; + +--echo # LooseScan PS +--echo # ============ + +eval +prepare stmt from " +delete from lineitem where $c12; +"; + +eval +select count(*) from lineitem where $c12; +eval +create table t as +select * from lineitem where $c12; +execute stmt; +eval +select count(*) from lineitem where $c12; +insert into lineitem select * from t; +eval +select count(*) from lineitem where $c12; + +eval +create table r as +select * from lineitem where $c12; +execute stmt; +eval +select count(*) from lineitem where $c12; +insert into lineitem select * from r; +eval +select count(*) from lineitem where $c12; + +drop tables r, t; +deallocate prepare stmt; + +--echo # LooseScan SP +--echo # ============ + +eval +create procedure p() +delete from lineitem where $c12; + +eval +select count(*) from lineitem where $c12; +eval +create table t as +select * from lineitem where $c12; +call p(); +eval +select count(*) from lineitem where $c12; +insert into lineitem select * from t; +eval +select count(*) from lineitem where $c12; + +eval +create table r as +select * from lineitem where $c12; +call p(); +eval +select count(*) from lineitem where $c12; +insert into lineitem select * from r; +eval +select count(*) from lineitem where $c12; + +drop tables r, t; +drop procedure p; + +--echo # DuplicateWeedout +--echo # ================ + +set @tmp_optimizer_switch= @@optimizer_switch; +set optimizer_switch='materialization=off'; + +analyze table lineitem; +analyze table orders; + +let $c13 = l_partkey in ( + select ps_partkey + from partsupp_small join lineitem on ps_partkey=l_partkey + where ps_suppkey in ( + select s_suppkey from supplier where s_suppkey < 2 + ) +); + +eval +explain +select count(*) from lineitem where $c13; +eval +explain format=json +select count(*) from lineitem where $c13; +eval +explain +select l_partkey from lineitem where $c13; +eval +explain format=json +select l_partkey from lineitem where $c13; +eval +select count(*) from lineitem where $c13; +eval +create table t as +select * from lineitem where $c13; + +eval +explain +delete from lineitem where $c13; +eval +explain format=json +delete from lineitem where $c13; +eval +delete from lineitem where $c13; +eval +select count(*) from lineitem where $c13; + +insert into lineitem select * from t; +eval +select count(*) from lineitem where $c13; + +drop table t; + +--echo # DuplicateWeedout PS +--echo # =================== + +eval +prepare stmt from " +delete from lineitem where $c13; +"; + +eval +select count(*) from lineitem where $c13; +eval +create table t as +select * from lineitem where $c13; +execute stmt; +eval +select count(*) from lineitem where $c13; +insert into lineitem select * from t; +eval +select count(*) from lineitem where $c13; + +eval +create table r as +select * from lineitem where $c13; +execute stmt; +eval +select count(*) from lineitem where $c13; +insert into lineitem select * from r; +eval +select count(*) from lineitem where $c13; + +drop tables r, t; +deallocate prepare stmt; + +--echo # DuplicateWeedout SP +--echo # =================== + +eval +create procedure p() +delete from lineitem where $c13; + +eval +select count(*) from lineitem where $c13; +eval +create table t as +select * from lineitem where $c13; +call p(); +eval +select count(*) from lineitem where $c13; +insert into lineitem select * from t; +eval +select count(*) from lineitem where $c13; + +eval +create table r as +select * from lineitem where $c13; +call p(); +eval +select count(*) from lineitem where $c13; +insert into lineitem select * from r; +eval +select count(*) from lineitem where $c13; + +drop tables r, t; +drop procedure p; + +set @@optimizer_switch=@tmp_optimizer_switch; + +drop table partsupp_small; + +DROP DATABASE dbt3_s001; diff --git a/mysql-test/main/delete_use_source.result b/mysql-test/main/delete_use_source.result index 0990a551db6..329203af613 100644 --- a/mysql-test/main/delete_use_source.result +++ b/mysql-test/main/delete_use_source.result @@ -49,7 +49,7 @@ rollback; start transaction; explain delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range c1 c1 4 NULL 600 Using where +1 PRIMARY t1 range c1 c1 4 NULL 600 Using index condition; Using where 2 DEPENDENT SUBQUERY b ref c1 c1 4 test.t1.c1 167 Using index delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1; affected rows: 1 @@ -65,7 +65,7 @@ rollback; start transaction; explain delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL c1 NULL NULL NULL # Using where +1 PRIMARY t1 range c1 c1 4 NULL # Using index condition; Using where 2 DEPENDENT SUBQUERY b ref c1 c1 4 test.t1.c1 # Using index delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 ; affected rows: 500 @@ -154,3 +154,183 @@ set session sort_buffer_size = 1024; delete from t1 where c1=0 and exists(select 'x' from t1 b where b.c1<10); affected rows: 128000 drop table t1; +# +# MDEV-17954: multi-table DELETE with the same source and target +# +create table t1 (c1 int, c2 int, c3 int); +insert into t1 values +(1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,4,7), (2,5,8); +# +# Single-table DELETE with the same source and target +# handled as multi-table DELETE +# +explain delete from t1 +where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1 and a.c2 < 3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 8 Using where; FirstMatch(t1) +delete from t1 +where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1 and a.c2 < 3); +select * from t1; +c1 c2 c3 +1 3 3 +2 3 6 +2 4 7 +2 5 8 +delete from t1; +insert into t1 values +(1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,4,7), (2,5,8); +prepare stmt from "delete from t1 +where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1 and a.c2 < 3)"; +execute stmt; +select * from t1; +c1 c2 c3 +1 3 3 +2 3 6 +2 4 7 +2 5 8 +delete from t1; +insert into t1 values +(2,2,5), (2,3,6), (2,4,7), (2,5,8); +execute stmt; +select * from t1; +c1 c2 c3 +2 3 6 +2 4 7 +2 5 8 +deallocate prepare stmt; +delete from t1; +insert into t1 values +(1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,4,7), (2,5,8); +# +# Multi-table DELETE with the same source and target +# +create table t2 (c1 int, c2 int, c3 int); +insert into t2 values +(1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,5,8); +explain delete from t1 using t1,t2 +where t1.c2 = t2.c2 and t1.c1 > 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 7 +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where +delete from t1 using t1,t2 +where t1.c2 = t2.c2 and t1.c1 > 1; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +2 4 7 +delete from t1; +insert into t1 values +(1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,4,7), (2,5,8); +prepare stmt from "delete from t1 using t1,t2 +where t1.c2 = t2.c2 and t1.c1 > 1"; +execute stmt; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +2 4 7 +delete from t1; +insert into t1 values +(2,2,5), (2,3,6), (2,4,7), (2,5,8); +execute stmt; +select * from t1; +c1 c2 c3 +2 4 7 +deallocate prepare stmt; +explain delete from t1 using t1,t2 +where t1.c2 = t2.c2 and t1.c1 > 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +1 SIMPLE t2 ALL NULL NULL NULL NULL 7 Using where +delete from t1 using t1,t2 +where t1.c2 = t2.c2 and t1.c1 > 1; +select * from t1; +c1 c2 c3 +2 4 7 +delete from t1; +insert into t1 values +(1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,4,7), (2,5,8); +prepare stmt from "delete from t1 using t1,t2 +where t1.c2 = t2.c2 and t1.c1 > 1"; +execute stmt; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +2 4 7 +delete from t1; +insert into t1 values +(2,2,5), (2,3,6), (2,4,7), (2,5,8); +execute stmt; +select * from t1; +c1 c2 c3 +2 4 7 +deallocate prepare stmt; +delete from t1; +insert into t1 values +(1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,4,7), (2,5,8); +explain delete from t1,t2 using t1,t2 +where t1.c2 = t2.c2 and t1.c1 > 1 and t2.c1 > 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 7 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where +delete from t1,t2 using t1,t2 +where t1.c2 = t2.c2 and t1.c1 > 1 and t2.c1 > 1; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +2 4 7 +select * from t2; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +delete from t1; +insert into t1 values +(1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,4,7), (2,5,8); +delete from t2; +insert into t2 values +(1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,5,8); +prepare stmt from "delete from t1,t2 using t1,t2 +where t1.c2 = t2.c2 and t1.c1 > 1 and t2.c1 > 1"; +execute stmt; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +2 4 7 +select * from t2; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +delete from t1; +insert into t1 values +(1,2,2), (1,3,3), (2,2,5), (2,3,6), (2,4,7), (2,5,8); +delete from t2; +insert into t2 values +(1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5); +execute stmt; +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +2 3 6 +2 4 7 +2 5 8 +select * from t2; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +2 1 4 +deallocate prepare stmt; +drop table t1,t2; diff --git a/mysql-test/main/delete_use_source.test b/mysql-test/main/delete_use_source.test index 4aed00da375..9625431c1a8 100644 --- a/mysql-test/main/delete_use_source.test +++ b/mysql-test/main/delete_use_source.test @@ -135,3 +135,123 @@ set session sort_buffer_size = 1024; delete from t1 where c1=0 and exists(select 'x' from t1 b where b.c1<10); drop table t1; + +--echo # +--echo # MDEV-17954: multi-table DELETE with the same source and target +--echo # + +create table t1 (c1 int, c2 int, c3 int); +insert into t1 values + (1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,4,7), (2,5,8); + +--echo # +--echo # Single-table DELETE with the same source and target +--echo # handled as multi-table DELETE +--echo # + +let $q1= +delete from t1 + where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1 and a.c2 < 3); + +eval explain $q1; +eval $q1; +select * from t1; +delete from t1; +insert into t1 values + (1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,4,7), (2,5,8); +eval prepare stmt from "$q1"; +execute stmt; +select * from t1; +delete from t1; +insert into t1 values + (2,2,5), (2,3,6), (2,4,7), (2,5,8); +execute stmt; +select * from t1; +deallocate prepare stmt; + +delete from t1; +insert into t1 values + (1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,4,7), (2,5,8); + +--echo # +--echo # Multi-table DELETE with the same source and target +--echo # + +create table t2 (c1 int, c2 int, c3 int); +insert into t2 values + (1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,5,8); + +let $q2= +delete from t1 using t1,t2 + where t1.c2 = t2.c2 and t1.c1 > 1; + +eval explain $q2; +eval $q2; +select * from t1; +delete from t1; +insert into t1 values + (1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,4,7), (2,5,8); +eval prepare stmt from "$q2"; +execute stmt; +select * from t1; +delete from t1; +insert into t1 values + (2,2,5), (2,3,6), (2,4,7), (2,5,8); +execute stmt; +select * from t1; +deallocate prepare stmt; + +let $q2= +delete from t1 using t1,t2 + where t1.c2 = t2.c2 and t1.c1 > 1; + +eval explain $q2; +eval $q2; +select * from t1; +delete from t1; +insert into t1 values + (1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,4,7), (2,5,8); +eval prepare stmt from "$q2"; +execute stmt; +select * from t1; +delete from t1; +insert into t1 values + (2,2,5), (2,3,6), (2,4,7), (2,5,8); +execute stmt; +select * from t1; +deallocate prepare stmt; + +delete from t1; +insert into t1 values + (1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,4,7), (2,5,8); + +let $q3= +delete from t1,t2 using t1,t2 + where t1.c2 = t2.c2 and t1.c1 > 1 and t2.c1 > 1; + +eval explain $q3; +eval $q3; +select * from t1; +select * from t2; +delete from t1; +insert into t1 values + (1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,4,7), (2,5,8); +delete from t2; +insert into t2 values + (1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5), (2,3,6), (2,5,8); +eval prepare stmt from "$q3"; +execute stmt; +select * from t1; +select * from t2; +delete from t1; +insert into t1 values + (1,2,2), (1,3,3), (2,2,5), (2,3,6), (2,4,7), (2,5,8); +delete from t2; +insert into t2 values + (1,1,1), (1,2,2), (1,3,3), (2,1,4), (2,2,5); +execute stmt; +select * from t1; +select * from t2; +deallocate prepare stmt; + +drop table t1,t2; diff --git a/mysql-test/main/delete_use_source_engines.result b/mysql-test/main/delete_use_source_engines.result new file mode 100644 index 00000000000..b1ad9c009d9 --- /dev/null +++ b/mysql-test/main/delete_use_source_engines.result @@ -0,0 +1,8870 @@ +set @save_default_engine=@@default_storage_engine; +####################################### +# # +# Engine InnoDB # +# # +####################################### +set global innodb_stats_persistent=1; +set default_storage_engine=InnoDB; +create table t1 (c1 integer, c2 integer, c3 integer); +insert into t1(c1,c2,c3) +values (1,1,1),(1,2,2),(1,3,3), +(2,1,4),(2,2,5),(2,3,6), +(2,4,7),(2,5,8); +insert into t1 select c1+10,c2,c3+10 from t1; +insert into t1 select c1+20,c2+1,c3+20 from t1; +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 +create view v1 as select * from t1 where c2=2; +####################################### +# Test without any index # +####################################### +# +# Delete with value from subquery on the same table +# +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 +create table tmp as select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +explain select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +explain delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 4 +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +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 +create table tmp as select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +explain select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +analyze delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 9.38 9.38 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 12.00 3.12 5.56 Using where; FirstMatch(t1) +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with IN predicand over the updated table in WHERE +# +create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +affected rows: 8 +select * from t1; +c1 c2 c3 +1 3 3 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit - can be deleted +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 100.00 12.50 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 24.50 3.12 1.02 Using where; FirstMatch(t1) +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit and an order by +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using temporary; Using filesort +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +affected rows: 1 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete: 2 execution of PS +# +prepare create_tmp_stmt from +"create table tmp as select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +prepare delete_t1_stmt from +"delete from t1 where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=5; +execute create_tmp_stmt using @a; +execute delete_t1_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 6 38 +prepare insert_tmp_stmt from +"insert into tmp(c1,c2,c3) select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=2; +execute insert_tmp_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +2 1 4 +2 3 6 +2 4 7 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +drop table tmp; +# +# Delete in stored procedure +# +create procedure sp() +begin +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +end +// +create table tmp as select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop procedure sp; +drop table tmp; +# +# Delete in stored function +# +create function f1(IN a INT) returns int +begin +delete from t1 where c3 < a order by c3 limit 1; +return 1; +end;// +set @a:=7; +create table tmp as select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +insert into tmp(c1,c2,c3) select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop function f1; +drop table tmp; +# +# Delete in trigger +# +create table t2 (c1 integer); +insert into t2(c1) values (1), (2), (3), (4), (5), (6), (7), (8); +CREATE TABLE cnt(del integer); +INSERT INTO cnt VALUES(0); +CREATE TRIGGER tr1 AFTER DELETE ON t1 FOR EACH ROW +UPDATE cnt SET del=del+1; +CREATE TRIGGER tr2 AFTER DELETE ON t1 FOR EACH ROW +DELETE FROM t2 WHERE c1> (SELECT count(*)-1 FROM t2); +CREATE TABLE tmp as SELECT * FROM t1 WHERE c2>=3; +DELETE FROM t1 WHERE c2>=3; +affected rows: 20 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +SELECT * FROM t2; +c1 +SELECT * FROM cnt; +del +20 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +DROP TRIGGER tr1; +DROP TRIGGER tr2; +drop table t2, cnt, tmp; +# +# Delete with a reference to view in subquery +# +create table tmp as select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +explain select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +explain delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +analyze delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 100.00 25.00 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 32.00 25.00 3.12 Using where +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +####################################### +# Test with an index # +####################################### +create index t1_c2 on t1 (c2,c1); +# +# Delete with value from subquery on the same table +# +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 +create table tmp as select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +explain select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +explain delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 4 +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +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 +create table tmp as select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +explain select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a index NULL t1_c2 10 NULL 32 Using where; Using index; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a index NULL t1_c2 10 NULL 32 Using where; Using index; FirstMatch(t1) +analyze delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 32.00 9.38 9.38 Using where +1 PRIMARY a index NULL t1_c2 10 NULL 32 11.67 3.12 5.71 Using where; Using index; FirstMatch(t1) +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with IN predicand over the updated table in WHERE +# +create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 10 test.t1.c2,test.t1.c3 1 Using index; FirstMatch(t1) +explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 10 test.t1.c2,test.t1.c3 1 Using index; FirstMatch(t1) +delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +affected rows: 8 +select * from t1; +c1 c2 c3 +1 3 3 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit - can be deleted +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 Using index; FirstMatch(t1) +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 Using index; FirstMatch(t1) +analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 100.00 12.50 Using where +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 0.25 18.75 100.00 Using index; FirstMatch(t1) +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit and an order by +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using temporary; Using filesort +1 PRIMARY a ALL t1_c2 NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +2 DEPENDENT SUBQUERY a index_subquery t1_c2 t1_c2 5 func 5 Using where +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +affected rows: 1 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete: 2 execution of PS +# +prepare create_tmp_stmt from +"create table tmp as select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +prepare delete_t1_stmt from +"delete from t1 where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=5; +execute create_tmp_stmt using @a; +execute delete_t1_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 6 38 +prepare insert_tmp_stmt from +"insert into tmp(c1,c2,c3) select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=2; +execute insert_tmp_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +2 1 4 +2 3 6 +2 4 7 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +drop table tmp; +# +# Delete in stored procedure +# +create procedure sp() +begin +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +end +// +create table tmp as select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop procedure sp; +drop table tmp; +# +# Delete in stored function +# +create function f1(IN a INT) returns int +begin +delete from t1 where c3 < a order by c3 limit 1; +return 1; +end;// +set @a:=7; +create table tmp as select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +insert into tmp(c1,c2,c3) select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop function f1; +drop table tmp; +# +# Delete in trigger +# +create table t2 (c1 integer); +insert into t2(c1) values (1), (2), (3), (4), (5), (6), (7), (8); +CREATE TABLE cnt(del integer); +INSERT INTO cnt VALUES(0); +CREATE TRIGGER tr1 AFTER DELETE ON t1 FOR EACH ROW +UPDATE cnt SET del=del+1; +CREATE TRIGGER tr2 AFTER DELETE ON t1 FOR EACH ROW +DELETE FROM t2 WHERE c1> (SELECT count(*)-1 FROM t2); +CREATE TABLE tmp as SELECT * FROM t1 WHERE c2>=3; +DELETE FROM t1 WHERE c2>=3; +affected rows: 20 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +SELECT * FROM t2; +c1 +SELECT * FROM cnt; +del +20 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +DROP TRIGGER tr1; +DROP TRIGGER tr2; +drop table t2, cnt, tmp; +# +# Delete with a reference to view in subquery +# +create table tmp as select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +explain select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 Using index +explain delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 Using index +analyze delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 100.00 25.00 Using where +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 1.00 100.00 100.00 Using index +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +####################################### +# Test with a primary key # +####################################### +drop index t1_c2 on t1; +alter table t1 add primary key (c3); +# +# Delete with value from subquery on the same table +# +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 +create table tmp as select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +explain select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 +explain delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 +delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 4 +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +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 +create table tmp as select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +explain select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +analyze delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 9.38 9.38 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 12.33 3.12 5.41 Using where; FirstMatch(t1) +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with IN predicand over the updated table in WHERE +# +create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c1 1 Using where; End temporary +explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c1 1 Using where; End temporary +delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +affected rows: 8 +select * from t1; +c1 c2 c3 +1 3 3 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit - can be deleted +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 Using where; End temporary +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 Using where; End temporary +analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 1.00 100.00 100.00 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 1.00 3.12 100.00 Using where; End temporary +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit and an order by +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index PRIMARY PRIMARY 4 NULL 1 +1 PRIMARY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using where +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index NULL PRIMARY 4 NULL 1 Using where +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using where +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +affected rows: 1 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete: 2 execution of PS +# +prepare create_tmp_stmt from +"create table tmp as select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +prepare delete_t1_stmt from +"delete from t1 where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=5; +execute create_tmp_stmt using @a; +execute delete_t1_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 6 38 +prepare insert_tmp_stmt from +"insert into tmp(c1,c2,c3) select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=2; +execute insert_tmp_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +2 1 4 +2 3 6 +2 4 7 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +drop table tmp; +# +# Delete in stored procedure +# +create procedure sp() +begin +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +end +// +create table tmp as select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop procedure sp; +drop table tmp; +# +# Delete in stored function +# +create function f1(IN a INT) returns int +begin +delete from t1 where c3 < a order by c3 limit 1; +return 1; +end;// +set @a:=7; +create table tmp as select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +insert into tmp(c1,c2,c3) select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop function f1; +drop table tmp; +# +# Delete in trigger +# +create table t2 (c1 integer); +insert into t2(c1) values (1), (2), (3), (4), (5), (6), (7), (8); +CREATE TABLE cnt(del integer); +INSERT INTO cnt VALUES(0); +CREATE TRIGGER tr1 AFTER DELETE ON t1 FOR EACH ROW +UPDATE cnt SET del=del+1; +CREATE TRIGGER tr2 AFTER DELETE ON t1 FOR EACH ROW +DELETE FROM t2 WHERE c1> (SELECT count(*)-1 FROM t2); +CREATE TABLE tmp as SELECT * FROM t1 WHERE c2>=3; +DELETE FROM t1 WHERE c2>=3; +affected rows: 20 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +SELECT * FROM t2; +c1 +SELECT * FROM cnt; +del +20 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +DROP TRIGGER tr1; +DROP TRIGGER tr2; +drop table t2, cnt, tmp; +# +# Delete with a reference to view in subquery +# +create table tmp as select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +explain select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +explain delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +analyze delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 100.00 25.00 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 32.00 25.00 3.12 Using where +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +drop view v1; +drop table t1; +# +# Test on dynamic columns (blob) +# +create table assets ( +item_name varchar(32) primary key, -- A common attribute for all items +dynamic_cols blob -- Dynamic columns will be stored here +); +INSERT INTO assets +VALUES ('MariaDB T-shirt', +COLUMN_CREATE('color', 'blue', 'size', 'XL')); +INSERT INTO assets +VALUES ('Thinkpad Laptop', +COLUMN_CREATE('color', 'black', 'price', 500)); +INSERT INTO assets +VALUES ('Fridge', +COLUMN_CREATE('color', 'white', 'warranty', '5 years')); +INSERT INTO assets +VALUES ('Microwave', +COLUMN_CREATE('warranty', '3 years')); +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color +FROM assets ORDER BY item_name; +item_name color +Fridge white +MariaDB T-shirt blue +Microwave NULL +Thinkpad Laptop black +UPDATE assets SET dynamic_cols=COLUMN_DELETE(dynamic_cols, 'color') +WHERE item_name='Fridge'; +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color +FROM assets ORDER BY item_name; +item_name color +Fridge NULL +MariaDB T-shirt blue +Microwave NULL +Thinkpad Laptop black +DELETE FROM assets +WHERE item_name in +(select b.item_name from assets b +where COLUMN_GET(b.dynamic_cols, 'color' as char) ='black'); +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color +FROM assets ORDER BY item_name; +item_name color +Fridge NULL +MariaDB T-shirt blue +Microwave NULL +DELETE FROM assets WHERE item_name='Microwave'; +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color +FROM assets ORDER BY item_name; +item_name color +Fridge NULL +MariaDB T-shirt blue +drop table assets ; +# +# Test on fulltext columns +# +CREATE TABLE ft2(copy TEXT,FULLTEXT(copy)); +INSERT INTO ft2(copy) VALUES +('MySQL vs MariaDB database'), +('Oracle vs MariaDB database'), +('PostgreSQL vs MariaDB database'), +('MariaDB overview'), +('Foreign keys'), +('Primary keys'), +('Indexes'), +('Transactions'), +('Triggers'); +SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('database'); +copy +MySQL vs MariaDB database +Oracle vs MariaDB database +PostgreSQL vs MariaDB database +DELETE FROM ft2 WHERE MATCH(copy) AGAINST('database'); +SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('database'); +copy +drop table ft2; +####################################### +# # +# Engine Aria # +# # +####################################### +set default_storage_engine=Aria; +create table t1 (c1 integer, c2 integer, c3 integer); +insert into t1(c1,c2,c3) +values (1,1,1),(1,2,2),(1,3,3), +(2,1,4),(2,2,5),(2,3,6), +(2,4,7),(2,5,8); +insert into t1 select c1+10,c2,c3+10 from t1; +insert into t1 select c1+20,c2+1,c3+20 from t1; +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 +create view v1 as select * from t1 where c2=2; +####################################### +# Test without any index # +####################################### +# +# Delete with value from subquery on the same table +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +create table tmp as select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +explain select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +explain delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 4 +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +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 +create table tmp as select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +explain select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +analyze delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 9.38 9.38 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 12.67 3.12 5.26 Using where; FirstMatch(t1) +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with IN predicand over the updated table in WHERE +# +create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +affected rows: 8 +select * from t1; +c1 c2 c3 +1 3 3 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit - can be deleted +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 25.00 100.00 12.00 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 22.67 3.12 1.47 Using where; FirstMatch(t1) +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit and an order by +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using temporary; Using filesort +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +affected rows: 1 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete: 2 execution of PS +# +prepare create_tmp_stmt from +"create table tmp as select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +prepare delete_t1_stmt from +"delete from t1 where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=5; +execute create_tmp_stmt using @a; +execute delete_t1_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 6 38 +prepare insert_tmp_stmt from +"insert into tmp(c1,c2,c3) select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=2; +execute insert_tmp_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +2 1 4 +2 3 6 +2 4 7 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +drop table tmp; +# +# Delete in stored procedure +# +create procedure sp() +begin +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +end +// +create table tmp as select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop procedure sp; +drop table tmp; +# +# Delete in stored function +# +create function f1(IN a INT) returns int +begin +delete from t1 where c3 < a order by c3 limit 1; +return 1; +end;// +set @a:=7; +create table tmp as select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +insert into tmp(c1,c2,c3) select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop function f1; +drop table tmp; +# +# Delete in trigger +# +create table t2 (c1 integer); +insert into t2(c1) values (1), (2), (3), (4), (5), (6), (7), (8); +CREATE TABLE cnt(del integer); +INSERT INTO cnt VALUES(0); +CREATE TRIGGER tr1 AFTER DELETE ON t1 FOR EACH ROW +UPDATE cnt SET del=del+1; +CREATE TRIGGER tr2 AFTER DELETE ON t1 FOR EACH ROW +DELETE FROM t2 WHERE c1> (SELECT count(*)-1 FROM t2); +CREATE TABLE tmp as SELECT * FROM t1 WHERE c2>=3; +DELETE FROM t1 WHERE c2>=3; +affected rows: 20 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +SELECT * FROM t2; +c1 +SELECT * FROM cnt; +del +20 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +DROP TRIGGER tr1; +DROP TRIGGER tr2; +drop table t2, cnt, tmp; +# +# Delete with a reference to view in subquery +# +create table tmp as select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +explain select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +explain delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +analyze delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 100.00 25.00 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 32.00 25.00 3.12 Using where +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +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 +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +affected rows: 8 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 4 7 +2 5 8 +21 2 21 +21 4 23 +22 2 24 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 4 33 +32 2 34 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with order by +# +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 +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func # +2 MATERIALIZED a ALL NULL NULL NULL NULL # +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func # +2 MATERIALIZED a ALL NULL NULL NULL NULL # +analyze delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # 32.00 62.50 62.50 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func # 1.00 100.00 100.00 +2 MATERIALIZED a ALL NULL NULL NULL NULL # 32.00 62.50 100.00 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view +# +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 +create table tmp as select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +explain select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +explain delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +affected rows: 0 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view using reference +# to the same view in subquery +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +create table tmp as select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +explain select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL # Using where +explain delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL # Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL # Using where +analyze delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # 32.00 3.91 3.12 Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL # 5.00 25.00 20.00 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL # 32.00 100.00 3.12 Using where +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +####################################### +# Test with an index # +####################################### +create index t1_c2 on t1 (c2,c1); +# +# Delete with value from subquery on the same table +# +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 +create table tmp as select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +explain select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +explain delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 4 +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +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 +create table tmp as select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +explain select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a index NULL t1_c2 10 NULL 32 Using where; Using index; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a index NULL t1_c2 10 NULL 32 Using where; Using index; FirstMatch(t1) +analyze delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 32.00 9.38 9.38 Using where +1 PRIMARY a index NULL t1_c2 10 NULL 32 11.67 3.12 5.71 Using where; Using index; FirstMatch(t1) +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with IN predicand over the updated table in WHERE +# +create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 10 test.t1.c2,test.t1.c3 1 Using index; FirstMatch(t1) +explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 10 test.t1.c2,test.t1.c3 1 Using index; FirstMatch(t1) +delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +affected rows: 8 +select * from t1; +c1 c2 c3 +1 3 3 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit - can be deleted +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 Using index; FirstMatch(t1) +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 Using index; FirstMatch(t1) +analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 27.00 100.00 14.81 Using where +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 0.25 18.75 100.00 Using index; FirstMatch(t1) +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit and an order by +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 Using where; FirstMatch(t1) +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +2 DEPENDENT SUBQUERY a index_subquery t1_c2 t1_c2 5 func 5 Using where +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +affected rows: 1 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete: 2 execution of PS +# +prepare create_tmp_stmt from +"create table tmp as select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +prepare delete_t1_stmt from +"delete from t1 where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=5; +execute create_tmp_stmt using @a; +execute delete_t1_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 6 38 +prepare insert_tmp_stmt from +"insert into tmp(c1,c2,c3) select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=2; +execute insert_tmp_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +2 1 4 +2 3 6 +2 4 7 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +drop table tmp; +# +# Delete in stored procedure +# +create procedure sp() +begin +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +end +// +create table tmp as select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop procedure sp; +drop table tmp; +# +# Delete in stored function +# +create function f1(IN a INT) returns int +begin +delete from t1 where c3 < a order by c3 limit 1; +return 1; +end;// +set @a:=7; +create table tmp as select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +insert into tmp(c1,c2,c3) select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop function f1; +drop table tmp; +# +# Delete in trigger +# +create table t2 (c1 integer); +insert into t2(c1) values (1), (2), (3), (4), (5), (6), (7), (8); +CREATE TABLE cnt(del integer); +INSERT INTO cnt VALUES(0); +CREATE TRIGGER tr1 AFTER DELETE ON t1 FOR EACH ROW +UPDATE cnt SET del=del+1; +CREATE TRIGGER tr2 AFTER DELETE ON t1 FOR EACH ROW +DELETE FROM t2 WHERE c1> (SELECT count(*)-1 FROM t2); +CREATE TABLE tmp as SELECT * FROM t1 WHERE c2>=3; +DELETE FROM t1 WHERE c2>=3; +affected rows: 20 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +SELECT * FROM t2; +c1 +SELECT * FROM cnt; +del +20 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +DROP TRIGGER tr1; +DROP TRIGGER tr2; +drop table t2, cnt, tmp; +# +# Delete with a reference to view in subquery +# +create table tmp as select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +explain select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 Using index +explain delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 Using index +analyze delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 100.00 25.00 Using where +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 1.00 100.00 100.00 Using index +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +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 +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 5 const 8 +1 PRIMARY a ref t1_c2 t1_c2 5 const 8 Using index; FirstMatch(t1) +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 5 const 8 +1 PRIMARY a ref t1_c2 t1_c2 5 const 8 Using index; FirstMatch(t1) +delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +affected rows: 8 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 4 7 +2 5 8 +21 2 21 +21 4 23 +22 2 24 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 4 33 +32 2 34 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with order by +# +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 +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 5 NULL # Using index condition +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c2 # Using index; FirstMatch(t1) +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a index t1_c2 t1_c2 10 NULL # Using where; Using index; LooseScan +1 PRIMARY t1 ref t1_c2 t1_c2 5 test.a.c2 # +analyze delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY a index t1_c2 t1_c2 10 NULL # 16.00 20.00 25.00 Using where; Using index; LooseScan +1 PRIMARY t1 ref t1_c2 t1_c2 5 test.a.c2 # 5.00 4.76 100.00 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view +# +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 +create table tmp as select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +explain select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 5 const 8 Using where +2 DEPENDENT SUBQUERY a ref t1_c2 t1_c2 5 test.t1.c2 5 Using index +explain delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 5 const 8 Using where +2 DEPENDENT SUBQUERY a ref t1_c2 t1_c2 5 test.t1.c2 5 Using index +delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +affected rows: 0 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view using reference +# to the same view in subquery +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +create table tmp as select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +explain select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 10 const,const # Using where +1 PRIMARY t1 ref t1_c2 t1_c2 10 const,const # Using index; FirstMatch(t1) +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL # Using where +explain delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 10 const,const # Using where +3 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,func # Using where; Using index +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL # Using where +analyze delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ref t1_c2 t1_c2 10 const,const # 1.00 100.00 100.00 Using where +3 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,func # 1.00 100.00 100.00 Using where; Using index +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL # 32.00 100.00 3.12 Using where +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +####################################### +# Test with a primary key # +####################################### +drop index t1_c2 on t1; +alter table t1 add primary key (c3); +# +# Delete with value from subquery on the same table +# +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 +create table tmp as select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +explain select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using index +explain delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using index +delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 4 +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +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 +create table tmp as select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +explain select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +analyze delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 9.38 9.38 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 12.00 3.12 5.56 Using where; FirstMatch(t1) +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with IN predicand over the updated table in WHERE +# +create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c1 1 Using where; End temporary +explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c1 1 Using where; End temporary +delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +affected rows: 8 +select * from t1; +c1 c2 c3 +1 3 3 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit - can be deleted +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 Using where; End temporary +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 Using where; End temporary +analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 4.00 100.00 100.00 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 1.00 3.12 25.00 Using where; End temporary +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit and an order by +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index PRIMARY PRIMARY 4 NULL 1 +1 PRIMARY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using where +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index NULL PRIMARY 4 NULL 1 Using where +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using where +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +affected rows: 1 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete: 2 execution of PS +# +prepare create_tmp_stmt from +"create table tmp as select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +prepare delete_t1_stmt from +"delete from t1 where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=5; +execute create_tmp_stmt using @a; +execute delete_t1_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 6 38 +prepare insert_tmp_stmt from +"insert into tmp(c1,c2,c3) select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=2; +execute insert_tmp_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +2 1 4 +2 3 6 +2 4 7 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +drop table tmp; +# +# Delete in stored procedure +# +create procedure sp() +begin +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +end +// +create table tmp as select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop procedure sp; +drop table tmp; +# +# Delete in stored function +# +create function f1(IN a INT) returns int +begin +delete from t1 where c3 < a order by c3 limit 1; +return 1; +end;// +set @a:=7; +create table tmp as select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +insert into tmp(c1,c2,c3) select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop function f1; +drop table tmp; +# +# Delete in trigger +# +create table t2 (c1 integer); +insert into t2(c1) values (1), (2), (3), (4), (5), (6), (7), (8); +CREATE TABLE cnt(del integer); +INSERT INTO cnt VALUES(0); +CREATE TRIGGER tr1 AFTER DELETE ON t1 FOR EACH ROW +UPDATE cnt SET del=del+1; +CREATE TRIGGER tr2 AFTER DELETE ON t1 FOR EACH ROW +DELETE FROM t2 WHERE c1> (SELECT count(*)-1 FROM t2); +CREATE TABLE tmp as SELECT * FROM t1 WHERE c2>=3; +DELETE FROM t1 WHERE c2>=3; +affected rows: 20 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +SELECT * FROM t2; +c1 +SELECT * FROM cnt; +del +20 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +DROP TRIGGER tr1; +DROP TRIGGER tr2; +drop table t2, cnt, tmp; +# +# Delete with a reference to view in subquery +# +create table tmp as select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +explain select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +explain delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +analyze delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 100.00 25.00 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 32.00 25.00 3.12 Using where +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +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 +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +affected rows: 8 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 4 7 +2 5 8 +21 2 21 +21 4 23 +22 2 24 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 4 33 +32 2 34 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with order by +# +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 +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func # +2 MATERIALIZED a ALL NULL NULL NULL NULL # +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func # +2 MATERIALIZED a ALL NULL NULL NULL NULL # +analyze delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # 32.00 62.50 62.50 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func # 1.00 100.00 100.00 +2 MATERIALIZED a ALL NULL NULL NULL NULL # 32.00 62.50 100.00 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view +# +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 +create table tmp as select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +explain select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 const PRIMARY PRIMARY 4 const 1 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +explain delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 const PRIMARY PRIMARY 4 const 1 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +affected rows: 0 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view using reference +# to the same view in subquery +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +create table tmp as select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +explain select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 # +explain delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL # Using where +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 # +analyze delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # 32.00 3.91 3.12 Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL # 6.00 25.00 16.67 Using where +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 # 1.00 100.00 100.00 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +drop view v1; +drop table t1; +# +# Test on dynamic columns (blob) +# +create table assets ( +item_name varchar(32) primary key, -- A common attribute for all items +dynamic_cols blob -- Dynamic columns will be stored here +); +INSERT INTO assets +VALUES ('MariaDB T-shirt', +COLUMN_CREATE('color', 'blue', 'size', 'XL')); +INSERT INTO assets +VALUES ('Thinkpad Laptop', +COLUMN_CREATE('color', 'black', 'price', 500)); +INSERT INTO assets +VALUES ('Fridge', +COLUMN_CREATE('color', 'white', 'warranty', '5 years')); +INSERT INTO assets +VALUES ('Microwave', +COLUMN_CREATE('warranty', '3 years')); +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color +FROM assets ORDER BY item_name; +item_name color +Fridge white +MariaDB T-shirt blue +Microwave NULL +Thinkpad Laptop black +UPDATE assets SET dynamic_cols=COLUMN_DELETE(dynamic_cols, 'color') +WHERE item_name='Fridge'; +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color +FROM assets ORDER BY item_name; +item_name color +Fridge NULL +MariaDB T-shirt blue +Microwave NULL +Thinkpad Laptop black +DELETE FROM assets +WHERE item_name in +(select b.item_name from assets b +where COLUMN_GET(b.dynamic_cols, 'color' as char) ='black'); +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color +FROM assets ORDER BY item_name; +item_name color +Fridge NULL +MariaDB T-shirt blue +Microwave NULL +DELETE FROM assets WHERE item_name='Microwave'; +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color +FROM assets ORDER BY item_name; +item_name color +Fridge NULL +MariaDB T-shirt blue +drop table assets ; +# +# Test on fulltext columns +# +CREATE TABLE ft2(copy TEXT,FULLTEXT(copy)); +INSERT INTO ft2(copy) VALUES +('MySQL vs MariaDB database'), +('Oracle vs MariaDB database'), +('PostgreSQL vs MariaDB database'), +('MariaDB overview'), +('Foreign keys'), +('Primary keys'), +('Indexes'), +('Transactions'), +('Triggers'); +SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('database'); +copy +MySQL vs MariaDB database +Oracle vs MariaDB database +PostgreSQL vs MariaDB database +DELETE FROM ft2 WHERE MATCH(copy) AGAINST('database'); +SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('database'); +copy +drop table ft2; +####################################### +# # +# Engine MyISAM # +# # +####################################### +set default_storage_engine=MyISAM; +create table t1 (c1 integer, c2 integer, c3 integer); +insert into t1(c1,c2,c3) +values (1,1,1),(1,2,2),(1,3,3), +(2,1,4),(2,2,5),(2,3,6), +(2,4,7),(2,5,8); +insert into t1 select c1+10,c2,c3+10 from t1; +insert into t1 select c1+20,c2+1,c3+20 from t1; +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 +create view v1 as select * from t1 where c2=2; +####################################### +# Test without any index # +####################################### +# +# Delete with value from subquery on the same table +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +create table tmp as select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +explain select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +explain delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 4 +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +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 +create table tmp as select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +explain select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +analyze delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 9.38 9.38 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 12.67 3.12 5.26 Using where; FirstMatch(t1) +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with IN predicand over the updated table in WHERE +# +create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +affected rows: 8 +select * from t1; +c1 c2 c3 +1 3 3 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit - can be deleted +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 25.00 100.00 12.00 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 22.67 3.12 1.47 Using where; FirstMatch(t1) +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit and an order by +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using temporary; Using filesort +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +affected rows: 1 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete: 2 execution of PS +# +prepare create_tmp_stmt from +"create table tmp as select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +prepare delete_t1_stmt from +"delete from t1 where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=5; +execute create_tmp_stmt using @a; +execute delete_t1_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 6 38 +prepare insert_tmp_stmt from +"insert into tmp(c1,c2,c3) select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=2; +execute insert_tmp_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +2 1 4 +2 3 6 +2 4 7 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +drop table tmp; +# +# Delete in stored procedure +# +create procedure sp() +begin +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +end +// +create table tmp as select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop procedure sp; +drop table tmp; +# +# Delete in stored function +# +create function f1(IN a INT) returns int +begin +delete from t1 where c3 < a order by c3 limit 1; +return 1; +end;// +set @a:=7; +create table tmp as select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +insert into tmp(c1,c2,c3) select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop function f1; +drop table tmp; +# +# Delete in trigger +# +create table t2 (c1 integer); +insert into t2(c1) values (1), (2), (3), (4), (5), (6), (7), (8); +CREATE TABLE cnt(del integer); +INSERT INTO cnt VALUES(0); +CREATE TRIGGER tr1 AFTER DELETE ON t1 FOR EACH ROW +UPDATE cnt SET del=del+1; +CREATE TRIGGER tr2 AFTER DELETE ON t1 FOR EACH ROW +DELETE FROM t2 WHERE c1> (SELECT count(*)-1 FROM t2); +CREATE TABLE tmp as SELECT * FROM t1 WHERE c2>=3; +DELETE FROM t1 WHERE c2>=3; +affected rows: 20 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +SELECT * FROM t2; +c1 +SELECT * FROM cnt; +del +20 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +DROP TRIGGER tr1; +DROP TRIGGER tr2; +drop table t2, cnt, tmp; +# +# Delete with a reference to view in subquery +# +create table tmp as select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +explain select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +explain delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +analyze delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 100.00 25.00 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 32.00 25.00 3.12 Using where +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +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 +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +affected rows: 8 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 4 7 +2 5 8 +21 2 21 +21 4 23 +22 2 24 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 4 33 +32 2 34 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with order by +# +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 +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func # +2 MATERIALIZED a ALL NULL NULL NULL NULL # +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func # +2 MATERIALIZED a ALL NULL NULL NULL NULL # +analyze delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # 32.00 62.50 62.50 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func # 1.00 100.00 100.00 +2 MATERIALIZED a ALL NULL NULL NULL NULL # 32.00 62.50 100.00 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view +# +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 +create table tmp as select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +explain select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +explain delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +affected rows: 0 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view using reference +# to the same view in subquery +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +create table tmp as select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +explain select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL # Using where +explain delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL # Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL # Using where +analyze delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # 32.00 3.91 3.12 Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL # 5.00 25.00 20.00 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL # 32.00 100.00 3.12 Using where +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +####################################### +# Test with an index # +####################################### +create index t1_c2 on t1 (c2,c1); +# +# Delete with value from subquery on the same table +# +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 +create table tmp as select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +explain select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +explain delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 4 +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +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 +create table tmp as select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +explain select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a index NULL t1_c2 10 NULL 32 Using where; Using index; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a index NULL t1_c2 10 NULL 32 Using where; Using index; FirstMatch(t1) +analyze delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 32.00 9.38 9.38 Using where +1 PRIMARY a index NULL t1_c2 10 NULL 32 11.67 3.12 5.71 Using where; Using index; FirstMatch(t1) +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with IN predicand over the updated table in WHERE +# +create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 10 test.t1.c2,test.t1.c3 1 Using index; FirstMatch(t1) +explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 10 test.t1.c2,test.t1.c3 1 Using index; FirstMatch(t1) +delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +affected rows: 8 +select * from t1; +c1 c2 c3 +1 3 3 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit - can be deleted +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 Using index; FirstMatch(t1) +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 Using index; FirstMatch(t1) +analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 29.00 100.00 13.79 Using where +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c1 5 0.25 18.75 100.00 Using index; FirstMatch(t1) +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit and an order by +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using temporary; Using filesort +1 PRIMARY a ALL t1_c2 NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +2 DEPENDENT SUBQUERY a index_subquery t1_c2 t1_c2 5 func 5 Using where +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +affected rows: 1 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete: 2 execution of PS +# +prepare create_tmp_stmt from +"create table tmp as select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +prepare delete_t1_stmt from +"delete from t1 where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=5; +execute create_tmp_stmt using @a; +execute delete_t1_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 6 38 +prepare insert_tmp_stmt from +"insert into tmp(c1,c2,c3) select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=2; +execute insert_tmp_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +2 1 4 +2 3 6 +2 4 7 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +drop table tmp; +# +# Delete in stored procedure +# +create procedure sp() +begin +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +end +// +create table tmp as select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop procedure sp; +drop table tmp; +# +# Delete in stored function +# +create function f1(IN a INT) returns int +begin +delete from t1 where c3 < a order by c3 limit 1; +return 1; +end;// +set @a:=7; +create table tmp as select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +insert into tmp(c1,c2,c3) select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop function f1; +drop table tmp; +# +# Delete in trigger +# +create table t2 (c1 integer); +insert into t2(c1) values (1), (2), (3), (4), (5), (6), (7), (8); +CREATE TABLE cnt(del integer); +INSERT INTO cnt VALUES(0); +CREATE TRIGGER tr1 AFTER DELETE ON t1 FOR EACH ROW +UPDATE cnt SET del=del+1; +CREATE TRIGGER tr2 AFTER DELETE ON t1 FOR EACH ROW +DELETE FROM t2 WHERE c1> (SELECT count(*)-1 FROM t2); +CREATE TABLE tmp as SELECT * FROM t1 WHERE c2>=3; +DELETE FROM t1 WHERE c2>=3; +affected rows: 20 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +SELECT * FROM t2; +c1 +SELECT * FROM cnt; +del +20 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +DROP TRIGGER tr1; +DROP TRIGGER tr2; +drop table t2, cnt, tmp; +# +# Delete with a reference to view in subquery +# +create table tmp as select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +explain select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 Using index +explain delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 Using index +analyze delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 100.00 25.00 Using where +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 1.00 100.00 100.00 Using index +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +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 +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 5 const 8 +1 PRIMARY a ref t1_c2 t1_c2 5 const 8 Using index; FirstMatch(t1) +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 5 const 8 +1 PRIMARY a ref t1_c2 t1_c2 5 const 8 Using index; FirstMatch(t1) +delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +affected rows: 8 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 4 7 +2 5 8 +21 2 21 +21 4 23 +22 2 24 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 4 33 +32 2 34 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with order by +# +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 +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL # Using where; Using filesort +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c2 # Using index; FirstMatch(t1) +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a index t1_c2 t1_c2 10 NULL # Using where; Using index; LooseScan +1 PRIMARY t1 ref t1_c2 t1_c2 5 test.a.c2 # +analyze delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY a index t1_c2 t1_c2 10 NULL # 16.00 20.00 25.00 Using where; Using index; LooseScan +1 PRIMARY t1 ref t1_c2 t1_c2 5 test.a.c2 # 5.00 5.00 100.00 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view +# +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 +create table tmp as select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +explain select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 5 const 8 Using where +2 DEPENDENT SUBQUERY a ref t1_c2 t1_c2 5 test.t1.c2 5 Using index +explain delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 5 const 8 Using where +2 DEPENDENT SUBQUERY a ref t1_c2 t1_c2 5 test.t1.c2 5 Using index +delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +affected rows: 0 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view using reference +# to the same view in subquery +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +create table tmp as select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +explain select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 10 const,const # Using where +1 PRIMARY t1 ref t1_c2 t1_c2 10 const,const # Using index; FirstMatch(t1) +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL # Using where +explain delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 10 const,const # Using where +3 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,func # Using where; Using index +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL # Using where +analyze delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ref t1_c2 t1_c2 10 const,const # 1.00 100.00 100.00 Using where +3 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,func # 1.00 100.00 100.00 Using where; Using index +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL # 32.00 100.00 3.12 Using where +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +####################################### +# Test with a primary key # +####################################### +drop index t1_c2 on t1; +alter table t1 add primary key (c3); +# +# Delete with value from subquery on the same table +# +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 +create table tmp as select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +explain select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using index +explain delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using index +delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 4 +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +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 +create table tmp as select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +explain select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +analyze delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 9.38 9.38 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 13.33 3.12 5.00 Using where; FirstMatch(t1) +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with IN predicand over the updated table in WHERE +# +create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c1 1 Using where; End temporary +explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c1 1 Using where; End temporary +delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +affected rows: 8 +select * from t1; +c1 c2 c3 +1 3 3 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit - can be deleted +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 Using where; End temporary +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 Using where; End temporary +analyze delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 4.00 100.00 100.00 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 1.00 3.12 25.00 Using where; End temporary +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit and an order by +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index PRIMARY PRIMARY 4 NULL 1 +1 PRIMARY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using where +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index NULL PRIMARY 4 NULL 1 Using where +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using where +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +affected rows: 1 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete: 2 execution of PS +# +prepare create_tmp_stmt from +"create table tmp as select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +prepare delete_t1_stmt from +"delete from t1 where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=5; +execute create_tmp_stmt using @a; +execute delete_t1_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 6 38 +prepare insert_tmp_stmt from +"insert into tmp(c1,c2,c3) select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=2; +execute insert_tmp_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +2 1 4 +2 3 6 +2 4 7 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +drop table tmp; +# +# Delete in stored procedure +# +create procedure sp() +begin +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +end +// +create table tmp as select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop procedure sp; +drop table tmp; +# +# Delete in stored function +# +create function f1(IN a INT) returns int +begin +delete from t1 where c3 < a order by c3 limit 1; +return 1; +end;// +set @a:=7; +create table tmp as select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +insert into tmp(c1,c2,c3) select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop function f1; +drop table tmp; +# +# Delete in trigger +# +create table t2 (c1 integer); +insert into t2(c1) values (1), (2), (3), (4), (5), (6), (7), (8); +CREATE TABLE cnt(del integer); +INSERT INTO cnt VALUES(0); +CREATE TRIGGER tr1 AFTER DELETE ON t1 FOR EACH ROW +UPDATE cnt SET del=del+1; +CREATE TRIGGER tr2 AFTER DELETE ON t1 FOR EACH ROW +DELETE FROM t2 WHERE c1> (SELECT count(*)-1 FROM t2); +CREATE TABLE tmp as SELECT * FROM t1 WHERE c2>=3; +DELETE FROM t1 WHERE c2>=3; +affected rows: 20 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +SELECT * FROM t2; +c1 +SELECT * FROM cnt; +del +20 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +DROP TRIGGER tr1; +DROP TRIGGER tr2; +drop table t2, cnt, tmp; +# +# Delete with a reference to view in subquery +# +create table tmp as select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +explain select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +explain delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +analyze delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 32.00 100.00 25.00 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 32.00 25.00 3.12 Using where +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +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 +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +affected rows: 8 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 4 7 +2 5 8 +21 2 21 +21 4 23 +22 2 24 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 4 33 +32 2 34 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with order by +# +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 +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func # +2 MATERIALIZED a ALL NULL NULL NULL NULL # +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func # +2 MATERIALIZED a ALL NULL NULL NULL NULL # +analyze delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # 32.00 62.50 62.50 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func # 1.00 100.00 100.00 +2 MATERIALIZED a ALL NULL NULL NULL NULL # 32.00 62.50 100.00 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view +# +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 +create table tmp as select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +explain select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 const PRIMARY PRIMARY 4 const 1 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +explain delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 const PRIMARY PRIMARY 4 const 1 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +affected rows: 0 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view using reference +# to the same view in subquery +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +create table tmp as select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +explain select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 # +explain delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL # Using where +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 # +analyze delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL # 32.00 3.91 3.12 Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL # 3.00 25.00 33.33 Using where +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 # 1.00 100.00 100.00 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +drop view v1; +drop table t1; +# +# Test on dynamic columns (blob) +# +create table assets ( +item_name varchar(32) primary key, -- A common attribute for all items +dynamic_cols blob -- Dynamic columns will be stored here +); +INSERT INTO assets +VALUES ('MariaDB T-shirt', +COLUMN_CREATE('color', 'blue', 'size', 'XL')); +INSERT INTO assets +VALUES ('Thinkpad Laptop', +COLUMN_CREATE('color', 'black', 'price', 500)); +INSERT INTO assets +VALUES ('Fridge', +COLUMN_CREATE('color', 'white', 'warranty', '5 years')); +INSERT INTO assets +VALUES ('Microwave', +COLUMN_CREATE('warranty', '3 years')); +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color +FROM assets ORDER BY item_name; +item_name color +Fridge white +MariaDB T-shirt blue +Microwave NULL +Thinkpad Laptop black +UPDATE assets SET dynamic_cols=COLUMN_DELETE(dynamic_cols, 'color') +WHERE item_name='Fridge'; +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color +FROM assets ORDER BY item_name; +item_name color +Fridge NULL +MariaDB T-shirt blue +Microwave NULL +Thinkpad Laptop black +DELETE FROM assets +WHERE item_name in +(select b.item_name from assets b +where COLUMN_GET(b.dynamic_cols, 'color' as char) ='black'); +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color +FROM assets ORDER BY item_name; +item_name color +Fridge NULL +MariaDB T-shirt blue +Microwave NULL +DELETE FROM assets WHERE item_name='Microwave'; +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color +FROM assets ORDER BY item_name; +item_name color +Fridge NULL +MariaDB T-shirt blue +drop table assets ; +# +# Test on fulltext columns +# +CREATE TABLE ft2(copy TEXT,FULLTEXT(copy)); +INSERT INTO ft2(copy) VALUES +('MySQL vs MariaDB database'), +('Oracle vs MariaDB database'), +('PostgreSQL vs MariaDB database'), +('MariaDB overview'), +('Foreign keys'), +('Primary keys'), +('Indexes'), +('Transactions'), +('Triggers'); +SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('database'); +copy +MySQL vs MariaDB database +Oracle vs MariaDB database +PostgreSQL vs MariaDB database +DELETE FROM ft2 WHERE MATCH(copy) AGAINST('database'); +SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('database'); +copy +drop table ft2; +####################################### +# # +# Engine MEMORY # +# # +####################################### +set default_storage_engine=MEMORY; +create table t1 (c1 integer, c2 integer, c3 integer); +insert into t1(c1,c2,c3) +values (1,1,1),(1,2,2),(1,3,3), +(2,1,4),(2,2,5),(2,3,6), +(2,4,7),(2,5,8); +insert into t1 select c1+10,c2,c3+10 from t1; +insert into t1 select c1+20,c2+1,c3+20 from t1; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +create view v1 as select * from t1 where c2=2; +####################################### +# Test without any index # +####################################### +# +# Delete with value from subquery on the same table +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +create table tmp as select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +explain select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +explain delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 4 +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +create table tmp as select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +explain select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +affected rows: 2 +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +affected rows: 8 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 4 7 +2 5 8 +21 2 21 +21 4 23 +22 2 24 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 4 33 +32 2 34 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with order by +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +affected rows: 20 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with IN predicand over the updated table in WHERE +# +create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +affected rows: 8 +select * from t1; +c1 c2 c3 +1 3 3 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit - can be deleted +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +affected rows: 1 +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit and an order by +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using temporary; Using filesort +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +affected rows: 1 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete: 2 execution of PS +# +prepare create_tmp_stmt from +"create table tmp as select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +prepare delete_t1_stmt from +"delete from t1 where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=5; +execute create_tmp_stmt using @a; +execute delete_t1_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 6 38 +prepare insert_tmp_stmt from +"insert into tmp(c1,c2,c3) select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=2; +execute insert_tmp_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +2 1 4 +2 3 6 +2 4 7 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +drop table tmp; +# +# Delete in stored procedure +# +create procedure sp() +begin +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +end +// +create table tmp as select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop procedure sp; +drop table tmp; +# +# Delete in stored function +# +create function f1(IN a INT) returns int +begin +delete from t1 where c3 < a order by c3 limit 1; +return 1; +end;// +set @a:=7; +create table tmp as select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +insert into tmp(c1,c2,c3) select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop function f1; +drop table tmp; +# +# Delete in trigger +# +create table t2 (c1 integer); +insert into t2(c1) values (1), (2), (3), (4), (5), (6), (7), (8); +CREATE TABLE cnt(del integer); +INSERT INTO cnt VALUES(0); +CREATE TRIGGER tr1 AFTER DELETE ON t1 FOR EACH ROW +UPDATE cnt SET del=del+1; +CREATE TRIGGER tr2 AFTER DELETE ON t1 FOR EACH ROW +DELETE FROM t2 WHERE c1> (SELECT count(*)-1 FROM t2); +CREATE TABLE tmp as SELECT * FROM t1 WHERE c2>=3; +DELETE FROM t1 WHERE c2>=3; +affected rows: 20 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +SELECT * FROM t2; +c1 +SELECT * FROM cnt; +del +20 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +DROP TRIGGER tr1; +DROP TRIGGER tr2; +drop table t2, cnt, tmp; +# +Delete with a reference to view in subquery +# +create table tmp as select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +explain select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +explain delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +affected rows: 8 +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +create table tmp as select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +explain select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +explain delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +affected rows: 0 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view using reference +# to the same view in subquery +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +create table tmp as select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +explain select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +explain delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +affected rows: 1 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +####################################### +# Test with an index # +####################################### +create index t1_c2 on t1 (c2,c1); +# +# Delete with value from subquery on the same table +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +create table tmp as select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +explain select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +explain delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 4 +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +create table tmp as select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +explain select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +affected rows: 2 +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ALL t1_c2 NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ALL t1_c2 NULL NULL NULL 32 Using where; FirstMatch(t1) +delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +affected rows: 8 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 4 7 +2 5 8 +21 2 21 +21 4 23 +22 2 24 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 4 33 +32 2 34 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with order by +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL t1_c2 NULL NULL NULL 32 +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL t1_c2 NULL NULL NULL 32 +delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +affected rows: 20 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with IN predicand over the updated table in WHERE +# +create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 10 test.t1.c2,test.t1.c3 2 FirstMatch(t1) +explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 10 test.t1.c2,test.t1.c3 2 FirstMatch(t1) +delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +affected rows: 8 +select * from t1; +c1 c2 c3 +1 3 3 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit - can be deleted +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL t1_c2 NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL t1_c2 NULL NULL NULL 32 Using where; FirstMatch(t1) +delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +affected rows: 1 +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit and an order by +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using temporary; Using filesort +1 PRIMARY a ALL t1_c2 NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +2 DEPENDENT SUBQUERY a ALL t1_c2 NULL NULL NULL 32 Using where +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +affected rows: 1 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete: 2 execution of PS +# +prepare create_tmp_stmt from +"create table tmp as select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +prepare delete_t1_stmt from +"delete from t1 where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=5; +execute create_tmp_stmt using @a; +execute delete_t1_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 6 38 +prepare insert_tmp_stmt from +"insert into tmp(c1,c2,c3) select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=2; +execute insert_tmp_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +2 1 4 +2 3 6 +2 4 7 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +drop table tmp; +# +# Delete in stored procedure +# +create procedure sp() +begin +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +end +// +create table tmp as select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop procedure sp; +drop table tmp; +# +# Delete in stored function +# +create function f1(IN a INT) returns int +begin +delete from t1 where c3 < a order by c3 limit 1; +return 1; +end;// +set @a:=7; +create table tmp as select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +insert into tmp(c1,c2,c3) select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop function f1; +drop table tmp; +# +# Delete in trigger +# +create table t2 (c1 integer); +insert into t2(c1) values (1), (2), (3), (4), (5), (6), (7), (8); +CREATE TABLE cnt(del integer); +INSERT INTO cnt VALUES(0); +CREATE TRIGGER tr1 AFTER DELETE ON t1 FOR EACH ROW +UPDATE cnt SET del=del+1; +CREATE TRIGGER tr2 AFTER DELETE ON t1 FOR EACH ROW +DELETE FROM t2 WHERE c1> (SELECT count(*)-1 FROM t2); +CREATE TABLE tmp as SELECT * FROM t1 WHERE c2>=3; +DELETE FROM t1 WHERE c2>=3; +affected rows: 20 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +SELECT * FROM t2; +c1 +SELECT * FROM cnt; +del +20 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +DROP TRIGGER tr1; +DROP TRIGGER tr2; +drop table t2, cnt, tmp; +# +Delete with a reference to view in subquery +# +create table tmp as select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +explain select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 2 +explain delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 2 +delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +affected rows: 8 +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +create table tmp as select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +explain select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL t1_c2 NULL NULL NULL 32 Using where +explain delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL t1_c2 NULL NULL NULL 32 Using where +delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +affected rows: 0 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view using reference +# to the same view in subquery +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +create table tmp as select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +explain select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 10 const,const 2 Using where +1 PRIMARY t1 ref t1_c2 t1_c2 10 const,const 2 FirstMatch(t1) +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +explain delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 10 const,const 2 Using where +3 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,func 2 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +affected rows: 1 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +####################################### +# Test with a primary key # +####################################### +drop index t1_c2 on t1; +alter table t1 add primary key (c3); +# +# Delete with value from subquery on the same table +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +create table tmp as select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +explain select * from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 +explain delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 +delete from t1 where c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 4 +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +create table tmp as select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +explain select * from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +delete from t1 where c1 = 1 and exists (select 'X' from t1 a where a.c1 = t1.c2); +affected rows: 2 +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 = 3; +affected rows: 8 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 4 7 +2 5 8 +21 2 21 +21 4 23 +22 2 24 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 4 33 +32 2 34 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with order by +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +create table tmp as select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +delete from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +affected rows: 20 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with IN predicand over the updated table in WHERE +# +create table tmp as select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +explain select * from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c1 1 Using where; End temporary +explain delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c1 1 Using where; End temporary +delete from t1 where c3 in (select distinct a.c1 from t1 a where t1.c2=a.c2); +affected rows: 8 +select * from t1; +c1 c2 c3 +1 3 3 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit - can be deleted +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 Using where; End temporary +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; Start temporary +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.a.c2 1 Using where; End temporary +delete from t1 where c1 in (select a.c2 from t1 a where a.c2 = t1.c3) limit 1; +affected rows: 1 +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete with a limit and an order by +# +create table tmp as select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +explain select * from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32 Using filesort +1 PRIMARY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using where +explain delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using where +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +affected rows: 1 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete: 2 execution of PS +# +prepare create_tmp_stmt from +"create table tmp as select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +prepare delete_t1_stmt from +"delete from t1 where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=5; +execute create_tmp_stmt using @a; +execute delete_t1_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 6 38 +prepare insert_tmp_stmt from +"insert into tmp(c1,c2,c3) select * from t1 + where c2=(select a.c3 from t1 a where a.c3 = ?)"; +set @a:=2; +execute insert_tmp_stmt using @a; +execute delete_t1_stmt using @a; +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +2 1 4 +2 3 6 +2 4 7 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +drop table tmp; +# +# Delete in stored procedure +# +create procedure sp() +begin +delete from t1 where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +end +// +create table tmp as select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +insert into tmp(c1,c2,c3) select * from t1 +where c1 in (select a.c2 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 1; +CALL sp; +select * from t1; +c1 c2 c3 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop procedure sp; +drop table tmp; +# +# Delete in stored function +# +create function f1(IN a INT) returns int +begin +delete from t1 where c3 < a order by c3 limit 1; +return 1; +end;// +set @a:=7; +create table tmp as select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +insert into tmp(c1,c2,c3) select * from t1 where c3 < @a +order by c3 limit 1; +select f1(@a); +f1(@a) +1 +select * from t1; +c1 c2 c3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop function f1; +drop table tmp; +# +# Delete in trigger +# +create table t2 (c1 integer); +insert into t2(c1) values (1), (2), (3), (4), (5), (6), (7), (8); +CREATE TABLE cnt(del integer); +INSERT INTO cnt VALUES(0); +CREATE TRIGGER tr1 AFTER DELETE ON t1 FOR EACH ROW +UPDATE cnt SET del=del+1; +CREATE TRIGGER tr2 AFTER DELETE ON t1 FOR EACH ROW +DELETE FROM t2 WHERE c1> (SELECT count(*)-1 FROM t2); +CREATE TABLE tmp as SELECT * FROM t1 WHERE c2>=3; +DELETE FROM t1 WHERE c2>=3; +affected rows: 20 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +11 1 11 +11 2 12 +12 1 14 +12 2 15 +2 1 4 +2 2 5 +21 2 21 +22 2 24 +31 2 31 +32 2 34 +SELECT * FROM t2; +c1 +SELECT * FROM cnt; +del +20 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +DROP TRIGGER tr1; +DROP TRIGGER tr2; +drop table t2, cnt, tmp; +# +Delete with a reference to view in subquery +# +create table tmp as select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +explain select * from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +explain delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +delete from t1 where t1.c2 in ( select max(a.c2) from v1 a +where a.c1 = t1.c1); +affected rows: 8 +select * from t1; +c1 c2 c3 +1 1 1 +1 3 3 +11 1 11 +11 3 13 +12 1 14 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 3 22 +21 4 23 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 3 32 +31 4 33 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +create table tmp as select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +explain select * from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 const PRIMARY PRIMARY 4 const 1 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +explain delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 const PRIMARY PRIMARY 4 const 1 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +delete from v1 where v1.c1 in +(select max(a.c1) from t1 a where a.c2 = v1.c2) and c3 = 5; +affected rows: 0 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +# +# Delete from view using reference +# to the same view in subquery +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +create table tmp as select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +explain select * from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 +explain delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 +delete from v1 where v1.c2 in (select max(a.c2) from t1 a where a.c3 = v1.c3) +and c1 = 2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +affected rows: 1 +select * from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +insert into t1(c1,c2,c3) select c1,c2,c3 from tmp; +drop table tmp; +drop view v1; +drop table t1; +set @@default_storage_engine=@save_default_engine; +# +# End of 11.0 tests +# diff --git a/mysql-test/main/delete_use_source_engines.test b/mysql-test/main/delete_use_source_engines.test new file mode 100644 index 00000000000..1a0d98f8399 --- /dev/null +++ b/mysql-test/main/delete_use_source_engines.test @@ -0,0 +1,42 @@ +--source include/have_innodb.inc + +set @save_default_engine=@@default_storage_engine; + +--echo ####################################### +--echo # # +--echo # Engine InnoDB # +--echo # # +--echo ####################################### +set global innodb_stats_persistent=1; +set default_storage_engine=InnoDB; +--source include/delete_use_source_innodb.inc + +--echo ####################################### +--echo # # +--echo # Engine Aria # +--echo # # +--echo ####################################### +set default_storage_engine=Aria; +--source include/delete_use_source.inc + +--echo ####################################### +--echo # # +--echo # Engine MyISAM # +--echo # # +--echo ####################################### +set default_storage_engine=MyISAM; +--source include/delete_use_source.inc + +--echo ####################################### +--echo # # +--echo # Engine MEMORY # +--echo # # +--echo ####################################### +set default_storage_engine=MEMORY; +--source include/delete_use_source_memory.inc + +set @@default_storage_engine=@save_default_engine; + +--echo # +--echo # End of 11.0 tests +--echo # diff --git a/mysql-test/main/derived.result b/mysql-test/main/derived.result index 091ca13d579..0c23f558757 100644 --- a/mysql-test/main/derived.result +++ b/mysql-test/main/derived.result @@ -1529,3 +1529,340 @@ DROP TABLE t1; # # End of 11.0 tests # +# +# MDEV-28883: single/multi-table UPDATE/DELETE whose WHERE condition +# contains subquery from mergeable derived table +# that uses the updated/deleted table +# +create table t1 (pk int, a int); +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +explain update t1 set a = 10 +where a = ( select * from (select a from t1) dt where dt.a > 7); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where +2 SUBQUERY t1 ALL NULL NULL NULL NULL 4 Using where +update t1 set a = 10 +where a = ( select * from (select a from t1) dt where dt.a > 7); +select * from t1; +pk a +1 3 +2 7 +3 1 +4 10 +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +prepare stmt from "update t1 set a = 10 +where a = ( select * from (select a from t1) dt where dt.a > 7)"; +execute stmt; +select * from t1; +pk a +1 3 +2 7 +3 1 +4 10 +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +execute stmt; +select * from t1; +pk a +4 10 +3 1 +1 3 +deallocate prepare stmt; +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +explain update t1 set a = 10 +where a <> ( select * from (select a from t1) dt where dt.a > 7) +order by a limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Using filesort +2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where +update t1 set a = 10 +where a <> ( select * from (select a from t1) dt where dt.a > 7) +order by a limit 2; +select * from t1; +pk a +4 9 +3 10 +1 10 +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +prepare stmt from "update t1 set a = 10 +where a <> ( select * from (select a from t1) dt where dt.a > 7) +order by a limit 2"; +execute stmt; +select * from t1; +pk a +4 9 +3 10 +1 10 +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +execute stmt; +select * from t1; +pk a +4 9 +3 10 +1 10 +deallocate prepare stmt; +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +explain delete from t1 +where a = ( select * from (select a from t1) dt where dt.a > 7); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where +2 SUBQUERY t1 ALL NULL NULL NULL NULL 4 Using where +delete from t1 +where a = ( select * from (select a from t1) dt where dt.a > 7); +select * from t1; +pk a +1 3 +2 7 +3 1 +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +prepare stmt from "delete from t1 +where a = ( select * from (select a from t1) dt where dt.a > 7)"; +execute stmt; +select * from t1; +pk a +1 3 +2 7 +3 1 +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +execute stmt; +select * from t1; +pk a +3 1 +1 3 +deallocate prepare stmt; +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +explain delete from t1 +where a = ( select * from (select a from t1) dt where dt.a > 5) +returning pk, a; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where +2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where +delete from t1 +where a = ( select * from (select a from t1) dt where dt.a > 5) +returning pk, a; +pk a +4 9 +select * from t1; +pk a +3 1 +1 3 +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +prepare stmt from "delete from t1 +where a = ( select * from (select a from t1) dt where dt.a > 5) +returning pk, a"; +execute stmt; +pk a +4 9 +select * from t1; +pk a +3 1 +1 3 +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +execute stmt; +pk a +4 9 +select * from t1; +pk a +3 1 +1 3 +deallocate prepare stmt; +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +explain delete from t1 +where a <> ( select * from (select a from t1) dt where dt.a > 7) +order by a limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using filesort +2 SUBQUERY t1 ALL NULL NULL NULL NULL 4 Using where +delete from t1 +where a <> ( select * from (select a from t1) dt where dt.a > 7) +order by a limit 2; +select * from t1; +pk a +2 7 +4 9 +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +prepare stmt from "delete from t1 +where a <> ( select * from (select a from t1) dt where dt.a > 7) +order by a limit 2"; +execute stmt; +select * from t1; +pk a +2 7 +4 9 +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +execute stmt; +select * from t1; +pk a +2 7 +4 9 +deallocate prepare stmt; +create table t2 (pk int, a int); +insert into t2 values (1,3), (2, 7), (3,1), (4,9); +create table t3 (a int); +insert into t3 VALUES (0),(1); +explain update t1,t3 set t1.a = 1 +where t1.a=t3.a and +t1.a = ( select * from (select a from t1) dt where dt.a > 7); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where +2 SUBQUERY <derived3> ALL NULL NULL NULL NULL 2 Using where +3 DERIVED t1 ALL NULL NULL NULL NULL 2 Using where +update t1,t3 set t1.a = 1 +where t1.a=t3.a and +t1.a = ( select * from (select a from t1) dt where dt.a > 7); +select * from t1; +pk a +2 7 +4 9 +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +prepare stmt from "update t1,t3 set t1.a = 1 +where t1.a=t3.a and +t1.a = ( select * from (select a from t1) dt where dt.a > 7)"; +execute stmt; +select * from t1; +pk a +1 3 +2 7 +3 1 +4 9 +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +execute stmt; +select * from t1; +pk a +4 9 +3 1 +1 3 +deallocate prepare stmt; +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +explain update t1,t3 set t1.a = 1 +where t1.a=t3.a and +t1.a = ( select * from (select a from t2) dt where dt.a > 7); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where +2 SUBQUERY <derived3> ALL NULL NULL NULL NULL 4 Using where +3 DERIVED t2 ALL NULL NULL NULL NULL 4 Using where +update t1,t3 set t1.a = 1 +where t1.a=t3.a and +t1.a = ( select * from (select a from t2) dt where dt.a > 7); +select * from t1; +pk a +1 3 +2 7 +3 1 +4 9 +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +prepare stmt from "update t1,t3 set t1.a = 1 +where t1.a=t3.a and +t1.a = ( select * from (select a from t2) dt where dt.a > 7)"; +execute stmt; +select * from t1; +pk a +1 3 +2 7 +3 1 +4 9 +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +execute stmt; +select * from t1; +pk a +4 9 +3 1 +1 3 +deallocate prepare stmt; +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +insert into t3 values (9), (10), (7); +explain delete from t1 using t1,t3 +where t1.a=t3.a and +t1.a = ( select * from (select a from t1) dt where dt.a > 7); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where +1 PRIMARY t3 ALL NULL NULL NULL NULL 5 Using where +2 SUBQUERY <derived3> ALL NULL NULL NULL NULL 4 Using where +3 DERIVED t1 ALL NULL NULL NULL NULL 4 Using where +delete from t1 using t1,t3 +where t1.a=t3.a and +t1.a = ( select * from (select a from t1) dt where dt.a > 7); +select * from t1; +pk a +1 3 +2 7 +3 1 +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +prepare stmt from "delete from t1 using t1,t3 +where t1.a=t3.a and +t1.a = ( select * from (select a from t1) dt where dt.a > 7)"; +execute stmt; +select * from t1; +pk a +1 3 +2 7 +3 1 +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +execute stmt; +select * from t1; +pk a +3 1 +1 3 +deallocate prepare stmt; +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +explain delete from t1 using t1,t3 +where t1.a=t3.a and +t1.a = ( select * from (select a from t2) dt where dt.a > 7); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where +1 PRIMARY t3 ALL NULL NULL NULL NULL 5 Using where +2 SUBQUERY <derived3> ALL NULL NULL NULL NULL 4 Using where +3 DERIVED t2 ALL NULL NULL NULL NULL 4 Using where +delete from t1 using t1,t3 +where t1.a=t3.a and +t1.a = ( select * from (select a from t2) dt where dt.a > 7); +select * from t1; +pk a +1 3 +2 7 +3 1 +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +prepare stmt from "delete from t1 using t1,t3 +where t1.a=t3.a and +t1.a = ( select * from (select a from t2) dt where dt.a > 7)"; +execute stmt; +select * from t1; +pk a +1 3 +2 7 +3 1 +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +execute stmt; +select * from t1; +pk a +3 1 +1 3 +deallocate prepare stmt; +drop table t1,t2,t3; +# End of MariaDB 11.1 tests diff --git a/mysql-test/main/derived.test b/mysql-test/main/derived.test index 78ccba0b362..772d7be2ace 100644 --- a/mysql-test/main/derived.test +++ b/mysql-test/main/derived.test @@ -1300,3 +1300,211 @@ DROP TABLE t1; --echo # --echo # End of 11.0 tests --echo # + +--echo # +--echo # MDEV-28883: single/multi-table UPDATE/DELETE whose WHERE condition +--echo # contains subquery from mergeable derived table +--echo # that uses the updated/deleted table +--echo # + +create table t1 (pk int, a int); +insert into t1 values (1,3), (2, 7), (3,1), (4,9); + +let $q1= +update t1 set a = 10 + where a = ( select * from (select a from t1) dt where dt.a > 7); + +eval explain $q1; +eval $q1; +select * from t1; +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +eval prepare stmt from "$q1"; +execute stmt; +select * from t1; +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +execute stmt; +select * from t1; +deallocate prepare stmt; + +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); + +let $q2= +update t1 set a = 10 + where a <> ( select * from (select a from t1) dt where dt.a > 7) +order by a limit 2; +eval explain $q2; +eval $q2; +select * from t1; +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +eval prepare stmt from "$q2"; +execute stmt; +select * from t1; +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +execute stmt; +select * from t1; +deallocate prepare stmt; + +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); + +let $q3= +delete from t1 + where a = ( select * from (select a from t1) dt where dt.a > 7); + +eval explain $q3; +eval $q3; +select * from t1; +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +eval prepare stmt from "$q3"; +execute stmt; +select * from t1; +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +execute stmt; +select * from t1; +deallocate prepare stmt; + +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); + +let $q4= +delete from t1 + where a = ( select * from (select a from t1) dt where dt.a > 5) +returning pk, a; + +eval explain $q4; +eval $q4; +select * from t1; +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +eval prepare stmt from "$q4"; +execute stmt; +select * from t1; +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +execute stmt; +select * from t1; +deallocate prepare stmt; + +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); + +let $q5= +delete from t1 + where a <> ( select * from (select a from t1) dt where dt.a > 7) +order by a limit 2; +eval explain $q5; +eval $q5; +select * from t1; +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +eval prepare stmt from "$q5"; +execute stmt; +select * from t1; +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +execute stmt; +select * from t1; +deallocate prepare stmt; + +create table t2 (pk int, a int); +insert into t2 values (1,3), (2, 7), (3,1), (4,9); +create table t3 (a int); +insert into t3 VALUES (0),(1); + +let $q6= +update t1,t3 set t1.a = 1 + where t1.a=t3.a and + t1.a = ( select * from (select a from t1) dt where dt.a > 7); + +eval explain $q6; +eval $q6; +select * from t1; +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +eval prepare stmt from "$q6"; +execute stmt; +select * from t1; +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +execute stmt; +select * from t1; +deallocate prepare stmt; + +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); + +let $q7= +update t1,t3 set t1.a = 1 + where t1.a=t3.a and + t1.a = ( select * from (select a from t2) dt where dt.a > 7); + +eval explain $q7; +eval $q7; +select * from t1; +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +eval prepare stmt from "$q7"; +execute stmt; +select * from t1; +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +execute stmt; +select * from t1; +deallocate prepare stmt; + +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +insert into t3 values (9), (10), (7); + +let $q8= +delete from t1 using t1,t3 + where t1.a=t3.a and + t1.a = ( select * from (select a from t1) dt where dt.a > 7); + +eval explain $q8; +eval $q8; +select * from t1; +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +eval prepare stmt from "$q8"; +execute stmt; +select * from t1; +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +execute stmt; +select * from t1; +deallocate prepare stmt; + +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); + +let $q9= +delete from t1 using t1,t3 + where t1.a=t3.a and + t1.a = ( select * from (select a from t2) dt where dt.a > 7); + +eval explain $q9; +eval $q9; +select * from t1; +delete from t1; +insert into t1 values (1,3), (2, 7), (3,1), (4,9); +eval prepare stmt from "$q9"; +execute stmt; +select * from t1; +delete from t1; +insert into t1 value (4,9), (3,1), (1,3); +execute stmt; +select * from t1; +deallocate prepare stmt; + + +drop table t1,t2,t3; + +--echo # End of MariaDB 11.1 tests diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index c4ed53ee311..76f899edc96 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -13098,7 +13098,7 @@ DROP TABLE t1; # CREATE TABLE t1 (f1 text, f2 int); INSERT INTO t1 VALUES ('x',1), ('y',2); -CREATE VIEW v1 AS SELECT f2 FROM ( SELECT f2 FROM t1 ) AS t; +CREATE VIEW v1 AS SELECT f2 FROM ( SELECT f2 FROM t1 GROUP BY f2) AS t; UPDATE v1, t1 SET t1.f1 = 'z' WHERE v1.f2 < 2 AND t1.f2 = v1.f2; EXPLAIN FORMAT=JSON UPDATE v1, t1 SET t1.f1 = 'z' WHERE v1.f2 < 2 AND t1.f2 = v1.f2; EXPLAIN @@ -13135,19 +13135,24 @@ EXPLAIN "query_block": { "select_id": 3, "cost": "COST_REPLACED", - "nested_loop": [ - { - "table": { - "table_name": "t1", - "access_type": "ALL", - "loops": 1, - "rows": 2, - "cost": "COST_REPLACED", - "filtered": 100, - "attached_condition": "t1.f2 < 2" - } + "filesort": { + "sort_key": "t1.f2", + "temporary_table": { + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "loops": 1, + "rows": 2, + "cost": "COST_REPLACED", + "filtered": 100, + "attached_condition": "t1.f2 < 2" + } + } + ] } - ] + } } } } diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test index b1f3ec86c3f..5bd1489db78 100644 --- a/mysql-test/main/derived_cond_pushdown.test +++ b/mysql-test/main/derived_cond_pushdown.test @@ -2219,7 +2219,7 @@ DROP TABLE t1; CREATE TABLE t1 (f1 text, f2 int); INSERT INTO t1 VALUES ('x',1), ('y',2); -CREATE VIEW v1 AS SELECT f2 FROM ( SELECT f2 FROM t1 ) AS t; +CREATE VIEW v1 AS SELECT f2 FROM ( SELECT f2 FROM t1 GROUP BY f2) AS t; let $q1 = UPDATE v1, t1 SET t1.f1 = 'z' WHERE v1.f2 < 2 AND t1.f2 = v1.f2; eval $q1; diff --git a/mysql-test/main/events_skip_grant_tables-master.opt b/mysql-test/main/events_skip_grant_tables-master.opt new file mode 100644 index 00000000000..3cf617286a2 --- /dev/null +++ b/mysql-test/main/events_skip_grant_tables-master.opt @@ -0,0 +1 @@ +--event-scheduler=ON --skip-grant-tables diff --git a/mysql-test/main/events_skip_grant_tables.result b/mysql-test/main/events_skip_grant_tables.result new file mode 100644 index 00000000000..2bd2e383a23 --- /dev/null +++ b/mysql-test/main/events_skip_grant_tables.result @@ -0,0 +1,8 @@ +call mtr.add_suppression("Event Scheduler will not function when starting with --skip-grant-tables or --bootstrap."); +CREATE EVENT test ON SCHEDULE AT CURRENT_TIMESTAMP DO DO NULL; +ERROR HY000: Event scheduler cannot function with --skip-grant-tables, --bootstrap, or embedded build +select (@@global.event_scheduler='DISABLED') as expect_1; +expect_1 +1 +set global event_scheduler=1; +ERROR HY000: The MariaDB server is running with the --event-scheduler=DISABLED or --skip-grant-tables option so it cannot execute this statement diff --git a/mysql-test/main/events_skip_grant_tables.test b/mysql-test/main/events_skip_grant_tables.test new file mode 100644 index 00000000000..b19178294b8 --- /dev/null +++ b/mysql-test/main/events_skip_grant_tables.test @@ -0,0 +1,18 @@ +# Can't test with embedded server that doesn't support grants +-- source include/not_embedded.inc +call mtr.add_suppression("Event Scheduler will not function when starting with --skip-grant-tables or --bootstrap."); + +# [MARIADB-29827] Verify that if server is started with +# --event-scheduler=ON --skip-grant-tables, we get an error +# with a distinct explanation that the latter disables the former. + +--error ER_EVENTS_NO_ACL +CREATE EVENT test ON SCHEDULE AT CURRENT_TIMESTAMP DO DO NULL; + +# Although --event-scheduler=ON was specified (see -master.opt), it should +# have been changed to 'DISABLED' at startup. +select (@@global.event_scheduler='DISABLED') as expect_1; + +# Verify that we cannot (re)enable event scheduler +--error ER_OPTION_PREVENTS_STATEMENT +set global event_scheduler=1; diff --git a/mysql-test/main/explain_innodb.result b/mysql-test/main/explain_innodb.result index 39190d597cd..03052eb3006 100644 --- a/mysql-test/main/explain_innodb.result +++ b/mysql-test/main/explain_innodb.result @@ -29,9 +29,9 @@ INSERT INTO t2 VALUES (1),(2); EXPLAIN EXTENDED DELETE FROM t1 WHERE a IN (SELECT pk FROM t2); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where -2 DEPENDENT SUBQUERY t2 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index +1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 100.00 Using index Warnings: -Note 1003 /* select#1 */ delete from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`a`)))) +Note 1003 delete from `test`.`t1` using `test`.`t2` where `test`.`t2`.`pk` = `test`.`t1`.`a` drop table t1, t2; # # End of 10.4 tests diff --git a/mysql-test/main/explain_non_select.result b/mysql-test/main/explain_non_select.result index 2eb46db4c67..e998d8745c1 100644 --- a/mysql-test/main/explain_non_select.result +++ b/mysql-test/main/explain_non_select.result @@ -163,7 +163,7 @@ explain extended delete from t2 where a in (3,4); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 delete from `test`.`t2` where `test`.`t2`.`a` in (3,4) +Note 1003 delete from `test`.`t2` using dual where `test`.`t2`.`a` in (3,4) drop table t1,t2; # # Check the special case where partition pruning removed all partitions diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index 8cbc5305405..f202de76359 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -2580,3 +2580,2158 @@ JSON_EXTRACT('{ "my-key": 1 }', '$.my-key') # # End of 10.9 Test # +# Beginning of 11.1 test +# +# MDEV-27128: Implement JSON Schema Validation FUNCTION +# +# Checking annotations +SET @schema_number= '{ + "title" : "This is title 1", + "description":"this is description 1", + "$comment":"This is comment 1", + "type":"number", + "deprecated":true, + "readOnly":true, + "writeOnly":false, + "example":[2], + "default":4, + "$schema": "https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5" + }'; +SELECT JSON_SCHEMA_VALID(@schema_number, '"string1"'); +JSON_SCHEMA_VALID(@schema_number, '"string1"') +0 +SELECT JSON_SCHEMA_VALID(@schema_number, '2'); +JSON_SCHEMA_VALID(@schema_number, '2') +1 +# Checking empty schema with empty json document +SET @schema= '{}'; +SELECT JSON_SCHEMA_VALID(@schema, ''); +JSON_SCHEMA_VALID(@schema, '') +1 +SELECT JSON_SCHEMA_VALID(@schema, '{}'); +JSON_SCHEMA_VALID(@schema, '{}') +1 +SELECT JSON_SCHEMA_VALID(@schema, '[]'); +JSON_SCHEMA_VALID(@schema, '[]') +1 +SELECT JSON_SCHEMA_VALID(@schema, 'null'); +JSON_SCHEMA_VALID(@schema, 'null') +1 +SELECT JSON_SCHEMA_VALID(@schema, 'true'); +JSON_SCHEMA_VALID(@schema, 'true') +1 +SELECT JSON_SCHEMA_VALID(@schema, 'false'); +JSON_SCHEMA_VALID(@schema, 'false') +1 +# Checking scalar against json schema +# Checking boolean and null +SET @schema_true= '{ "type": "boolean"}'; +SELECT JSON_SCHEMA_VALID(@schema_true, 'true'); +JSON_SCHEMA_VALID(@schema_true, 'true') +1 +SELECT JSON_SCHEMA_VALID(@schema_true, 'false'); +JSON_SCHEMA_VALID(@schema_true, 'false') +1 +SELECT JSON_SCHEMA_VALID(@schema_true, 'null'); +JSON_SCHEMA_VALID(@schema_true, 'null') +0 +SET @schema_true= '{ "type": "boolean", + "const":"false"}'; +SELECT JSON_SCHEMA_VALID(@schema_true, 'true'); +JSON_SCHEMA_VALID(@schema_true, 'true') +0 +SET @schema_true= '{ "type": "boolean", + "enum":[true, null, false]}'; +SELECT JSON_SCHEMA_VALID(@schema_true, 'true'); +JSON_SCHEMA_VALID(@schema_true, 'true') +1 +SET @schema_true= '{ "type": "boolean", + "enum": [null, false]}'; +SELECT JSON_SCHEMA_VALID(@schema_true, 'true'); +JSON_SCHEMA_VALID(@schema_true, 'true') +0 +SET @schema_true= '{ "type": "boolean", + "enum": [null, true]}'; +SELECT JSON_SCHEMA_VALID(@schema_true, 'true'); +JSON_SCHEMA_VALID(@schema_true, 'true') +1 +SET @schema_true= '{ "type": "boolean", + "const":"false"}'; +SELECT JSON_SCHEMA_VALID(@schema_true, 'true'); +JSON_SCHEMA_VALID(@schema_true, 'true') +0 +# Type can be more than one +SET @schema= ' + { + "type":["string", "number","array"] + }'; +SELECT JSON_SCHEMA_VALID(@schema, '{"key1":"val1"}'); +JSON_SCHEMA_VALID(@schema, '{"key1":"val1"}') +0 +SELECT JSON_SCHEMA_VALID(@schema, '"abc"'); +JSON_SCHEMA_VALID(@schema, '"abc"') +1 +SELECT JSON_SCHEMA_VALID(@schema, '3.14'); +JSON_SCHEMA_VALID(@schema, '3.14') +1 +# Checking number +SET @schema_number= '{ + "maximum":7, + "minimum": 3, + "multipleOf":3 +}'; +SELECT JSON_SCHEMA_VALID(@schema_number, '2'); +JSON_SCHEMA_VALID(@schema_number, '2') +0 +SET @schema_number= '{ + "type": "number", + "maximum":13, + "minimum": 4, + "multipleOf":3, + "exclusiveMaximum": 9, + "exclusiveMinimum":4 +}'; +SELECT JSON_SCHEMA_VALID(@schema_number, '2'); +JSON_SCHEMA_VALID(@schema_number, '2') +0 +SELECT JSON_SCHEMA_VALID(@schema_number, '6'); +JSON_SCHEMA_VALID(@schema_number, '6') +1 +SELECT JSON_SCHEMA_VALID(@schema_number, '9'); +JSON_SCHEMA_VALID(@schema_number, '9') +0 +SELECT JSON_SCHEMA_VALID(@schema_number, '5'); +JSON_SCHEMA_VALID(@schema_number, '5') +0 +SET @schema_number= '{ + "type": "number", + "maximum":100, + "minimum": 0, + "enum": [1, 2, "3", [4, 5, 6], {"key1":"val1"}] +}'; +SELECT JSON_SCHEMA_VALID(@schema_number, 1); +JSON_SCHEMA_VALID(@schema_number, 1) +1 +SELECT JSON_SCHEMA_VALID(@schema_number, 3); +JSON_SCHEMA_VALID(@schema_number, 3) +0 +SET @schema_number= '{ + "type":"number", + "maximum":10, + "const":2 + }'; +SELECT JSON_SCHEMA_VALID(@schema_number, '3'); +JSON_SCHEMA_VALID(@schema_number, '3') +0 +SELECT JSON_SCHEMA_VALID(@schema_number, '2'); +JSON_SCHEMA_VALID(@schema_number, '2') +1 +# Checking string +# checking format keyword. (not validating for now) +SET @schema_string= '{ + "type": "string", + "format":"date-time" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_date-time"'); +JSON_SCHEMA_VALID(@schema_string, '"not_date-time"') +1 +SET @schema_string= '{ + "type": "string", + "format":"date" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_date"'); +JSON_SCHEMA_VALID(@schema_string, '"not_date"') +1 +SET @schema_string= '{ + "type": "string", + "format":"time" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_time"'); +JSON_SCHEMA_VALID(@schema_string, '"not_time"') +1 +SET @schema_string= '{ + "type": "string", + "format":"duration" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_duration"'); +JSON_SCHEMA_VALID(@schema_string, '"not_duration"') +1 +SET @schema_string= '{ + "type": "string", + "format":"email" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_email"'); +JSON_SCHEMA_VALID(@schema_string, '"not_email"') +1 +SET @schema_string= '{ + "type": "string", + "format":"idn-email" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_idn-email"'); +JSON_SCHEMA_VALID(@schema_string, '"not_idn-email"') +1 +SET @schema_string= '{ + "type": "string", + "format":"hostname" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_hostname"'); +JSON_SCHEMA_VALID(@schema_string, '"not_hostname"') +1 +SET @schema_string= '{ + "type": "string", + "format":"idn-hostname" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_idn-hostname"'); +JSON_SCHEMA_VALID(@schema_string, '"not_idn-hostname"') +1 +SET @schema_string= '{ + "type": "string", + "format":"ipv4" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_ipv4"'); +JSON_SCHEMA_VALID(@schema_string, '"not_ipv4"') +1 +SET @schema_string= '{ + "type": "string", + "format":"ipv6" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_ipv6"'); +JSON_SCHEMA_VALID(@schema_string, '"not_ipv6"') +1 +SET @schema_string= '{ + "type": "string", + "format":"uri" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_uri"'); +JSON_SCHEMA_VALID(@schema_string, '"not_uri"') +1 +SET @schema_string= '{ + "type": "string", + "format":"uri-reference" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_uri-reference"'); +JSON_SCHEMA_VALID(@schema_string, '"not_uri-reference"') +1 +SET @schema_string= '{ + "type": "string", + "format":"iri" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_iri"'); +JSON_SCHEMA_VALID(@schema_string, '"not_iri"') +1 +SET @schema_string= '{ + "type": "string", + "format":"iri-reference" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_iri-reference"'); +JSON_SCHEMA_VALID(@schema_string, '"not_iri-reference"') +1 +SET @schema_string= '{ + "type": "string", + "format":"uuid" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_uuid"'); +JSON_SCHEMA_VALID(@schema_string, '"not_uuid"') +1 +SET @schema_string= '{ + "type": "string", + "format":"json-pointer" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_json-pointer"'); +JSON_SCHEMA_VALID(@schema_string, '"not_json-pointer"') +1 +SET @schema_string= '{ + "type": "string", + "format":"relative-json-pointer" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_relative-json-pointer"'); +JSON_SCHEMA_VALID(@schema_string, '"not_relative-json-pointer"') +1 +SET @schema_string= '{ + "type": "string", + "format":"regex" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_regex"'); +JSON_SCHEMA_VALID(@schema_string, '"not_regex"') +1 +# Validating other string keywords +SET @schema_string= '{ + "type": "string", + "maxLength":7, + "minLength": 4 +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"foobar"'); +JSON_SCHEMA_VALID(@schema_string, '"foobar"') +1 +SET @schema_string= '{ + "type": "string", + "maxLength": 10, + "minLength": 8 +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"foobar"'); +JSON_SCHEMA_VALID(@schema_string, '"foobar"') +0 +SELECT JSON_SCHEMA_VALID(@schema_string, '"foobar123"'); +JSON_SCHEMA_VALID(@schema_string, '"foobar123"') +1 +SET @schema_string= '{ + "type": "string", + "maxLength": 10, + "minLength": 3, + "const": "foobar" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"foobar123"'); +JSON_SCHEMA_VALID(@schema_string, '"foobar123"') +0 +SET @schema_string= '{ + "type": "string", + "enum": ["red", "green", "blue"] +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"green"'); +JSON_SCHEMA_VALID(@schema_string, '"green"') +1 +SELECT JSON_SCHEMA_VALID(@schema_string, '"orange"'); +JSON_SCHEMA_VALID(@schema_string, '"orange"') +0 +SET @string_schema= '{ + "type":"string", + "pattern":"ab+c" + }'; +SELECT JSON_SCHEMA_VALID(@string_schema, '"abc"'); +JSON_SCHEMA_VALID(@string_schema, '"abc"') +1 +# Validating non-scalar +# Validating array +SET @schema_array= '{"type":"array"}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, {"key1":"val1"}]'); +JSON_SCHEMA_VALID(@schema_array, '[1, 2, {"key1":"val1"}]') +1 +SET @schema_array= '{"type":"array", + "maxItems": 4, + "minItems": 2}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, {"key1":"val1"}]'); +JSON_SCHEMA_VALID(@schema_array, '[1, 2, {"key1":"val1"}]') +1 +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, false, null, "foobar"]'); +JSON_SCHEMA_VALID(@schema_array, '[1, 2, false, null, "foobar"]') +0 +SELECT JSON_SCHEMA_VALID(@schema_array, '[1]'); +JSON_SCHEMA_VALID(@schema_array, '[1]') +0 +SET @schema_array= '{"maxItems": 4, + "minItems": 2}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, {"key1":"val1"}]'); +JSON_SCHEMA_VALID(@schema_array, '[1, 2, {"key1":"val1"}]') +1 +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, false, null, "foobar"]'); +JSON_SCHEMA_VALID(@schema_array, '[1, 2, false, null, "foobar"]') +0 +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2]'); +JSON_SCHEMA_VALID(@schema_array, '[1, 2]') +1 +SET @schema_array= '{ + "type":"array", + "items": {"type":"number"}, + "maxItems": 4, + "minItems": 2}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3]'); +JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3]') +1 +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, "foobar"]'); +JSON_SCHEMA_VALID(@schema_array, '[1, 2, "foobar"]') +0 +SET @schema_array= '{"type":"array", + "maxItems": 4, + "minItems": 2, + "const": [1, 2, 3, 4]}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3, "foobar"]'); +JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3, "foobar"]') +0 +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3, 4]'); +JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3, 4]') +1 +SET @schema_array= '{"type":"array", + "enum":[[1,2,3], [4,5,6], [7,8,9]]}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[4,5,6]'); +JSON_SCHEMA_VALID(@schema_array, '[4,5,6]') +1 +SELECT JSON_SCHEMA_VALID(@schema_array, '[1,5,7]'); +JSON_SCHEMA_VALID(@schema_array, '[1,5,7]') +0 +SET @schema_array= '{ + "type": "array", + "uniqueItems":true + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3, 2.0]'); +JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3, 2.0]') +0 +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3, 4.0]'); +JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3, 4.0]') +1 +SET @schema_array= '{ + "type": "array", + "contains": { + "type": "number" + }, + "minContains": 2, + "maxContains": 3 +}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '["string1", "string2", "string3", 1, 2, 3, 4]'); +JSON_SCHEMA_VALID(@schema_array, '["string1", "string2", "string3", 1, 2, 3, 4]') +0 +SELECT JSON_SCHEMA_VALID(@schema_array, '["string1", "string2", "string3", 1, 2, 3]'); +JSON_SCHEMA_VALID(@schema_array, '["string1", "string2", "string3", 1, 2, 3]') +1 +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ] + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1",2]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1",2]') +1 +SELECT JSON_SCHEMA_VALID(@schema_array, '[2, "string1",2]'); +JSON_SCHEMA_VALID(@schema_array, '[2, "string1",2]') +0 +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "items":true + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1",2]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1",2]') +1 +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "items":false + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1",2]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1",2]') +0 +# Checking objects +SET @schema_object= '{"type":"object", + "properties": + { + "number1":{ + "type":"number", + "maximum":12, + "minimum":1 + }, + "string1": { + "type":"string", + "maxLength":10, + "minLength": 4 + }, + "array1": {"type":"array", + "maxItems": 4, + "minItems": 2} + } + }'; +SELECT JSON_SCHEMA_VALID(@schema_object, '{"number1":10, "string1":"foobar","array1":[1,2,3]}'); +JSON_SCHEMA_VALID(@schema_object, '{"number1":10, "string1":"foobar","array1":[1,2,3]}') +1 +SELECT JSON_SCHEMA_VALID(@schema_object, '{"number1":10, "string1":"foobar","array1":[1,2,3,4,5]}'); +JSON_SCHEMA_VALID(@schema_object, '{"number1":10, "string1":"foobar","array1":[1,2,3,4,5]}') +0 +SET @schema_obj= '{ + "type": "object", + "properties": { + "number1":{"type":"number"}, + "string1":{"type":"string"}, + "array1":{"type":"array"} + }, + "dependentRequired": { + "number1":["string1"] + } + }'; +SELECT JSON_SCHEMA_VALID(@schema_obj, '{"array1":[1,2,3], "number1":2, "string1":"abc"}'); +JSON_SCHEMA_VALID(@schema_obj, '{"array1":[1,2,3], "number1":2, "string1":"abc"}') +1 +SELECT JSON_SCHEMA_VALID(@schema_obj, '{"array1":[1,2,3], "number1":2}'); +JSON_SCHEMA_VALID(@schema_obj, '{"array1":[1,2,3], "number1":2}') +0 +SET @schema_obj= '{"type":"object", + "properties": + { + "number1":{ + "type":"number", + "maximum":12, + "minimum":1 + }, + "key1" : { + "type":"object", + "properties": { + "key2" :{ + "type":"string" + } + } + } + }, + "enum": [{"number1":3, "key1":{"key2":"string1"}}, {"number1":5, "key1":{"key2":"string3"}}, {"number1":7, "key1":{"key2":"string5"}}] + }'; +SELECT JSON_SCHEMA_VALID(@schema_obj, '{"number1":5, "key1":{"key2":1}}'); +JSON_SCHEMA_VALID(@schema_obj, '{"number1":5, "key1":{"key2":1}}') +0 +SELECT JSON_SCHEMA_VALID(@schema_obj, '{"number1":5, "key1":{"key2":"string1"}}'); +JSON_SCHEMA_VALID(@schema_obj, '{"number1":5, "key1":{"key2":"string1"}}') +0 +SELECT JSON_SCHEMA_VALID(@schema_obj, '{"number1":5, "key1":{"key2":"string7"}}'); +JSON_SCHEMA_VALID(@schema_obj, '{"number1":5, "key1":{"key2":"string7"}}') +0 +SET @schema_obj= '{"type":"object", + "properties": + { + "number1":{ + "type":"number", + "maximum":12, + "minimum":1 + }, + "obj1" : { + "type":"object", + "properties": { + "obj1_1":{ + "type":"string" + }, + "obj1_2": { + "type":"array" + } + } + }, + "obj2" : { + "type":"object", + "properties" : { + "obj2_1":{ + "type":"number" + } + } + } + }, + "required":["number1", "obj2"] + }'; +SELECT JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}}'); +JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}}') +0 +SELECT JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}, "obj2":{"obj2_1":7}}'); +JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}, "obj2":{"obj2_1":7}}') +1 +SET @schema_obj= '{"type":"object", + "properties": + { + "number1":{ + "type":"number", + "maximum":12, + "minimum":1 + }, + "obj1" : { + "type":"object", + "properties": { + "obj1_1":{ + "type":"string" + }, + "obj1_2": { + "type":"array" + } + } + }, + "obj2" : { + "type":"object", + "properties" : { + "obj2_1":{ + "type":"number" + } + } + } + }, + "required":["number1", "obj2"], + "const": {"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}, "obj2":{"obj2_1":7}} + }'; +SELECT JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}, "obj2":{"obj2_1":7}}'); +JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}, "obj2":{"obj2_1":7}}') +1 +SELECT JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}}'); +JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}}') +0 +SET @schema_obj= '{"type":"object", + "properties": + { + "number1":{ + "type":"number", + "maximum":12, + "minimum":1 + }, + "obj1" : { + "type":"object", + "properties": { + "obj1_1":{ + "type":"string" + }, + "obj1_2": { + "type":"array" + } + } + }, + "obj2" : { + "type":"object", + "properties" : { + "obj2_1":{ + "type":"number" + } + } + } + }, + "maxProperties": 5, + "minProperties":2 + }'; +SELECT JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}, "obj2":{"obj2_1":7}}'); +JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}, "obj2":{"obj2_1":7}}') +1 +SELECT JSON_SCHEMA_VALID(@schema_obj,'{"number1":1, "number2":2, "number3":3, "number4":4, "number5":5, "number6":6}'); +JSON_SCHEMA_VALID(@schema_obj,'{"number1":1, "number2":2, "number3":3, "number4":4, "number5":5, "number6":6}') +0 +SET @schema_obj= '{"type":"object", + "properties": + { + "number1":{ + "type":"number", + "maximum":12, + "minimum":1 + }, + "obj1" : { + "type":"object", + "properties": { + "obj1_1":{ + "type":"string" + }, + "obj1_2": { + "type":"array" + } + } + } + }, + "maxProperties": 3, + "minProperties":1, + "additionalProperties":false + }'; +SELECT JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}, "obj2":"string2"}'); +JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}, "obj2":"string2"}') +0 +# Demonstrating that irrelavent keywords for a type and irrelavent type +# are ignored, and none of the keywords are mandatory, including "type". +SET @schema_properties= '{ + "properties" : { + "number1":{ "maximum":10 }, + "string1" : { "maxLength": 3} + } + }'; +SELECT JSON_SCHEMA_VALID(@schema_properties, '{ "number1":25, "string1":"ab" }'); +JSON_SCHEMA_VALID(@schema_properties, '{ "number1":25, "string1":"ab" }') +0 +SELECT JSON_SCHEMA_VALID(@schema_properties, '{ "number1":10, "string1":"ab" }'); +JSON_SCHEMA_VALID(@schema_properties, '{ "number1":10, "string1":"ab" }') +1 +SET @schema_properties= '{ + "properties" : { + "number1":{ "maximum":10 }, + "string1" : { "maxLength": 3}, + "obj1" : { + "properties":{ + "number2": {"minimum":8}, + "array2": {"uniqueItems":true} + } + } + } + }'; +SELECT JSON_SCHEMA_VALID(@schema_properties, '{ "number1":2, "string1":"ab", "obj1":{"number2":2, "array2":[1,2,3]} }'); +JSON_SCHEMA_VALID(@schema_properties, '{ "number1":2, "string1":"ab", "obj1":{"number2":2, "array2":[1,2,3]} }') +0 +SELECT JSON_SCHEMA_VALID(@schema_properties, '{ "number1":2, "string1":"ab", "obj1":{"number2":10, "array2":[1,2,3]} }'); +JSON_SCHEMA_VALID(@schema_properties, '{ "number1":2, "string1":"ab", "obj1":{"number2":10, "array2":[1,2,3]} }') +1 +SELECT JSON_SCHEMA_VALID(@schema_properties, '{ "number1":2, "string1":"ab", "obj1":{"array2":[1,2,3]} }'); +JSON_SCHEMA_VALID(@schema_properties, '{ "number1":2, "string1":"ab", "obj1":{"array2":[1,2,3]} }') +1 +SELECT JSON_SCHEMA_VALID(@schema_properties, '{ "number1":2, "string1":"ab", "obj1":{"number2":10, "array2":[1,2,3,2]} }'); +JSON_SCHEMA_VALID(@schema_properties, '{ "number1":2, "string1":"ab", "obj1":{"number2":10, "array2":[1,2,3,2]} }') +0 +SET @schema_num= '{ + "maximum":10, + "minimum":2 + }'; +SELECT JSON_SCHEMA_VALID(@schema_num, '5'); +JSON_SCHEMA_VALID(@schema_num, '5') +1 +SELECT JSON_SCHEMA_VALID(@schema_num, '"abc"'); +JSON_SCHEMA_VALID(@schema_num, '"abc"') +1 +SET @schema_str= '{ + "maxLength":5, + "minLength":2, + "pattern":"a+bc" + }'; +SELECT JSON_SCHEMA_VALID(@schema_str, '"abc"'); +JSON_SCHEMA_VALID(@schema_str, '"abc"') +1 +SELECT JSON_SCHEMA_VALID(@schema_str, '"abcadef"'); +JSON_SCHEMA_VALID(@schema_str, '"abcadef"') +0 +SELECT JSON_SCHEMA_VALID(@schema_str, '"bc"'); +JSON_SCHEMA_VALID(@schema_str, '"bc"') +0 +SET @schema_arr= '{ + "uniqueItems":true, + "items":{"type":"string"}, + "maximum":10 + }'; +SELECT JSON_SCHEMA_VALID(@schema_arr,'["abc", "bcd", "cde"]'); +JSON_SCHEMA_VALID(@schema_arr,'["abc", "bcd", "cde"]') +1 +SELECT JSON_SCHEMA_VALID(@schema_arr,'["abc", "bcd", "abc"]'); +JSON_SCHEMA_VALID(@schema_arr,'["abc", "bcd", "abc"]') +0 +SELECT JSON_SCHEMA_VALID(@schema_arr,'["abc", "bcd", 1]'); +JSON_SCHEMA_VALID(@schema_arr,'["abc", "bcd", 1]') +0 +SET @schema_const1= '{"const":2}'; +SELECT JSON_SCHEMA_VALID(@schema_const1, '2'); +JSON_SCHEMA_VALID(@schema_const1, '2') +1 +SELECT JSON_SCHEMA_VALID(@schema_const1, '"abc"'); +JSON_SCHEMA_VALID(@schema_const1, '"abc"') +0 +SET @schema_const2= '{"const":true}'; +SELECT JSON_SCHEMA_VALID(@schema_const2,'true'); +JSON_SCHEMA_VALID(@schema_const2,'true') +1 +SELECT JSON_SCHEMA_VALID(@schema_const2,'false'); +JSON_SCHEMA_VALID(@schema_const2,'false') +0 +SET @schema_enum='{"enum":[1,2,3,"abc", [4,5,6]]}'; +SELECT JSON_SCHEMA_VALID(@schema_enum,'[4,5,6]'); +JSON_SCHEMA_VALID(@schema_enum,'[4,5,6]') +1 +SELECT JSON_SCHEMA_VALID(@schema_enum,'4'); +JSON_SCHEMA_VALID(@schema_enum,'4') +0 +SELECT JSON_SCHEMA_VALID(@schema_enum,'"abc"'); +JSON_SCHEMA_VALID(@schema_enum,'"abc"') +1 +SET @schema_required='{"required":["num1","str1", "arr1"]}'; +SELECT JSON_SCHEMA_VALID(@schema_required,'{"num1":1, "str1":"abc", "arr1":[1,2,3]}'); +JSON_SCHEMA_VALID(@schema_required,'{"num1":1, "str1":"abc", "arr1":[1,2,3]}') +1 +SELECT JSON_SCHEMA_VALID(@schema_required,'{"num1":1, "arr1":[1,2,3]}'); +JSON_SCHEMA_VALID(@schema_required,'{"num1":1, "arr1":[1,2,3]}') +0 +SELECT JSON_SCHEMA_VALID(@schema_required,'"abcd"'); +JSON_SCHEMA_VALID(@schema_required,'"abcd"') +1 +SET @schema_dep_required='{ + "dependentRequired": { + "num1":["num2","num3"], + "str1":["str2","str3"] + } + }'; +SELECT JSON_SCHEMA_VALID(@schema_dep_required,'{"num1":1, "num2":"abc", "num3":[1,2,3]}'); +JSON_SCHEMA_VALID(@schema_dep_required,'{"num1":1, "num2":"abc", "num3":[1,2,3]}') +1 +SELECT JSON_SCHEMA_VALID(@schema_dep_required,'{"num1":1, "num2":"abc", "num3":[1,2,3], "str1":"abcd"}'); +JSON_SCHEMA_VALID(@schema_dep_required,'{"num1":1, "num2":"abc", "num3":[1,2,3], "str1":"abcd"}') +0 +SELECT JSON_SCHEMA_VALID(@schema_dep_required,'{"num1":1, "num2":"abc", "num3":[1,2,3], "arr1":[1,2,3]}'); +JSON_SCHEMA_VALID(@schema_dep_required,'{"num1":1, "num2":"abc", "num3":[1,2,3], "arr1":[1,2,3]}') +1 +# Checking syntax error +SET @invalid_schema= '{"type":"object" + "properties":{ + "number1": {"type":"number"}, + "obj2": {"type":"object", + "properties": { + "key1": {"type":"number"} + } + } + } + }'; +SELECT JSON_SCHEMA_VALID(@invalid_schema, '{"number1":3, "obj2":{"key1":3}}'); +JSON_SCHEMA_VALID(@invalid_schema, '{"number1":3, "obj2":{"key1":3}}') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_schema_valid' at position 45 +SET @invalid_json= '{"type":"array", + "maxItems": 4, + "minItems": 2, + "const": [1, 2, 3, 4]}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3, 4'); +JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3, 4') +0 +SET @schema_string= '{ + "type": "string", + "maxLength":-2 + }'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"abcxyz"'); +ERROR HY000: Invalid value for keyword maxLength +SET @schema_number= '{ + "type": "number", + "multipleOf":-3 + }'; +SELECT JSON_SCHEMA_VALID(@schema_number, '3'); +ERROR HY000: Invalid value for keyword multipleOf +SET @schema_object= '{ + "type": "object", + "properties":{"num1":{"type":"number"}}, + "required":{} + }'; +SELECT JSON_SCHEMA_VALID(@schema_object, '{"num1":2}'); +ERROR HY000: Invalid value for keyword required +SET @schema_string= '{ + "type": "string", + "maxLength":-10 + }'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"str1"'); +ERROR HY000: Invalid value for keyword maxLength +SET @schema_number= '{"type":"numberz"}'; +SELECT JSON_SCHEMA_VALID(@schema_number, '"string1"'); +ERROR HY000: Invalid value for keyword type +# Using JSON_SCHEMA_VALID() as a constraint validation to insert into table +CREATE TABLE str_table (val_str JSON CHECK(JSON_SCHEMA_VALID('{ + "type":"string", + "maxLength":5, + "minLength":2, + "enum":["ab", "cd", "abc", "def", "abcdef"] + }', val_str))); +CREATE TABLE num_table(val_num JSON CHECK(JSON_SCHEMA_VALID('{ + "type":"number", + "minimum":10, + "maximum":30, + "exclusiveMinimum":11, + "exclusiveMaximum":29, + "multipleOf":5, + "const":15 + }', val_num))); +CREATE TABLE true_table(val_true JSON CHECK(JSON_SCHEMA_VALID('{ + "type":"boolean", + "enum":[true, false, null] + }', val_true))); +CREATE TABLE false_table (val_false JSON CHECK(JSON_SCHEMA_VALID('{ + "type":"boolean" + }', val_false))); +CREATE TABLE null_table (val_null JSON CHECK(JSON_SCHEMA_VALID('{ + "type":"null" + }', val_null))); +CREATE TABLE arr_table (val_arr JSON CHECK(JSON_SCHEMA_VALID('{ + "type":"array", + "uniqueItems":true, + "maxItems":5, + "minItems":1, + "items":true, + "prefixItems":[{"type":"number"}] + }', val_arr))); +CREATE TABLE obj_table(val_obj JSON CHECK(JSON_SCHEMA_VALID('{ + "type":"object", + "properties": { + "number1":{ + "type":"number", + "maximum":5, + "const":4 + }, + "string1":{ + "type":"string", + "maxLength":5, + "minLength":3 + }, + "object1":{ + "type":"object", + "properties":{ + "key1": {"type":"string"}, + "key2":{"type":"array"}, + "key3":{"type":"number", "minimum":3} + }, + "dependentRequired": { "key1":["key3"] } + } + }, + "required":["number1","object1"] + }', val_obj))); +INSERT INTO str_table VALUES ('"ab"'), ('"cd"'), ('"abc"'), ('"def"'); +INSERT INTO str_table VALUES ('"feb"'); +ERROR 23000: CONSTRAINT `str_table.val_str` failed for `test`.`str_table` +INSERT INTO str_table VALUES('"abcdef"'); +ERROR 23000: CONSTRAINT `str_table.val_str` failed for `test`.`str_table` +INSERT INTO str_table VALUES('"fedcba"'); +ERROR 23000: CONSTRAINT `str_table.val_str` failed for `test`.`str_table` +SELECT * FROM str_table; +val_str +"ab" +"cd" +"abc" +"def" +INSERT INTO num_table values('15'); +INSERT INTO num_table values('25'); +ERROR 23000: CONSTRAINT `num_table.val_num` failed for `test`.`num_table` +SELECT * FROM num_table; +val_num +15 +INSERT INTO true_table VALUES ('true'); +SELECT * FROM true_table; +val_true +true +INSERT INTO false_table VALUES('false'); +SELECT * FROM false_table; +val_false +false +INSERT INTO arr_table VALUES ('[10, 2, "abc"]'); +INSERT INTO arr_table VALUES('[100]'); +INSERT INTO arr_table VALUES ('["str1", 2, "abc", 2.0]'); +ERROR 23000: CONSTRAINT `arr_table.val_arr` failed for `test`.`arr_table` +SELECT * FROM arr_table; +val_arr +[10, 2, "abc"] +[100] +INSERT INTO obj_table VALUES('{"number1":4, "string1":"abcd", "object1":{"key1":"val1", "key2":[1,2,3, "string1"], "key3":4}}'); +INSERT INTO obj_table VALUES('{"number1":3, "string1":"abcd", "object1":{"key1":"val1", "key2":[1,2,3, "string1"], "key3":4}}'); +ERROR 23000: CONSTRAINT `obj_table.val_obj` failed for `test`.`obj_table` +INSERT INTO obj_table VALUES('{"number1":3, "string1":"abcd"}'); +ERROR 23000: CONSTRAINT `obj_table.val_obj` failed for `test`.`obj_table` +INSERT INTO obj_table VALUES('{"number1":3, "string1":"abcd", "object1":{"key1":"val1", "key2":[1,2,3, "string1"]}'); +ERROR 23000: CONSTRAINT `obj_table.val_obj` failed for `test`.`obj_table` +SELECT * FROM obj_table; +val_obj +{"number1":4, "string1":"abcd", "object1":{"key1":"val1", "key2":[1,2,3, "string1"], "key3":4}} +DROP TABLE str_table, num_table, true_table, false_table, null_table, arr_table, obj_table; +# array validation +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "additionalItems" : {"type":"number"}, + "unevaluatedItems": {"type":"string"}, + "items":{"type":"array"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], "2", "string"]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], "2", "string"]') +0 +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "2", "string"]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "2", "string"]') +0 +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], [1,2]]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], [1,2]]') +1 +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "additionalItems" : {"type":"number"}, + "unevaluatedItems": {"type":"string"}, + "items": true + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], "2", "string"]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], "2", "string"]') +1 +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "additionalItems" : {"type":"number"}, + "unevaluatedItems": {"type":"string"}, + "items": false + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], "2", "string"]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], "2", "string"]') +0 +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "additionalItems" : {"type":"number"}, + "unevaluatedItems": {"type":"string"}, + "items": [{"type":"string"}] + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], "2", "string"]'); +ERROR HY000: Invalid value for keyword items +# Removing items +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "additionalItems" : {"type":"number"}, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], "2", "string"]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], "2", "string"]') +0 +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]') +1 +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "additionalItems" : true, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]') +1 +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "additionalItems" : false, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]') +0 +# Using items in place of additionalItems +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "items" : false, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]') +0 +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "items" : true, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]') +1 +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "items" : {"type":"number"}, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]') +1 +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "items" : {"type":"number"}, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "string2", "string3"]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "string2", "string3"]') +0 +# Removing items and additionalItems both +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "unevaluatedItems": {"type":"number"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "string2", "string3"]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "string2", "string3"]') +0 +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2]') +1 +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "unevaluatedItems": true + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "string2", "string3"]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "string2", "string3"]') +1 +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "unevaluatedItems": false + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "string2", "string3"]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "string2", "string3"]') +0 +# Removing items, additionalItems, unevaluatedItems +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ] + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "string2", "string3"]'); +JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "string2", "string3"]') +1 +# Removing prefixItems +SET @schema_array= '{ + "type": "array", + "items": { "type": "number", "maximum": 10, "minimum":3}, + "additionalItems" : {"type":"number"}, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, 6,"2", "string"]'); +JSON_SCHEMA_VALID(@schema_array, '[5, 6,"2", "string"]') +0 +SET @schema_array= '{ + "type": "array", + "items": { "type": "number", "maximum": 10, "minimum":3}, + "additionalItems" : {"type":"string"}, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, 6,"2", "string"]'); +JSON_SCHEMA_VALID(@schema_array, '[5, 6,"2", "string"]') +0 +SET @schema_array= '{ + "type": "array", + "items": true, + "additionalItems" : {"type":"string"}, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, 6,"2", "string"]'); +JSON_SCHEMA_VALID(@schema_array, '[5, 6,"2", "string"]') +1 +SET @schema_array= '{ + "type": "array", + "items": false, + "additionalItems" : {"type":"string"}, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, 6,"2", "string"]'); +JSON_SCHEMA_VALID(@schema_array, '[5, 6,"2", "string"]') +0 +SELECT JSON_SCHEMA_VALID(@schema_array, '[]'); +JSON_SCHEMA_VALID(@schema_array, '[]') +1 +# Removing prefixItems and additionalItems +SET @schema_array= '{ + "type": "array", + "items": {"type":"string"}, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 2]'); +JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 2]') +0 +SELECT JSON_SCHEMA_VALID(@schema_array, '["str1", "str2"]'); +JSON_SCHEMA_VALID(@schema_array, '["str1", "str2"]') +1 +SET @schema_array= '{ + "type": "array", + "items": {"type":"string"}, + "unevaluatedItems": {"type":"number"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 2]'); +JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 2]') +0 +# removing prefixItems, additionalItems and unevaluatedItems +SET @schema_array= '{ + "type": "array", + "items": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 2]'); +JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 2]') +0 +SELECT JSON_SCHEMA_VALID(@schema_array, '["str1", "str2"]'); +JSON_SCHEMA_VALID(@schema_array, '["str1", "str2"]') +1 +# Checking that additionalItems alone has no effect on schema without items/prefixItems +# regardless existence of unevaluatedItems +SET @schema_array= '{ + "type": "array", + "additionalItems": {"type":"string"}, + "unevaluatedItems": {"type":"number"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 1]'); +JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 1]') +1 +SET @schema_array= '{ + "type": "array", + "additionalItems": true, + "unevaluatedItems": {"type":"number"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 1]'); +JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 1]') +1 +SET @schema_array= '{ + "type": "array", + "additionalItems": false, + "unevaluatedItems": {"type":"number"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 1]'); +JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 1]') +1 +# checking that unevaluatedItems alone can have effect on schema validation +SET @schema_array= '{ + "type": "array", + "unevaluatedItems": {"type":"number"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1]'); +JSON_SCHEMA_VALID(@schema_array, '[1]') +1 +SET @schema_array= '{ + "type": "array", + "unevaluatedItems": {"type":"number"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, "str1"]'); +JSON_SCHEMA_VALID(@schema_array, '[1, "str1"]') +0 +SET @schema_array= '{ + "type": "array", + "unevaluatedItems": false + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, "str1"]'); +JSON_SCHEMA_VALID(@schema_array, '[1, "str1"]') +0 +SELECT JSON_SCHEMA_VALID(@schema_array, '[]'); +JSON_SCHEMA_VALID(@schema_array, '[]') +1 +SELECT JSON_SCHEMA_VALID(@schema_array, '[1,2,3]'); +JSON_SCHEMA_VALID(@schema_array, '[1,2,3]') +0 +# Object validation +SET @property_names= '{ + "PropertyNames":{ + "pattern": "^I_" + } + }'; +SELECT JSON_SCHEMA_VALID(@property_names, '{"I_int1":3, "O_ob1":{"key1":"val1"}}'); +JSON_SCHEMA_VALID(@property_names, '{"I_int1":3, "O_ob1":{"key1":"val1"}}') +0 +SELECT JSON_SCHEMA_VALID(@property_names, '{"I_int1":3, "I_ob1":{"key1":"val1"}}'); +JSON_SCHEMA_VALID(@property_names, '{"I_int1":3, "I_ob1":{"key1":"val1"}}') +1 +# checking that when a match is found in properties or patternProperties, it must validate and +# validation result affects the schema. If key is not found in properties or patternProperties, and +# additionalProperties exists, it must validate regardless of existence or value for unevaluatedProperties +# and the result of validation with additionalProperties affects result of whole schema +SET @object_schema= '{ + "type":"object", + "properties": { + "key1":{"type":"string"}, + "key2":{"type":"number", "maximum":50} + }, + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "additionalProperties":{ + "type":"array", + "maxItems":5 + }, + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}') +1 +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": [1,2,3], "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": [1,2,3], "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}') +0 +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":[1,2,3], "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":[1,2,3], "S_":"abc", "some_prop1":[1,2,3]}') +0 +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":"string1"}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":"string1"}') +0 +# removing patternProperties to check that validation falls back on additionalProperties and +# existence of unevaluatedProperties still does not change anything because of existence of additional +# properties +SET @object_schema= '{ + "type":"object", + "properties": { + "key1":{"type":"string"}, + "key2":{"type":"number", "maximum":50} + }, + "additionalProperties":{ + "type":"array", + "maxItems":5 + }, + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}') +0 +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":[1,2,3], "S_":[1,2,3], "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":[1,2,3], "S_":[1,2,3], "some_prop1":[1,2,3]}') +1 +# Remvoing additionalProperties to check that validation falls back on unevaluatedProperties +SET @object_schema= '{ + "type":"object", + "properties": { + "key1":{"type":"string"}, + "key2":{"type":"number", "maximum":50} + }, + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":10, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":10, "S_":"abc", "some_prop1":[1,2,3]}') +0 +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":10, "S_":"abc", "some_prop1":"str"}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":10, "S_":"abc", "some_prop1":"str"}') +1 +# Removing unevaluatedProperties has no effect on result when additionalProperties is present +SET @object_schema= '{ + "type":"object", + "properties": { + "key1":{"type":"string"}, + "key2":{"type":"number", "maximum":50} + }, + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "additionalProperties":{ + "type":"array", + "maxItems":5 + } + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}') +1 +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":"str1"}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":"str1"}') +0 +SET @object_schema= '{ + "type":"object", + "properties": { + "key1":{"type":"string"}, + "key2":{"type":"number", "maximum":50} + }, + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "additionalProperties": false + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}') +0 +SET @object_schema= '{ + "type":"object", + "properties": { + "key1":{"type":"string"}, + "key2":{"type":"number", "maximum":50} + }, + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "additionalProperties": true + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}') +1 +# Checking that in absence of additionalProperties, validation falls back on evaluatedProperties +SET @object_schema= '{ + "type":"object", + "properties": { + "key1":{"type":"string"}, + "key2":{"type":"number", "maximum":50} + }, + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 3, "I_int":20, "S_":"abc", "some_prop1":"str1"}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 3, "I_int":20, "S_":"abc", "some_prop1":"str1"}') +1 +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 3, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 3, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}') +0 +SET @object_schema= '{ + "type":"object", + "properties": { + "key1":{"type":"string"}, + "key2":{"type":"number", "maximum":50} + }, + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 3, "I_int":"str2", "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 3, "I_int":"str2", "S_":"abc", "some_prop1":[1,2,3]}') +0 +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 3, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 3, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}') +0 +# Properties to check if patternProperties get evaluated but keys not found in patternProperties get evaluated against +# additionalProperties regardless of existence of unevaluatedProperperties +SET @object_schema= '{ + "type":"object", + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "additionalProperties":{ + "type":"array", + "maxItems":5 + }, + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}') +0 +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":[1, 2, 3], "key2": [1, 2, 3], "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":[1, 2, 3], "key2": [1, 2, 3], "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}') +1 +SET @object_schema= '{ + "type":"object", + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "additionalProperties":{ + "type":"array", + "maxItems":5 + } + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}') +0 +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":[1, 2, 3], "key2": [1, 2, 3], "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":[1, 2, 3], "key2": [1, 2, 3], "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}') +1 +# Checking that in absence of additionalProperties and properties, the keys not found in patternProperties are +# evaluated against unevaluatedProperties +SET @object_schema= '{ + "type":"object", + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}') +0 +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": "str2", "I_int":20, "S_":"abc", "some_prop1":"str1"}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": "str2", "I_int":20, "S_":"abc", "some_prop1":"str1"}') +1 +# checking that in absence of properties, additionalProperties and unevaluatedPropoerties, the keys that are +# not found are considered validated. +SET @object_schema= '{ + "type":"object", + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + } + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}') +1 +# checking that additionalProperties are evaluated in absence of patternProperties and properties, regardless +# of presence of unevaluatedProperties +SET @object_schema= '{ + "type":"object", + "additionalProperties":{ + "type":"array", + "maxItems":5 + }, + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}') +0 +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":[1,2,3], "key2": [1,2,3], "I_int":[1,2,3], "S_":[1,2,3], "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":[1,2,3], "key2": [1,2,3], "I_int":[1,2,3], "S_":[1,2,3], "some_prop1":[1,2,3]}') +1 +SET @object_schema= '{ + "type":"object", + "additionalProperties":{ + "type":"array", + "maxItems":5 + } + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}') +0 +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":[1,2,3], "key2": [1,2,3], "I_int":[1,2,3], "S_":[1,2,3], "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":[1,2,3], "key2": [1,2,3], "I_int":[1,2,3], "S_":[1,2,3], "some_prop1":[1,2,3]}') +1 +# Checking that in absence of properties, patternProperties and additionalProperties, validation falls back on unevaluatedProperties +SET @object_schema= '{ + "type":"object", + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": "str1", "I_int":"str2", "S_":"abc", "some_prop1":"str3"}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": "str1", "I_int":"str2", "S_":"abc", "some_prop1":"str3"}') +1 +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":[1,2,3], "key2": [1,2,3], "I_int":[1,2,3], "S_":[1,2,3], "some_prop1":[1,2,3]}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":[1,2,3], "key2": [1,2,3], "I_int":[1,2,3], "S_":[1,2,3], "some_prop1":[1,2,3]}') +0 +SET @object_schema= '{ + "type":"object", + "unevaluatedProperties": false + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": "str1", "I_int":"str2", "S_":"abc", "some_prop1":"str3"}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": "str1", "I_int":"str2", "S_":"abc", "some_prop1":"str3"}') +0 +SELECT JSON_SCHEMA_VALID(@object_schema, '{}'); +JSON_SCHEMA_VALID(@object_schema, '{}') +1 +SET @object_schema= '{ + "type":"object", + "unevaluatedProperties": true + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": "str1", "I_int":"str2", "S_":"abc", "some_prop1":"str3"}'); +JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": "str1", "I_int":"str2", "S_":"abc", "some_prop1":"str3"}') +1 +SELECT JSON_SCHEMA_VALID(@object_schema, '{}'); +JSON_SCHEMA_VALID(@object_schema, '{}') +1 +SET @json_schema_dependent_schemas='{ + "type": "object", + "properties": { + "str1": { "type": "string" }, + "num1": { "type": "number" } + }, + + "required": ["str1"], + + "dependentSchemas": { + "num1": { + "properties": { + "str2": { "type": "string" } + }, + "required": ["str2"] + } + } +}'; +SELECT JSON_SCHEMA_VALID(@json_schema_dependent_schemas, '{ "str1": "str", "num1":4}'); +JSON_SCHEMA_VALID(@json_schema_dependent_schemas, '{ "str1": "str", "num1":4}') +0 +SELECT JSON_SCHEMA_VALID(@json_schema_dependent_schemas, '{ "str1": "str"}'); +JSON_SCHEMA_VALID(@json_schema_dependent_schemas, '{ "str1": "str"}') +1 +# Validating logic +SET @not_schema= '{ + "not":{ + "maximum": 4 + } + }'; +SELECT JSON_SCHEMA_VALID(@not_schema, '{"I_int1":3, "O_ob1":{"key1":"val1"}}'); +JSON_SCHEMA_VALID(@not_schema, '{"I_int1":3, "O_ob1":{"key1":"val1"}}') +0 +SELECT JSON_SCHEMA_VALID(@not_schema, '3'); +JSON_SCHEMA_VALID(@not_schema, '3') +0 +SELECT JSON_SCHEMA_VALID(@not_schema, '10'); +JSON_SCHEMA_VALID(@not_schema, '10') +1 +SET @not_schema= '{ + "not":{ + "properties": { + "num1" : {"type":"number", "maximum":5}, + "string1" : { "maxLength": 3} + } + } + }'; +SELECT JSON_SCHEMA_VALID(@not_schema, '{"num1":10, "string2":"abcd"}'); +JSON_SCHEMA_VALID(@not_schema, '{"num1":10, "string2":"abcd"}') +1 +SELECT JSON_SCHEMA_VALID(@not_schema, '{"num1":2, "string2":"abcd"}'); +JSON_SCHEMA_VALID(@not_schema, '{"num1":2, "string2":"abcd"}') +0 +SET @any_of_schema= '{ + "anyOf":[{ + "properties": { + "num1" : {"type":"number", "maximum":5}, + "string1" : { "maxLength": 3} + } + }, + { + "properties":{ + "num1" : {"type":"number", "maximum": 1}, + "string1" : { "maxLength":5} + } + } + ] + }'; +SELECT JSON_SCHEMA_VALID(@any_of_schema, '{"num1":2, "string1":"abcd"}'); +JSON_SCHEMA_VALID(@any_of_schema, '{"num1":2, "string1":"abcd"}') +0 +SELECT JSON_SCHEMA_VALID(@any_of_schema, '{"num1":2, "string1":"abc"}'); +JSON_SCHEMA_VALID(@any_of_schema, '{"num1":2, "string1":"abc"}') +1 +SET @any_of_schema= '{ + "anyOf": [ + {"type":"number", "maximum":5}, + {"type":"string"} + ] + }'; +SELECT JSON_SCHEMA_VALID(@any_of_schema, '2'); +JSON_SCHEMA_VALID(@any_of_schema, '2') +1 +SELECT JSON_SCHEMA_VALID(@any_of_schema, '6'); +JSON_SCHEMA_VALID(@any_of_schema, '6') +0 +SELECT JSON_SCHEMA_VALID(@any_of_schema, '[1, 2, 3]'); +JSON_SCHEMA_VALID(@any_of_schema, '[1, 2, 3]') +0 +SET @one_of_schema= '{ + "oneOf":[{ + "properties": { + "num1" : {"type":"number", "maximum":5}, + "string1" : { "maxLength": 3} + } + }, + { + "properties":{ + "num1" : {"type":"number", "maximum": 1}, + "string1" : { "maxLength":5} + } + } + ] + }'; +SELECT JSON_SCHEMA_VALID(@one_of_schema, '{"num1":2, "string1":"abcd"}'); +JSON_SCHEMA_VALID(@one_of_schema, '{"num1":2, "string1":"abcd"}') +0 +SELECT JSON_SCHEMA_VALID(@one_of_schema, '{"num1":2, "string1":"abc"}'); +JSON_SCHEMA_VALID(@one_of_schema, '{"num1":2, "string1":"abc"}') +1 +SET @one_of_schema= '{ + "oneOf": [ + {"type":"number", "maximum":5}, + {"type":"number", "maximum":3} + ] + }'; +SELECT JSON_SCHEMA_VALID(@one_of_schema, '2'); +JSON_SCHEMA_VALID(@one_of_schema, '2') +0 +SELECT JSON_SCHEMA_VALID(@one_of_schema, '4'); +JSON_SCHEMA_VALID(@one_of_schema, '4') +1 +SET @all_of_schema= '{ + "allOf":[{ + "properties": { + "num1" : {"type":"number", "maximum":5}, + "string1" : { "maxLength": 3} + } + }, + { + "properties":{ + "num1" : {"type":"number", "maximum": 1}, + "string1" : { "maxLength":5} + } + } + ] + }'; +SELECT JSON_SCHEMA_VALID(@all_of_schema, '{"num1":2, "string1":"abcd"}'); +JSON_SCHEMA_VALID(@all_of_schema, '{"num1":2, "string1":"abcd"}') +0 +SET @all_of_schema= '{ + "allOf":[ + { + "properties":{ + "num1": {"type":"number"}, + "string1": {"type":"string"} + } + }, + { + "properties":{ + "num1": {"maximum":10}, + "string1": {"maxLength":5} + } + } + ] + }'; +SELECT JSON_SCHEMA_VALID(@all_of_schema, '{"num1":5, "string1":"abc"}'); +JSON_SCHEMA_VALID(@all_of_schema, '{"num1":5, "string1":"abc"}') +1 +SELECT JSON_SCHEMA_VALID(@all_of_schema, '{"num1":5, "string1":"foobar"}'); +JSON_SCHEMA_VALID(@all_of_schema, '{"num1":5, "string1":"foobar"}') +0 +SET @condition_schema= '{ + "if" : {"maximum":30, "multipleOf":3}, + "then":{"minimum":5}, + "else":{"minimum":10} + }'; +SELECT JSON_SCHEMA_VALID(@condition_schema, '6'); +JSON_SCHEMA_VALID(@condition_schema, '6') +1 +SELECT JSON_SCHEMA_VALID(@condition_schema, '4'); +JSON_SCHEMA_VALID(@condition_schema, '4') +0 +SELECT JSON_SCHEMA_VALID(@condition_schema, '13'); +JSON_SCHEMA_VALID(@condition_schema, '13') +1 +SET @condition_schema= '{ + "if" : {"maximum":30, "multipleOf":3} + }'; +SELECT JSON_SCHEMA_VALID(@condition_schema, '6'); +JSON_SCHEMA_VALID(@condition_schema, '6') +1 +SELECT JSON_SCHEMA_VALID(@condition_schema, '7'); +JSON_SCHEMA_VALID(@condition_schema, '7') +1 +SET @condition_schema= '{ + "then":{"minimum":5}, + "else":{"minimum":10} + }'; +SELECT JSON_SCHEMA_VALID(@condition_schema, '4'); +JSON_SCHEMA_VALID(@condition_schema, '4') +1 +SELECT JSON_SCHEMA_VALID(@condition_schema, '11'); +JSON_SCHEMA_VALID(@condition_schema, '11') +1 +# Checking unevaluatedProperperties with logical properties +SET @all_of_unevaluated='{ + "allOf": [ + { + "type": "object", + "properties": { + "street_address": { "type": "string" }, + "city": { "type": "string" }, + "state": { "type": "string" } + }, + "required": ["street_address", "city", "state"] + } + ], + + "properties": { + "type": { "enum": ["residential", "business"] } + }, + "required": ["type"], + "unevaluatedProperties": false +}'; +SELECT JSON_SCHEMA_VALID(@all_of_unevaluated, '{ + "street_address": "1600 Pennsylvania Avenue NW", + "city": "Washington", + "state": "DC", + "type": "business" +}'); +JSON_SCHEMA_VALID(@all_of_unevaluated, '{ + "street_address": "1600 Pennsylvania Avenue NW", + "city": "Washington", + "state": "DC", + "type": "business" +}') +1 +SET @all_of_unevaluated='{ + "allOf": [ + { + "type": "object", + "properties": { + "street_address": { "type": "string" }, + "city": { "type": "string" }, + "state": { "type": "string" } + }, + "required": ["street_address", "city", "state"] + } + ], + + "unevaluatedProperties": {"type":"number"} +}'; +SELECT JSON_SCHEMA_VALID(@all_of_unevaluated, '{ + "street_address": "1600 Pennsylvania Avenue NW", + "city": "Washington", + "state": "DC", + "type": "business" +}'); +JSON_SCHEMA_VALID(@all_of_unevaluated, '{ + "street_address": "1600 Pennsylvania Avenue NW", + "city": "Washington", + "state": "DC", + "type": "business" +}') +0 +SET @any_of_unevaluated='{ + "anyOf": [ + { + "type": "object", + "properties": { + "street_address": { "type": "string" }, + "city": { "type": "string" }, + "state": { "type": "string" } + }, + "required": ["street_address", "city", "state"] + } + ], + + "unevaluatedProperties": {"type":"number"} +}'; +SELECT JSON_SCHEMA_VALID(@any_of_unevaluated, '{ + "street_address": "1600 Pennsylvania Avenue NW", + "city": "Washington", + "state": "DC", + "type": "business" +}'); +JSON_SCHEMA_VALID(@any_of_unevaluated, '{ + "street_address": "1600 Pennsylvania Avenue NW", + "city": "Washington", + "state": "DC", + "type": "business" +}') +0 +SET @all_of_unevaluated='{ + "allOf": [ + { + "type": "array" + }, + { + "maxItems":10 + }, + { + "prefixItems": [ {"type":"number"}, {"type":"string"}], + "additionalItems":{"type":"array"} + } + ], + + "unevaluatedItems": {"type":"number"} +}'; +SELECT JSON_SCHEMA_VALID(@all_of_unevaluated, '[1, "str", 2]'); +JSON_SCHEMA_VALID(@all_of_unevaluated, '[1, "str", 2]') +0 +SET @all_of_unevaluated='{ + "anyOf": [ + { + "type": "array" + }, + { + "maxItems":10 + }, + { + "prefixItems": [ {"type":"number"}, {"type":"string"}], + "additionalItems":{"type":"array"} + } + ], + + "unevaluatedItems": {"type":"number"} +}'; +SELECT JSON_SCHEMA_VALID(@all_of_unevaluated, '[1, "str", 2]'); +JSON_SCHEMA_VALID(@all_of_unevaluated, '[1, "str", 2]') +1 +SET @all_of_unevaluated='{ + "oneOf": [ + { + "type": "array" + }, + { + "maxItems":10 + }, + { + "prefixItems": [ {"type":"number"}, {"type":"string"}], + "additionalItems":{"type":"array"} + } + ], + + "unevaluatedItems": {"type":"number"} +}'; +SELECT JSON_SCHEMA_VALID(@all_of_unevaluated, '[1, "str", 2]'); +JSON_SCHEMA_VALID(@all_of_unevaluated, '[1, "str", 2]') +0 +# Media string +SET @schema_media_string= '{ + "type": "string", + "contentMediaType": "text/html" +}'; +SELECT JSON_SCHEMA_VALID(@schema_media_string, '"str1"'); +JSON_SCHEMA_VALID(@schema_media_string, '"str1"') +1 +SET @schema_reference= '{"$ref": "http://example.com/custom-email-validator.json#"}'; +SELECT JSON_SCHEMA_VALID(@schema_reference, '{}'); +ERROR HY000: $ref keyword is not supported +SET @schema_reference= '{"$id": "http://example.com/custom-email-validator.json#"}'; +SELECT JSON_SCHEMA_VALID(@schema_reference, '{}'); +ERROR HY000: $id keyword is not supported +SET @schema_reference= '{"$anchor": "http://example.com/custom-email-validator.json#"}'; +SELECT JSON_SCHEMA_VALID(@schema_reference, '{}'); +ERROR HY000: $anchor keyword is not supported +SET @schema_reference= '{"$defs": "http://example.com/custom-email-validator.json#"}'; +SELECT JSON_SCHEMA_VALID(@schema_reference, '{}'); +ERROR HY000: $defs keyword is not supported +# +# MDEV-30795: JSON_SCHEMA_VALID bugs mentioned in comment +# +SET @schema= '{ + "type":"array", + "uniqueItems":true + }'; +SELECT JSON_SCHEMA_VALID(@schema, '[null, null]'); +JSON_SCHEMA_VALID(@schema, '[null, null]') +0 +SET @schema_max_items= '{"maxItems":-1}'; +SELECT JSON_SCHEMA_VALID(@schema_max_items, '[]'); +ERROR HY000: Invalid value for keyword maxItems +SET @schema_min_items= '{"minItems":-1}'; +SELECT JSON_SCHEMA_VALID(@schema_min_items, '[]'); +ERROR HY000: Invalid value for keyword maxLength +SET @schema_max_properties= '{"maxProperties":-1}'; +SELECT JSON_SCHEMA_VALID(@schema_max_properties, '{}'); +ERROR HY000: Invalid value for keyword maxProperties +SET @schema_min_properties= '{"minProperties":-1}'; +SELECT JSON_SCHEMA_VALID(@schema_min_properties, '{}'); +ERROR HY000: Invalid value for keyword minProperties +SET @schema_multiple_of= '{"multipleOf":-1}'; +SELECT JSON_SCHEMA_VALID(@schema_multiple_of, '2'); +ERROR HY000: Invalid value for keyword multipleOf +SET @schema_max_contains= '{"maxContains":-1}'; +SELECT JSON_SCHEMA_VALID(@schema_max_contains, '[]'); +ERROR HY000: Invalid value for keyword maxContains +SET @schema_min_contains= '{"minContains":-1}'; +SELECT JSON_SCHEMA_VALID(@schema_min_contains, '[]'); +ERROR HY000: Invalid value for keyword minContains +SET @schema_required='{"type":"object","required":[1,"str1", "str1"]}'; +SELECT JSON_SCHEMA_VALID(@schema_required,'{"num1":1, "str1":"abc", "arr1":[1,2,3]}'); +ERROR HY000: Invalid value for keyword required +# +# MDEV-30977: Additional key values are not validating properly when using +# unevaluatedProperties with properties declared in subschemas +# +SET @unevaluatedProperties_schema= '{ + "allOf": [ + { + "type": "object", + "properties": { + "name": { "type": "string" } + } + } + ], + "properties": { + "type": { "enum": ["residential", "business"] } + }, + "required": ["type"], + "unevaluatedProperties": false +}'; +SELECT JSON_SCHEMA_VALID(@unevaluatedProperties_schema, '{"name": "joe", "type": "business", "dummy" : "hello" }'); +JSON_SCHEMA_VALID(@unevaluatedProperties_schema, '{"name": "joe", "type": "business", "dummy" : "hello" }') +0 +# +# MDEV-30995: JSON_SCHEMA_VALID is not validating case sensitive when using regex +# +SET @schema_pattern='{ + "type": "string", + "pattern": "[A-Z]" + }'; +SELECT JSON_SCHEMA_VALID(@schema_pattern, '"a"'); +JSON_SCHEMA_VALID(@schema_pattern, '"a"') +0 +SET @schema_property_names='{ + "PropertyNames":{ + "pattern": "^I_" + } + }'; +SELECT JSON_SCHEMA_VALID(@schema_property_names, '{"I_num":4}'); +JSON_SCHEMA_VALID(@schema_property_names, '{"I_num":4}') +1 +SELECT JSON_SCHEMA_VALID(@schema_property_names, '{"i_num":4}'); +JSON_SCHEMA_VALID(@schema_property_names, '{"i_num":4}') +0 +SET @schema_pattern_properties= '{ + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + } + }'; +SELECT JSON_SCHEMA_VALID(@schema_pattern_properties, '{"I_": 50}'); +JSON_SCHEMA_VALID(@schema_pattern_properties, '{"I_": 50}') +1 +SELECT JSON_SCHEMA_VALID(@schema_pattern_properties, '{"I_": 150}'); +JSON_SCHEMA_VALID(@schema_pattern_properties, '{"I_": 150}') +0 +SELECT JSON_SCHEMA_VALID(@schema_pattern_properties, '{"i_": 50}'); +JSON_SCHEMA_VALID(@schema_pattern_properties, '{"i_": 50}') +1 +SELECT JSON_SCHEMA_VALID(@schema_pattern_properties, '{"i_": 150}'); +JSON_SCHEMA_VALID(@schema_pattern_properties, '{"i_": 150}') +1 +# +# MDEV-30690: Server crashed on function JSON_SCHEMA_VALID with incorrect input json schema +# +SET @schema = '{""}'; +SELECT JSON_SCHEMA_VALID(@schema, '1'); +JSON_SCHEMA_VALID(@schema, '1') +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_schema_valid' +SET @schema = '{ + "type": "string", + "format" + }'; +SELECT JSON_SCHEMA_VALID(@schema, '1'); +JSON_SCHEMA_VALID(@schema, '1') +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_schema_valid' +SET @invalid_schema= '{"type":"object" + "properties":{ + "number1": {"type":"number"}, + "obj2": {"type":"object", + "properties": { + "key1": {"type":"number"} + } + } + } + }'; +SELECT JSON_SCHEMA_VALID(@invalid_schema, '{"number1":3, "obj2":{"key1":3}}'); +JSON_SCHEMA_VALID(@invalid_schema, '{"number1":3, "obj2":{"key1":3}}') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_schema_valid' at position 45 +# +# MDEV-30703: JSON_SCHEMA_VALID : Enum array must have at least one value +# +SET @schema = '{ + "type":"array", + "enum": [] + }'; +SELECT JSON_SCHEMA_VALID(@schema, '2'); +ERROR HY000: Invalid value for keyword enum +SET @schema = '{ + "type":"number", + "enum": [2, 2] + }'; +SELECT JSON_SCHEMA_VALID(@schema, '2'); +ERROR HY000: Invalid value for keyword enum +# +# MDEV-30704: JSON_SCHEMA_VALID: multipleOf must be greater than zero +# +SET @schema = '{ + "multipleOf": 0 + }'; +SELECT JSON_SCHEMA_VALID(@schema, '2'); +ERROR HY000: Invalid value for keyword multipleOf +SET @schema= '{ "maxLength" : -3}'; +SELECT JSON_SCHEMA_VALID(@schema, '2'); +ERROR HY000: Invalid value for keyword maxLength +SET @schema= '{ "minLength" : -3}'; +SELECT JSON_SCHEMA_VALID(@schema, '2'); +ERROR HY000: Invalid value for keyword minLength +SET @schema= '{ "maxProperties" : -3}'; +SELECT JSON_SCHEMA_VALID(@schema, '2'); +ERROR HY000: Invalid value for keyword maxProperties +SET @schema= '{ "minProperties" : -3}'; +SELECT JSON_SCHEMA_VALID(@schema, '2'); +ERROR HY000: Invalid value for keyword minProperties +SET @schema= '{ "maxItems" : -3}'; +SELECT JSON_SCHEMA_VALID(@schema, '2'); +ERROR HY000: Invalid value for keyword maxItems +SET @schema= '{ "minItems" : -3}'; +SELECT JSON_SCHEMA_VALID(@schema, '2'); +ERROR HY000: Invalid value for keyword maxLength +SET @schema= '{ "items" : ["str1"]}'; +SELECT JSON_SCHEMA_VALID(@schema, '[]'); +ERROR HY000: Invalid value for keyword items +# +# MDEV-30705: JSON_SCHEMA_VALID: schema with multipleOf for big value always return 1 +# +SET @schema = '{ + "multipleOf": 2 + }'; +SELECT JSON_SCHEMA_VALID(@schema, '9007900000000001'); +JSON_SCHEMA_VALID(@schema, '9007900000000001') +0 +SELECT JSON_SCHEMA_VALID(@schema, '9007900000000060'); +JSON_SCHEMA_VALID(@schema, '9007900000000060') +1 +SELECT JSON_SCHEMA_VALID(@schema, '9007900000000061'); +JSON_SCHEMA_VALID(@schema, '9007900000000061') +0 +# +# MDEV-31032: UBSAN|downcast of address X which does not point to an object of type +# Item_string' in sql/json_schema.cc +# +SET @old_sql_mode= @@sql_mode; +SET @schema='{ "type":"object","patternProperties": { "^I_": {"type":"number"},"^S_" : {"type":"string"} } }'; +SET SESSION sql_mode='empty_string_is_null'; +SELECT JSON_SCHEMA_VALID (@schema,'{"key1":"val0","key2":0,"I_int":0,"S_":"abc","prop0":"str0"}'); +JSON_SCHEMA_VALID (@schema,'{"key1":"val0","key2":0,"I_int":0,"S_":"abc","prop0":"str0"}') +1 +SET @@sql_mode= @old_sql_mode; +SET @property_names='{ "PropertyNames":{ "pattern": "^I_" } }'; +SET GLOBAL sql_mode=17179869183; +SET @@sql_mode=DEFAULT; +SELECT JSON_SCHEMA_VALID(@property_names, '{"I_int1":3, "I_ob1":{"key1":"val1"}}'); +JSON_SCHEMA_VALID(@property_names, '{"I_int1":3, "I_ob1":{"key1":"val1"}}') +1 +SET @@sql_mode= @old_sql_mode; +set global sql_mode=default; +# +# MDEV-30287: JSON_SCHEMA_VALID returns incorrect result for type=number +# +SET @schema= '{"type":"number"}'; +SELECT JSON_SCHEMA_VALID(@schema, '3.14'); +JSON_SCHEMA_VALID(@schema, '3.14') +1 +SELECT JSON_SCHEMA_VALID(@schema, '0zzzz'); +JSON_SCHEMA_VALID(@schema, '0zzzz') +0 +Warnings: +Warning 4038 Syntax error in JSON text in argument 2 to function 'json_schema_valid' at position 2 +SELECT JSON_SCHEMA_VALID(@schema, '-#'); +JSON_SCHEMA_VALID(@schema, '-#') +0 +Warnings: +Warning 4038 Syntax error in JSON text in argument 2 to function 'json_schema_valid' at position 2 +# +# MDEV-30689: JSON_SCHEMA_VALID for type=array return 1 for any string that starts with '[' +# +SET @schema_array= '{"type":"array"}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '['); +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()) +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)) +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 +# +# MDEV-30677: Incorrect result for "SELECT JSON_SCHEMA_VALID('{}', NULL)" +# +SELECT JSON_SCHEMA_VALID('{}', NULL); +JSON_SCHEMA_VALID('{}', NULL) +NULL +SELECT JSON_SCHEMA_VALID(NULL, '{}'); +JSON_SCHEMA_VALID(NULL, '{}') +NULL +SELECT JSON_SCHEMA_VALID(NULL, NULL); +JSON_SCHEMA_VALID(NULL, NULL) +NULL +# End of 11.1 test diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index 9bf0c9bae05..120e5085ddb 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -1775,3 +1775,1842 @@ SELECT JSON_EXTRACT('{ "my-key": 1 }', '$.my-key'); --echo # --echo # End of 10.9 Test --echo # + +--echo # Beginning of 11.1 test + +--echo # +--echo # MDEV-27128: Implement JSON Schema Validation FUNCTION +--echo # + +--echo # Checking annotations + +SET @schema_number= '{ + "title" : "This is title 1", + "description":"this is description 1", + "$comment":"This is comment 1", + "type":"number", + "deprecated":true, + "readOnly":true, + "writeOnly":false, + "example":[2], + "default":4, + "$schema": "https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5" + }'; +SELECT JSON_SCHEMA_VALID(@schema_number, '"string1"'); +SELECT JSON_SCHEMA_VALID(@schema_number, '2'); + +--echo # Checking empty schema with empty json document + +SET @schema= '{}'; + +SELECT JSON_SCHEMA_VALID(@schema, ''); +SELECT JSON_SCHEMA_VALID(@schema, '{}'); +SELECT JSON_SCHEMA_VALID(@schema, '[]'); +SELECT JSON_SCHEMA_VALID(@schema, 'null'); +SELECT JSON_SCHEMA_VALID(@schema, 'true'); +SELECT JSON_SCHEMA_VALID(@schema, 'false'); + +--echo # Checking scalar against json schema + +--echo # Checking boolean and null + +SET @schema_true= '{ "type": "boolean"}'; +SELECT JSON_SCHEMA_VALID(@schema_true, 'true'); +SELECT JSON_SCHEMA_VALID(@schema_true, 'false'); +SELECT JSON_SCHEMA_VALID(@schema_true, 'null'); + +SET @schema_true= '{ "type": "boolean", + "const":"false"}'; +SELECT JSON_SCHEMA_VALID(@schema_true, 'true'); +SET @schema_true= '{ "type": "boolean", + "enum":[true, null, false]}'; +SELECT JSON_SCHEMA_VALID(@schema_true, 'true'); +SET @schema_true= '{ "type": "boolean", + "enum": [null, false]}'; +SELECT JSON_SCHEMA_VALID(@schema_true, 'true'); +SET @schema_true= '{ "type": "boolean", + "enum": [null, true]}'; +SELECT JSON_SCHEMA_VALID(@schema_true, 'true'); +SET @schema_true= '{ "type": "boolean", + "const":"false"}'; +SELECT JSON_SCHEMA_VALID(@schema_true, 'true'); + +--echo # Type can be more than one + +SET @schema= ' + { + "type":["string", "number","array"] + }'; +SELECT JSON_SCHEMA_VALID(@schema, '{"key1":"val1"}'); +SELECT JSON_SCHEMA_VALID(@schema, '"abc"'); +SELECT JSON_SCHEMA_VALID(@schema, '3.14'); + +--echo # Checking number + +SET @schema_number= '{ + "maximum":7, + "minimum": 3, + "multipleOf":3 +}'; +SELECT JSON_SCHEMA_VALID(@schema_number, '2'); + +SET @schema_number= '{ + "type": "number", + "maximum":13, + "minimum": 4, + "multipleOf":3, + "exclusiveMaximum": 9, + "exclusiveMinimum":4 +}'; + +SELECT JSON_SCHEMA_VALID(@schema_number, '2'); +SELECT JSON_SCHEMA_VALID(@schema_number, '6'); +SELECT JSON_SCHEMA_VALID(@schema_number, '9'); +SELECT JSON_SCHEMA_VALID(@schema_number, '5'); + +SET @schema_number= '{ + "type": "number", + "maximum":100, + "minimum": 0, + "enum": [1, 2, "3", [4, 5, 6], {"key1":"val1"}] +}'; +SELECT JSON_SCHEMA_VALID(@schema_number, 1); +SELECT JSON_SCHEMA_VALID(@schema_number, 3); + +SET @schema_number= '{ + "type":"number", + "maximum":10, + "const":2 + }'; +SELECT JSON_SCHEMA_VALID(@schema_number, '3'); +SELECT JSON_SCHEMA_VALID(@schema_number, '2'); + +--echo # Checking string + +--echo # checking format keyword. (not validating for now) + +SET @schema_string= '{ + "type": "string", + "format":"date-time" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_date-time"'); +SET @schema_string= '{ + "type": "string", + "format":"date" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_date"'); +SET @schema_string= '{ + "type": "string", + "format":"time" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_time"'); +SET @schema_string= '{ + "type": "string", + "format":"duration" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_duration"'); +SET @schema_string= '{ + "type": "string", + "format":"email" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_email"'); +SET @schema_string= '{ + "type": "string", + "format":"idn-email" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_idn-email"'); +SET @schema_string= '{ + "type": "string", + "format":"hostname" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_hostname"'); +SET @schema_string= '{ + "type": "string", + "format":"idn-hostname" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_idn-hostname"'); +SET @schema_string= '{ + "type": "string", + "format":"ipv4" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_ipv4"'); +SET @schema_string= '{ + "type": "string", + "format":"ipv6" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_ipv6"'); +SET @schema_string= '{ + "type": "string", + "format":"uri" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_uri"'); +SET @schema_string= '{ + "type": "string", + "format":"uri-reference" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_uri-reference"'); +SET @schema_string= '{ + "type": "string", + "format":"iri" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_iri"'); +SET @schema_string= '{ + "type": "string", + "format":"iri-reference" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_iri-reference"'); +SET @schema_string= '{ + "type": "string", + "format":"uuid" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_uuid"'); +SET @schema_string= '{ + "type": "string", + "format":"json-pointer" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_json-pointer"'); +SET @schema_string= '{ + "type": "string", + "format":"relative-json-pointer" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_relative-json-pointer"'); +SET @schema_string= '{ + "type": "string", + "format":"regex" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"not_regex"'); + +--echo # Validating other string keywords + +SET @schema_string= '{ + "type": "string", + "maxLength":7, + "minLength": 4 +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"foobar"'); + +SET @schema_string= '{ + "type": "string", + "maxLength": 10, + "minLength": 8 +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"foobar"'); +SELECT JSON_SCHEMA_VALID(@schema_string, '"foobar123"'); + +SET @schema_string= '{ + "type": "string", + "maxLength": 10, + "minLength": 3, + "const": "foobar" +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"foobar123"'); + +SET @schema_string= '{ + "type": "string", + "enum": ["red", "green", "blue"] +}'; +SELECT JSON_SCHEMA_VALID(@schema_string, '"green"'); +SELECT JSON_SCHEMA_VALID(@schema_string, '"orange"'); + +SET @string_schema= '{ + "type":"string", + "pattern":"ab+c" + }'; +SELECT JSON_SCHEMA_VALID(@string_schema, '"abc"'); + +--echo # Validating non-scalar + +--echo # Validating array + +SET @schema_array= '{"type":"array"}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, {"key1":"val1"}]'); + + +SET @schema_array= '{"type":"array", + "maxItems": 4, + "minItems": 2}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, {"key1":"val1"}]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, false, null, "foobar"]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '[1]'); +SET @schema_array= '{"maxItems": 4, + "minItems": 2}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, {"key1":"val1"}]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, false, null, "foobar"]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2]'); + +SET @schema_array= '{ + "type":"array", + "items": {"type":"number"}, + "maxItems": 4, + "minItems": 2}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, "foobar"]'); + +SET @schema_array= '{"type":"array", + "maxItems": 4, + "minItems": 2, + "const": [1, 2, 3, 4]}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3, "foobar"]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3, 4]'); + +SET @schema_array= '{"type":"array", + "enum":[[1,2,3], [4,5,6], [7,8,9]]}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[4,5,6]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '[1,5,7]'); + +SET @schema_array= '{ + "type": "array", + "uniqueItems":true + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3, 2.0]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3, 4.0]'); + +SET @schema_array= '{ + "type": "array", + "contains": { + "type": "number" + }, + "minContains": 2, + "maxContains": 3 +}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '["string1", "string2", "string3", 1, 2, 3, 4]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '["string1", "string2", "string3", 1, 2, 3]'); + +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ] + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1",2]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '[2, "string1",2]'); + +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "items":true + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1",2]'); +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "items":false + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1",2]'); + +--echo # Checking objects + +SET @schema_object= '{"type":"object", + "properties": + { + "number1":{ + "type":"number", + "maximum":12, + "minimum":1 + }, + "string1": { + "type":"string", + "maxLength":10, + "minLength": 4 + }, + "array1": {"type":"array", + "maxItems": 4, + "minItems": 2} + } + }'; +SELECT JSON_SCHEMA_VALID(@schema_object, '{"number1":10, "string1":"foobar","array1":[1,2,3]}'); +SELECT JSON_SCHEMA_VALID(@schema_object, '{"number1":10, "string1":"foobar","array1":[1,2,3,4,5]}'); + +SET @schema_obj= '{ + "type": "object", + "properties": { + "number1":{"type":"number"}, + "string1":{"type":"string"}, + "array1":{"type":"array"} + }, + "dependentRequired": { + "number1":["string1"] + } + }'; +SELECT JSON_SCHEMA_VALID(@schema_obj, '{"array1":[1,2,3], "number1":2, "string1":"abc"}'); +SELECT JSON_SCHEMA_VALID(@schema_obj, '{"array1":[1,2,3], "number1":2}'); + +SET @schema_obj= '{"type":"object", + "properties": + { + "number1":{ + "type":"number", + "maximum":12, + "minimum":1 + }, + "key1" : { + "type":"object", + "properties": { + "key2" :{ + "type":"string" + } + } + } + }, + "enum": [{"number1":3, "key1":{"key2":"string1"}}, {"number1":5, "key1":{"key2":"string3"}}, {"number1":7, "key1":{"key2":"string5"}}] + }'; +SELECT JSON_SCHEMA_VALID(@schema_obj, '{"number1":5, "key1":{"key2":1}}'); +SELECT JSON_SCHEMA_VALID(@schema_obj, '{"number1":5, "key1":{"key2":"string1"}}'); +SELECT JSON_SCHEMA_VALID(@schema_obj, '{"number1":5, "key1":{"key2":"string7"}}'); + +SET @schema_obj= '{"type":"object", + "properties": + { + "number1":{ + "type":"number", + "maximum":12, + "minimum":1 + }, + "obj1" : { + "type":"object", + "properties": { + "obj1_1":{ + "type":"string" + }, + "obj1_2": { + "type":"array" + } + } + }, + "obj2" : { + "type":"object", + "properties" : { + "obj2_1":{ + "type":"number" + } + } + } + }, + "required":["number1", "obj2"] + }'; +SELECT JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}}'); +SELECT JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}, "obj2":{"obj2_1":7}}'); + +SET @schema_obj= '{"type":"object", + "properties": + { + "number1":{ + "type":"number", + "maximum":12, + "minimum":1 + }, + "obj1" : { + "type":"object", + "properties": { + "obj1_1":{ + "type":"string" + }, + "obj1_2": { + "type":"array" + } + } + }, + "obj2" : { + "type":"object", + "properties" : { + "obj2_1":{ + "type":"number" + } + } + } + }, + "required":["number1", "obj2"], + "const": {"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}, "obj2":{"obj2_1":7}} + }'; +SELECT JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}, "obj2":{"obj2_1":7}}'); +SELECT JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}}'); + +SET @schema_obj= '{"type":"object", + "properties": + { + "number1":{ + "type":"number", + "maximum":12, + "minimum":1 + }, + "obj1" : { + "type":"object", + "properties": { + "obj1_1":{ + "type":"string" + }, + "obj1_2": { + "type":"array" + } + } + }, + "obj2" : { + "type":"object", + "properties" : { + "obj2_1":{ + "type":"number" + } + } + } + }, + "maxProperties": 5, + "minProperties":2 + }'; +SELECT JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}, "obj2":{"obj2_1":7}}'); +SELECT JSON_SCHEMA_VALID(@schema_obj,'{"number1":1, "number2":2, "number3":3, "number4":4, "number5":5, "number6":6}'); + +SET @schema_obj= '{"type":"object", + "properties": + { + "number1":{ + "type":"number", + "maximum":12, + "minimum":1 + }, + "obj1" : { + "type":"object", + "properties": { + "obj1_1":{ + "type":"string" + }, + "obj1_2": { + "type":"array" + } + } + } + }, + "maxProperties": 3, + "minProperties":1, + "additionalProperties":false + }'; +SELECT JSON_SCHEMA_VALID(@schema_obj,'{"number1":5, "obj1":{"obj1_1":"string1", "obj1_2":[1, 2, 3]}, "obj2":"string2"}'); + +--echo # Demonstrating that irrelavent keywords for a type and irrelavent type +--echo # are ignored, and none of the keywords are mandatory, including "type". + +SET @schema_properties= '{ + "properties" : { + "number1":{ "maximum":10 }, + "string1" : { "maxLength": 3} + } + }'; +SELECT JSON_SCHEMA_VALID(@schema_properties, '{ "number1":25, "string1":"ab" }'); +SELECT JSON_SCHEMA_VALID(@schema_properties, '{ "number1":10, "string1":"ab" }'); + +SET @schema_properties= '{ + "properties" : { + "number1":{ "maximum":10 }, + "string1" : { "maxLength": 3}, + "obj1" : { + "properties":{ + "number2": {"minimum":8}, + "array2": {"uniqueItems":true} + } + } + } + }'; +SELECT JSON_SCHEMA_VALID(@schema_properties, '{ "number1":2, "string1":"ab", "obj1":{"number2":2, "array2":[1,2,3]} }'); +SELECT JSON_SCHEMA_VALID(@schema_properties, '{ "number1":2, "string1":"ab", "obj1":{"number2":10, "array2":[1,2,3]} }'); +SELECT JSON_SCHEMA_VALID(@schema_properties, '{ "number1":2, "string1":"ab", "obj1":{"array2":[1,2,3]} }'); +SELECT JSON_SCHEMA_VALID(@schema_properties, '{ "number1":2, "string1":"ab", "obj1":{"number2":10, "array2":[1,2,3,2]} }'); + +SET @schema_num= '{ + "maximum":10, + "minimum":2 + }'; +SELECT JSON_SCHEMA_VALID(@schema_num, '5'); +SELECT JSON_SCHEMA_VALID(@schema_num, '"abc"'); + +SET @schema_str= '{ + "maxLength":5, + "minLength":2, + "pattern":"a+bc" + }'; +SELECT JSON_SCHEMA_VALID(@schema_str, '"abc"'); +SELECT JSON_SCHEMA_VALID(@schema_str, '"abcadef"'); +SELECT JSON_SCHEMA_VALID(@schema_str, '"bc"'); + +SET @schema_arr= '{ + "uniqueItems":true, + "items":{"type":"string"}, + "maximum":10 + }'; +SELECT JSON_SCHEMA_VALID(@schema_arr,'["abc", "bcd", "cde"]'); +SELECT JSON_SCHEMA_VALID(@schema_arr,'["abc", "bcd", "abc"]'); +SELECT JSON_SCHEMA_VALID(@schema_arr,'["abc", "bcd", 1]'); + +SET @schema_const1= '{"const":2}'; +SELECT JSON_SCHEMA_VALID(@schema_const1, '2'); +SELECT JSON_SCHEMA_VALID(@schema_const1, '"abc"'); + +SET @schema_const2= '{"const":true}'; +SELECT JSON_SCHEMA_VALID(@schema_const2,'true'); +SELECT JSON_SCHEMA_VALID(@schema_const2,'false'); + +SET @schema_enum='{"enum":[1,2,3,"abc", [4,5,6]]}'; +SELECT JSON_SCHEMA_VALID(@schema_enum,'[4,5,6]'); +SELECT JSON_SCHEMA_VALID(@schema_enum,'4'); +SELECT JSON_SCHEMA_VALID(@schema_enum,'"abc"'); + +SET @schema_required='{"required":["num1","str1", "arr1"]}'; +SELECT JSON_SCHEMA_VALID(@schema_required,'{"num1":1, "str1":"abc", "arr1":[1,2,3]}'); +SELECT JSON_SCHEMA_VALID(@schema_required,'{"num1":1, "arr1":[1,2,3]}'); +SELECT JSON_SCHEMA_VALID(@schema_required,'"abcd"'); + +SET @schema_dep_required='{ + "dependentRequired": { + "num1":["num2","num3"], + "str1":["str2","str3"] + } + }'; +SELECT JSON_SCHEMA_VALID(@schema_dep_required,'{"num1":1, "num2":"abc", "num3":[1,2,3]}'); +SELECT JSON_SCHEMA_VALID(@schema_dep_required,'{"num1":1, "num2":"abc", "num3":[1,2,3], "str1":"abcd"}'); +SELECT JSON_SCHEMA_VALID(@schema_dep_required,'{"num1":1, "num2":"abc", "num3":[1,2,3], "arr1":[1,2,3]}'); + +--echo # Checking syntax error +SET @invalid_schema= '{"type":"object" + "properties":{ + "number1": {"type":"number"}, + "obj2": {"type":"object", + "properties": { + "key1": {"type":"number"} + } + } + } + }'; +SELECT JSON_SCHEMA_VALID(@invalid_schema, '{"number1":3, "obj2":{"key1":3}}'); + +SET @invalid_json= '{"type":"array", + "maxItems": 4, + "minItems": 2, + "const": [1, 2, 3, 4]}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3, 4'); + +SET @schema_string= '{ + "type": "string", + "maxLength":-2 + }'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema_string, '"abcxyz"'); + +SET @schema_number= '{ + "type": "number", + "multipleOf":-3 + }'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema_number, '3'); + +SET @schema_object= '{ + "type": "object", + "properties":{"num1":{"type":"number"}}, + "required":{} + }'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema_object, '{"num1":2}'); + +SET @schema_string= '{ + "type": "string", + "maxLength":-10 + }'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema_string, '"str1"'); + +SET @schema_number= '{"type":"numberz"}'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema_number, '"string1"'); + +--echo # Using JSON_SCHEMA_VALID() as a constraint validation to insert into table + +CREATE TABLE str_table (val_str JSON CHECK(JSON_SCHEMA_VALID('{ + "type":"string", + "maxLength":5, + "minLength":2, + "enum":["ab", "cd", "abc", "def", "abcdef"] + }', val_str))); +CREATE TABLE num_table(val_num JSON CHECK(JSON_SCHEMA_VALID('{ + "type":"number", + "minimum":10, + "maximum":30, + "exclusiveMinimum":11, + "exclusiveMaximum":29, + "multipleOf":5, + "const":15 + }', val_num))); +CREATE TABLE true_table(val_true JSON CHECK(JSON_SCHEMA_VALID('{ + "type":"boolean", + "enum":[true, false, null] + }', val_true))); +CREATE TABLE false_table (val_false JSON CHECK(JSON_SCHEMA_VALID('{ + "type":"boolean" + }', val_false))); +CREATE TABLE null_table (val_null JSON CHECK(JSON_SCHEMA_VALID('{ + "type":"null" + }', val_null))); +CREATE TABLE arr_table (val_arr JSON CHECK(JSON_SCHEMA_VALID('{ + "type":"array", + "uniqueItems":true, + "maxItems":5, + "minItems":1, + "items":true, + "prefixItems":[{"type":"number"}] + }', val_arr))); +CREATE TABLE obj_table(val_obj JSON CHECK(JSON_SCHEMA_VALID('{ + "type":"object", + "properties": { + "number1":{ + "type":"number", + "maximum":5, + "const":4 + }, + "string1":{ + "type":"string", + "maxLength":5, + "minLength":3 + }, + "object1":{ + "type":"object", + "properties":{ + "key1": {"type":"string"}, + "key2":{"type":"array"}, + "key3":{"type":"number", "minimum":3} + }, + "dependentRequired": { "key1":["key3"] } + } + }, + "required":["number1","object1"] + }', val_obj))); + +INSERT INTO str_table VALUES ('"ab"'), ('"cd"'), ('"abc"'), ('"def"'); +--error ER_CONSTRAINT_FAILED +INSERT INTO str_table VALUES ('"feb"'); +--error ER_CONSTRAINT_FAILED +INSERT INTO str_table VALUES('"abcdef"'); +--error ER_CONSTRAINT_FAILED +INSERT INTO str_table VALUES('"fedcba"'); +SELECT * FROM str_table; + + +INSERT INTO num_table values('15'); +--error ER_CONSTRAINT_FAILED +INSERT INTO num_table values('25'); +SELECT * FROM num_table; + +INSERT INTO true_table VALUES ('true'); +SELECT * FROM true_table; + +INSERT INTO false_table VALUES('false'); +SELECT * FROM false_table; + +INSERT INTO arr_table VALUES ('[10, 2, "abc"]'); +INSERT INTO arr_table VALUES('[100]'); +--error ER_CONSTRAINT_FAILED +INSERT INTO arr_table VALUES ('["str1", 2, "abc", 2.0]'); +SELECT * FROM arr_table; + +INSERT INTO obj_table VALUES('{"number1":4, "string1":"abcd", "object1":{"key1":"val1", "key2":[1,2,3, "string1"], "key3":4}}'); +--error ER_CONSTRAINT_FAILED +INSERT INTO obj_table VALUES('{"number1":3, "string1":"abcd", "object1":{"key1":"val1", "key2":[1,2,3, "string1"], "key3":4}}'); +--error ER_CONSTRAINT_FAILED +INSERT INTO obj_table VALUES('{"number1":3, "string1":"abcd"}'); +--error ER_CONSTRAINT_FAILED +INSERT INTO obj_table VALUES('{"number1":3, "string1":"abcd", "object1":{"key1":"val1", "key2":[1,2,3, "string1"]}'); +SELECT * FROM obj_table; + +DROP TABLE str_table, num_table, true_table, false_table, null_table, arr_table, obj_table; + +--echo # array validation + +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "additionalItems" : {"type":"number"}, + "unevaluatedItems": {"type":"string"}, + "items":{"type":"array"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], "2", "string"]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "2", "string"]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], [1,2]]'); + +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "additionalItems" : {"type":"number"}, + "unevaluatedItems": {"type":"string"}, + "items": true + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], "2", "string"]'); + +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "additionalItems" : {"type":"number"}, + "unevaluatedItems": {"type":"string"}, + "items": false + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], "2", "string"]'); + +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "additionalItems" : {"type":"number"}, + "unevaluatedItems": {"type":"string"}, + "items": [{"type":"string"}] + }'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], "2", "string"]'); + +--echo # Removing items + +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "additionalItems" : {"type":"number"}, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", [1,2], "2", "string"]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]'); + +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "additionalItems" : true, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]'); + +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "additionalItems" : false, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]'); + +--echo # Using items in place of additionalItems + +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "items" : false, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]'); +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "items" : true, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]'); + +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "items" : {"type":"number"}, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2, 3]'); + +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "items" : {"type":"number"}, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "string2", "string3"]'); + +--echo # Removing items and additionalItems both + +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "unevaluatedItems": {"type":"number"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "string2", "string3"]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", 1, 2]'); + + +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "unevaluatedItems": true + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "string2", "string3"]'); + +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ], + "unevaluatedItems": false + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "string2", "string3"]'); + +--echo # Removing items, additionalItems, unevaluatedItems + +SET @schema_array= '{ + "type": "array", + "prefixItems": [ + { "type": "number", "maximum": 10, "minimum":3}, + { "type": "string" } + ] + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, "string1", "string2", "string3"]'); + + +--echo # Removing prefixItems + + +SET @schema_array= '{ + "type": "array", + "items": { "type": "number", "maximum": 10, "minimum":3}, + "additionalItems" : {"type":"number"}, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, 6,"2", "string"]'); + + +SET @schema_array= '{ + "type": "array", + "items": { "type": "number", "maximum": 10, "minimum":3}, + "additionalItems" : {"type":"string"}, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, 6,"2", "string"]'); + +SET @schema_array= '{ + "type": "array", + "items": true, + "additionalItems" : {"type":"string"}, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, 6,"2", "string"]'); + +SET @schema_array= '{ + "type": "array", + "items": false, + "additionalItems" : {"type":"string"}, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[5, 6,"2", "string"]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '[]'); + +--echo # Removing prefixItems and additionalItems + +SET @schema_array= '{ + "type": "array", + "items": {"type":"string"}, + "unevaluatedItems": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 2]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '["str1", "str2"]'); + +SET @schema_array= '{ + "type": "array", + "items": {"type":"string"}, + "unevaluatedItems": {"type":"number"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 2]'); + +--echo # removing prefixItems, additionalItems and unevaluatedItems + +SET @schema_array= '{ + "type": "array", + "items": {"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 2]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '["str1", "str2"]'); + +--echo # Checking that additionalItems alone has no effect on schema without items/prefixItems +--echo # regardless existence of unevaluatedItems + +SET @schema_array= '{ + "type": "array", + "additionalItems": {"type":"string"}, + "unevaluatedItems": {"type":"number"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 1]'); + +SET @schema_array= '{ + "type": "array", + "additionalItems": true, + "unevaluatedItems": {"type":"number"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 1]'); + +SET @schema_array= '{ + "type": "array", + "additionalItems": false, + "unevaluatedItems": {"type":"number"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '["str1", "str2", 1]'); + + +--echo # checking that unevaluatedItems alone can have effect on schema validation + +SET @schema_array= '{ + "type": "array", + "unevaluatedItems": {"type":"number"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1]'); + +SET @schema_array= '{ + "type": "array", + "unevaluatedItems": {"type":"number"} + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, "str1"]'); + +SET @schema_array= '{ + "type": "array", + "unevaluatedItems": false + }'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, "str1"]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '[]'); +SELECT JSON_SCHEMA_VALID(@schema_array, '[1,2,3]'); + + +--echo # Object validation + +SET @property_names= '{ + "PropertyNames":{ + "pattern": "^I_" + } + }'; +SELECT JSON_SCHEMA_VALID(@property_names, '{"I_int1":3, "O_ob1":{"key1":"val1"}}'); +SELECT JSON_SCHEMA_VALID(@property_names, '{"I_int1":3, "I_ob1":{"key1":"val1"}}'); + +--echo # checking that when a match is found in properties or patternProperties, it must validate and +--echo # validation result affects the schema. If key is not found in properties or patternProperties, and +--echo # additionalProperties exists, it must validate regardless of existence or value for unevaluatedProperties +--echo # and the result of validation with additionalProperties affects result of whole schema + +SET @object_schema= '{ + "type":"object", + "properties": { + "key1":{"type":"string"}, + "key2":{"type":"number", "maximum":50} + }, + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "additionalProperties":{ + "type":"array", + "maxItems":5 + }, + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": [1,2,3], "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":[1,2,3], "S_":"abc", "some_prop1":[1,2,3]}'); +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":"string1"}'); + +--echo # removing patternProperties to check that validation falls back on additionalProperties and +--echo # existence of unevaluatedProperties still does not change anything because of existence of additional +--echo # properties + + +SET @object_schema= '{ + "type":"object", + "properties": { + "key1":{"type":"string"}, + "key2":{"type":"number", "maximum":50} + }, + "additionalProperties":{ + "type":"array", + "maxItems":5 + }, + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":[1,2,3], "S_":[1,2,3], "some_prop1":[1,2,3]}'); + +--echo # Remvoing additionalProperties to check that validation falls back on unevaluatedProperties + +SET @object_schema= '{ + "type":"object", + "properties": { + "key1":{"type":"string"}, + "key2":{"type":"number", "maximum":50} + }, + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":10, "S_":"abc", "some_prop1":[1,2,3]}'); +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":10, "S_":"abc", "some_prop1":"str"}'); + +--echo # Removing unevaluatedProperties has no effect on result when additionalProperties is present + +SET @object_schema= '{ + "type":"object", + "properties": { + "key1":{"type":"string"}, + "key2":{"type":"number", "maximum":50} + }, + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "additionalProperties":{ + "type":"array", + "maxItems":5 + } + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":"str1"}'); + +SET @object_schema= '{ + "type":"object", + "properties": { + "key1":{"type":"string"}, + "key2":{"type":"number", "maximum":50} + }, + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "additionalProperties": false + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); + +SET @object_schema= '{ + "type":"object", + "properties": { + "key1":{"type":"string"}, + "key2":{"type":"number", "maximum":50} + }, + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "additionalProperties": true + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); + + +--echo # Checking that in absence of additionalProperties, validation falls back on evaluatedProperties + +SET @object_schema= '{ + "type":"object", + "properties": { + "key1":{"type":"string"}, + "key2":{"type":"number", "maximum":50} + }, + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 3, "I_int":20, "S_":"abc", "some_prop1":"str1"}'); +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 3, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); + +SET @object_schema= '{ + "type":"object", + "properties": { + "key1":{"type":"string"}, + "key2":{"type":"number", "maximum":50} + }, + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 3, "I_int":"str2", "S_":"abc", "some_prop1":[1,2,3]}'); +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 3, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); + +--echo # Properties to check if patternProperties get evaluated but keys not found in patternProperties get evaluated against +--echo # additionalProperties regardless of existence of unevaluatedProperperties + +SET @object_schema= '{ + "type":"object", + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "additionalProperties":{ + "type":"array", + "maxItems":5 + }, + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":[1, 2, 3], "key2": [1, 2, 3], "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); + +SET @object_schema= '{ + "type":"object", + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "additionalProperties":{ + "type":"array", + "maxItems":5 + } + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":[1, 2, 3], "key2": [1, 2, 3], "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); + +--echo # Checking that in absence of additionalProperties and properties, the keys not found in patternProperties are +--echo # evaluated against unevaluatedProperties +SET @object_schema= '{ + "type":"object", + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + }, + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": "str2", "I_int":20, "S_":"abc", "some_prop1":"str1"}'); + +--echo # checking that in absence of properties, additionalProperties and unevaluatedPropoerties, the keys that are +--echo # not found are considered validated. + +SET @object_schema= '{ + "type":"object", + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + } + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); + +--echo # checking that additionalProperties are evaluated in absence of patternProperties and properties, regardless +--echo # of presence of unevaluatedProperties + +SET @object_schema= '{ + "type":"object", + "additionalProperties":{ + "type":"array", + "maxItems":5 + }, + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":[1,2,3], "key2": [1,2,3], "I_int":[1,2,3], "S_":[1,2,3], "some_prop1":[1,2,3]}'); + +SET @object_schema= '{ + "type":"object", + "additionalProperties":{ + "type":"array", + "maxItems":5 + } + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": 10, "I_int":20, "S_":"abc", "some_prop1":[1,2,3]}'); +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":[1,2,3], "key2": [1,2,3], "I_int":[1,2,3], "S_":[1,2,3], "some_prop1":[1,2,3]}'); + +--echo # Checking that in absence of properties, patternProperties and additionalProperties, validation falls back on unevaluatedProperties + +SET @object_schema= '{ + "type":"object", + "unevaluatedProperties":{"type":"string"} + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": "str1", "I_int":"str2", "S_":"abc", "some_prop1":"str3"}'); +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":[1,2,3], "key2": [1,2,3], "I_int":[1,2,3], "S_":[1,2,3], "some_prop1":[1,2,3]}'); + +SET @object_schema= '{ + "type":"object", + "unevaluatedProperties": false + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": "str1", "I_int":"str2", "S_":"abc", "some_prop1":"str3"}'); +SELECT JSON_SCHEMA_VALID(@object_schema, '{}'); + +SET @object_schema= '{ + "type":"object", + "unevaluatedProperties": true + }'; +SELECT JSON_SCHEMA_VALID(@object_schema, '{"key1":"val1", "key2": "str1", "I_int":"str2", "S_":"abc", "some_prop1":"str3"}'); +SELECT JSON_SCHEMA_VALID(@object_schema, '{}'); + +SET @json_schema_dependent_schemas='{ + "type": "object", + "properties": { + "str1": { "type": "string" }, + "num1": { "type": "number" } + }, + + "required": ["str1"], + + "dependentSchemas": { + "num1": { + "properties": { + "str2": { "type": "string" } + }, + "required": ["str2"] + } + } +}'; +SELECT JSON_SCHEMA_VALID(@json_schema_dependent_schemas, '{ "str1": "str", "num1":4}'); +SELECT JSON_SCHEMA_VALID(@json_schema_dependent_schemas, '{ "str1": "str"}'); + +--echo # Validating logic + +SET @not_schema= '{ + "not":{ + "maximum": 4 + } + }'; +SELECT JSON_SCHEMA_VALID(@not_schema, '{"I_int1":3, "O_ob1":{"key1":"val1"}}'); +SELECT JSON_SCHEMA_VALID(@not_schema, '3'); +SELECT JSON_SCHEMA_VALID(@not_schema, '10'); + +SET @not_schema= '{ + "not":{ + "properties": { + "num1" : {"type":"number", "maximum":5}, + "string1" : { "maxLength": 3} + } + } + }'; +SELECT JSON_SCHEMA_VALID(@not_schema, '{"num1":10, "string2":"abcd"}'); +SELECT JSON_SCHEMA_VALID(@not_schema, '{"num1":2, "string2":"abcd"}'); + +SET @any_of_schema= '{ + "anyOf":[{ + "properties": { + "num1" : {"type":"number", "maximum":5}, + "string1" : { "maxLength": 3} + } + }, + { + "properties":{ + "num1" : {"type":"number", "maximum": 1}, + "string1" : { "maxLength":5} + } + } + ] + }'; +SELECT JSON_SCHEMA_VALID(@any_of_schema, '{"num1":2, "string1":"abcd"}'); +SELECT JSON_SCHEMA_VALID(@any_of_schema, '{"num1":2, "string1":"abc"}'); + +SET @any_of_schema= '{ + "anyOf": [ + {"type":"number", "maximum":5}, + {"type":"string"} + ] + }'; +SELECT JSON_SCHEMA_VALID(@any_of_schema, '2'); +SELECT JSON_SCHEMA_VALID(@any_of_schema, '6'); +SELECT JSON_SCHEMA_VALID(@any_of_schema, '[1, 2, 3]'); + +SET @one_of_schema= '{ + "oneOf":[{ + "properties": { + "num1" : {"type":"number", "maximum":5}, + "string1" : { "maxLength": 3} + } + }, + { + "properties":{ + "num1" : {"type":"number", "maximum": 1}, + "string1" : { "maxLength":5} + } + } + ] + }'; +SELECT JSON_SCHEMA_VALID(@one_of_schema, '{"num1":2, "string1":"abcd"}'); +SELECT JSON_SCHEMA_VALID(@one_of_schema, '{"num1":2, "string1":"abc"}'); + +SET @one_of_schema= '{ + "oneOf": [ + {"type":"number", "maximum":5}, + {"type":"number", "maximum":3} + ] + }'; +SELECT JSON_SCHEMA_VALID(@one_of_schema, '2'); +SELECT JSON_SCHEMA_VALID(@one_of_schema, '4'); + +SET @all_of_schema= '{ + "allOf":[{ + "properties": { + "num1" : {"type":"number", "maximum":5}, + "string1" : { "maxLength": 3} + } + }, + { + "properties":{ + "num1" : {"type":"number", "maximum": 1}, + "string1" : { "maxLength":5} + } + } + ] + }'; +SELECT JSON_SCHEMA_VALID(@all_of_schema, '{"num1":2, "string1":"abcd"}'); + +SET @all_of_schema= '{ + "allOf":[ + { + "properties":{ + "num1": {"type":"number"}, + "string1": {"type":"string"} + } + }, + { + "properties":{ + "num1": {"maximum":10}, + "string1": {"maxLength":5} + } + } + ] + }'; +SELECT JSON_SCHEMA_VALID(@all_of_schema, '{"num1":5, "string1":"abc"}'); +SELECT JSON_SCHEMA_VALID(@all_of_schema, '{"num1":5, "string1":"foobar"}'); + +SET @condition_schema= '{ + "if" : {"maximum":30, "multipleOf":3}, + "then":{"minimum":5}, + "else":{"minimum":10} + }'; +SELECT JSON_SCHEMA_VALID(@condition_schema, '6'); +SELECT JSON_SCHEMA_VALID(@condition_schema, '4'); +SELECT JSON_SCHEMA_VALID(@condition_schema, '13'); + +SET @condition_schema= '{ + "if" : {"maximum":30, "multipleOf":3} + }'; +SELECT JSON_SCHEMA_VALID(@condition_schema, '6'); +SELECT JSON_SCHEMA_VALID(@condition_schema, '7'); + +SET @condition_schema= '{ + "then":{"minimum":5}, + "else":{"minimum":10} + }'; +SELECT JSON_SCHEMA_VALID(@condition_schema, '4'); +SELECT JSON_SCHEMA_VALID(@condition_schema, '11'); + +--echo # Checking unevaluatedProperperties with logical properties + +SET @all_of_unevaluated='{ + "allOf": [ + { + "type": "object", + "properties": { + "street_address": { "type": "string" }, + "city": { "type": "string" }, + "state": { "type": "string" } + }, + "required": ["street_address", "city", "state"] + } + ], + + "properties": { + "type": { "enum": ["residential", "business"] } + }, + "required": ["type"], + "unevaluatedProperties": false +}'; +SELECT JSON_SCHEMA_VALID(@all_of_unevaluated, '{ + "street_address": "1600 Pennsylvania Avenue NW", + "city": "Washington", + "state": "DC", + "type": "business" +}'); + +SET @all_of_unevaluated='{ + "allOf": [ + { + "type": "object", + "properties": { + "street_address": { "type": "string" }, + "city": { "type": "string" }, + "state": { "type": "string" } + }, + "required": ["street_address", "city", "state"] + } + ], + + "unevaluatedProperties": {"type":"number"} +}'; +SELECT JSON_SCHEMA_VALID(@all_of_unevaluated, '{ + "street_address": "1600 Pennsylvania Avenue NW", + "city": "Washington", + "state": "DC", + "type": "business" +}'); + +SET @any_of_unevaluated='{ + "anyOf": [ + { + "type": "object", + "properties": { + "street_address": { "type": "string" }, + "city": { "type": "string" }, + "state": { "type": "string" } + }, + "required": ["street_address", "city", "state"] + } + ], + + "unevaluatedProperties": {"type":"number"} +}'; +SELECT JSON_SCHEMA_VALID(@any_of_unevaluated, '{ + "street_address": "1600 Pennsylvania Avenue NW", + "city": "Washington", + "state": "DC", + "type": "business" +}'); + +SET @all_of_unevaluated='{ + "allOf": [ + { + "type": "array" + }, + { + "maxItems":10 + }, + { + "prefixItems": [ {"type":"number"}, {"type":"string"}], + "additionalItems":{"type":"array"} + } + ], + + "unevaluatedItems": {"type":"number"} +}'; +SELECT JSON_SCHEMA_VALID(@all_of_unevaluated, '[1, "str", 2]'); + +SET @all_of_unevaluated='{ + "anyOf": [ + { + "type": "array" + }, + { + "maxItems":10 + }, + { + "prefixItems": [ {"type":"number"}, {"type":"string"}], + "additionalItems":{"type":"array"} + } + ], + + "unevaluatedItems": {"type":"number"} +}'; +SELECT JSON_SCHEMA_VALID(@all_of_unevaluated, '[1, "str", 2]'); + +SET @all_of_unevaluated='{ + "oneOf": [ + { + "type": "array" + }, + { + "maxItems":10 + }, + { + "prefixItems": [ {"type":"number"}, {"type":"string"}], + "additionalItems":{"type":"array"} + } + ], + + "unevaluatedItems": {"type":"number"} +}'; +SELECT JSON_SCHEMA_VALID(@all_of_unevaluated, '[1, "str", 2]'); + +--echo # Media string + +SET @schema_media_string= '{ + "type": "string", + "contentMediaType": "text/html" +}'; +SELECT JSON_SCHEMA_VALID(@schema_media_string, '"str1"'); + +SET @schema_reference= '{"$ref": "http://example.com/custom-email-validator.json#"}'; +--error ER_JSON_SCHEMA_KEYWORD_UNSUPPORTED +SELECT JSON_SCHEMA_VALID(@schema_reference, '{}'); + +SET @schema_reference= '{"$id": "http://example.com/custom-email-validator.json#"}'; +--error ER_JSON_SCHEMA_KEYWORD_UNSUPPORTED +SELECT JSON_SCHEMA_VALID(@schema_reference, '{}'); + +SET @schema_reference= '{"$anchor": "http://example.com/custom-email-validator.json#"}'; +--error ER_JSON_SCHEMA_KEYWORD_UNSUPPORTED +SELECT JSON_SCHEMA_VALID(@schema_reference, '{}'); + +SET @schema_reference= '{"$defs": "http://example.com/custom-email-validator.json#"}'; +--error ER_JSON_SCHEMA_KEYWORD_UNSUPPORTED +SELECT JSON_SCHEMA_VALID(@schema_reference, '{}'); + + + +--echo # +--echo # MDEV-30795: JSON_SCHEMA_VALID bugs mentioned in comment +--echo # +SET @schema= '{ + "type":"array", + "uniqueItems":true + }'; +SELECT JSON_SCHEMA_VALID(@schema, '[null, null]'); + +SET @schema_max_items= '{"maxItems":-1}'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema_max_items, '[]'); + +SET @schema_min_items= '{"minItems":-1}'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema_min_items, '[]'); + +SET @schema_max_properties= '{"maxProperties":-1}'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema_max_properties, '{}'); + +SET @schema_min_properties= '{"minProperties":-1}'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema_min_properties, '{}'); + +SET @schema_multiple_of= '{"multipleOf":-1}'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema_multiple_of, '2'); + +SET @schema_max_contains= '{"maxContains":-1}'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema_max_contains, '[]'); + +SET @schema_min_contains= '{"minContains":-1}'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema_min_contains, '[]'); + +SET @schema_required='{"type":"object","required":[1,"str1", "str1"]}'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema_required,'{"num1":1, "str1":"abc", "arr1":[1,2,3]}'); + +--echo # +--echo # MDEV-30977: Additional key values are not validating properly when using +--echo # unevaluatedProperties with properties declared in subschemas +--echo # + +SET @unevaluatedProperties_schema= '{ + "allOf": [ + { + "type": "object", + "properties": { + "name": { "type": "string" } + } + } + ], + "properties": { + "type": { "enum": ["residential", "business"] } + }, + "required": ["type"], + "unevaluatedProperties": false +}'; +SELECT JSON_SCHEMA_VALID(@unevaluatedProperties_schema, '{"name": "joe", "type": "business", "dummy" : "hello" }'); + +--echo # +--echo # MDEV-30995: JSON_SCHEMA_VALID is not validating case sensitive when using regex +--echo # + +SET @schema_pattern='{ + "type": "string", + "pattern": "[A-Z]" + }'; +SELECT JSON_SCHEMA_VALID(@schema_pattern, '"a"'); + +SET @schema_property_names='{ + "PropertyNames":{ + "pattern": "^I_" + } + }'; +SELECT JSON_SCHEMA_VALID(@schema_property_names, '{"I_num":4}'); +SELECT JSON_SCHEMA_VALID(@schema_property_names, '{"i_num":4}'); + +SET @schema_pattern_properties= '{ + "patternProperties": { + "^I_": {"type":"number", "maximum":100}, + "^S_" : {"type":"string", "maxLength":4} + } + }'; +SELECT JSON_SCHEMA_VALID(@schema_pattern_properties, '{"I_": 50}'); +SELECT JSON_SCHEMA_VALID(@schema_pattern_properties, '{"I_": 150}'); +SELECT JSON_SCHEMA_VALID(@schema_pattern_properties, '{"i_": 50}'); +SELECT JSON_SCHEMA_VALID(@schema_pattern_properties, '{"i_": 150}'); + +--echo # +--echo # MDEV-30690: Server crashed on function JSON_SCHEMA_VALID with incorrect input json schema +--echo # + +SET @schema = '{""}'; +SELECT JSON_SCHEMA_VALID(@schema, '1'); + +SET @schema = '{ + "type": "string", + "format" + }'; +SELECT JSON_SCHEMA_VALID(@schema, '1'); + +SET @invalid_schema= '{"type":"object" + "properties":{ + "number1": {"type":"number"}, + "obj2": {"type":"object", + "properties": { + "key1": {"type":"number"} + } + } + } + }'; +SELECT JSON_SCHEMA_VALID(@invalid_schema, '{"number1":3, "obj2":{"key1":3}}'); + +--echo # +--echo # MDEV-30703: JSON_SCHEMA_VALID : Enum array must have at least one value +--echo # + +SET @schema = '{ + "type":"array", + "enum": [] + }'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema, '2'); + +SET @schema = '{ + "type":"number", + "enum": [2, 2] + }'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema, '2'); + + +--echo # +--echo # MDEV-30704: JSON_SCHEMA_VALID: multipleOf must be greater than zero +--echo # + +SET @schema = '{ + "multipleOf": 0 + }'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema, '2'); + +SET @schema= '{ "maxLength" : -3}'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema, '2'); + +SET @schema= '{ "minLength" : -3}'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema, '2'); + +SET @schema= '{ "maxProperties" : -3}'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema, '2'); + +SET @schema= '{ "minProperties" : -3}'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema, '2'); + +SET @schema= '{ "maxItems" : -3}'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema, '2'); + +SET @schema= '{ "minItems" : -3}'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema, '2'); + +SET @schema= '{ "items" : ["str1"]}'; +--error ER_JSON_INVALID_VALUE_FOR_KEYWORD +SELECT JSON_SCHEMA_VALID(@schema, '[]'); + + +--echo # +--echo # MDEV-30705: JSON_SCHEMA_VALID: schema with multipleOf for big value always return 1 +--echo # +SET @schema = '{ + "multipleOf": 2 + }'; +SELECT JSON_SCHEMA_VALID(@schema, '9007900000000001'); +SELECT JSON_SCHEMA_VALID(@schema, '9007900000000060'); +SELECT JSON_SCHEMA_VALID(@schema, '9007900000000061'); + +--echo # +--echo # MDEV-31032: UBSAN|downcast of address X which does not point to an object of type +--echo # Item_string' in sql/json_schema.cc +--echo # + +SET @old_sql_mode= @@sql_mode; + +SET @schema='{ "type":"object","patternProperties": { "^I_": {"type":"number"},"^S_" : {"type":"string"} } }'; +SET SESSION sql_mode='empty_string_is_null'; +SELECT JSON_SCHEMA_VALID (@schema,'{"key1":"val0","key2":0,"I_int":0,"S_":"abc","prop0":"str0"}'); + +SET @@sql_mode= @old_sql_mode; + +SET @property_names='{ "PropertyNames":{ "pattern": "^I_" } }'; +SET GLOBAL sql_mode=17179869183; +SET @@sql_mode=DEFAULT; +SELECT JSON_SCHEMA_VALID(@property_names, '{"I_int1":3, "I_ob1":{"key1":"val1"}}'); + +SET @@sql_mode= @old_sql_mode; +set global sql_mode=default; + +--echo # +--echo # MDEV-30287: JSON_SCHEMA_VALID returns incorrect result for type=number +--echo # + +SET @schema= '{"type":"number"}'; + +SELECT JSON_SCHEMA_VALID(@schema, '3.14'); +SELECT JSON_SCHEMA_VALID(@schema, '0zzzz'); +SELECT JSON_SCHEMA_VALID(@schema, '-#'); + +--echo # +--echo # MDEV-30689: JSON_SCHEMA_VALID for type=array return 1 for any string that starts with '[' +--echo # + + +SET @schema_array= '{"type":"array"}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '['); + +SELECT JSON_SCHEMA_VALID(repeat('[', 100000), json_object()); + +SELECT JSON_SCHEMA_VALID(json_object(), repeat('[', 10000000)); + +--echo # +--echo # MDEV-30677: Incorrect result for "SELECT JSON_SCHEMA_VALID('{}', NULL)" +--echo # +SELECT JSON_SCHEMA_VALID('{}', NULL); +SELECT JSON_SCHEMA_VALID(NULL, '{}'); +SELECT JSON_SCHEMA_VALID(NULL, NULL); + +--echo # End of 11.1 test diff --git a/mysql-test/main/innodb_mysql_lock2.result b/mysql-test/main/innodb_mysql_lock2.result index 9dd5bddc085..a03e1d842b2 100644 --- a/mysql-test/main/innodb_mysql_lock2.result +++ b/mysql-test/main/innodb_mysql_lock2.result @@ -12,8 +12,8 @@ # This test makes sense only in REPEATABLE-READ mode as # in SERIALIZABLE mode all statements that read data take # shared lock on them to enforce its semantics. -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ # Prepare playground by creating tables, views, # routines and triggers used in tests. diff --git a/mysql-test/main/innodb_mysql_lock2.test b/mysql-test/main/innodb_mysql_lock2.test index e5bb4bd9565..b35c23ce659 100644 --- a/mysql-test/main/innodb_mysql_lock2.test +++ b/mysql-test/main/innodb_mysql_lock2.test @@ -31,7 +31,7 @@ CALL mtr.add_suppression("Unsafe statement written to the binary log using state --echo # This test makes sense only in REPEATABLE-READ mode as --echo # in SERIALIZABLE mode all statements that read data take --echo # shared lock on them to enforce its semantics. -select @@session.tx_isolation; +select @@session.transaction_isolation; --echo # Prepare playground by creating tables, views, --echo # routines and triggers used in tests. diff --git a/mysql-test/main/json_debug_nonembedded.result b/mysql-test/main/json_debug_nonembedded.result index e759cafa38b..0e7458edd9f 100644 --- a/mysql-test/main/json_debug_nonembedded.result +++ b/mysql-test/main/json_debug_nonembedded.result @@ -7,6 +7,13 @@ SET @json1= '{"key1":"val1"}'; SET @json2= '{"key1":"val1"}'; SELECT JSON_OVERLAPS(@json1, @json2); ERROR HY000: Thread stack overrun: 'used bytes' used of a 'available' byte stack, and 'X' bytes needed. Consider increasing the thread_stack system variable. +SET @schema_array= '{ + "type":"array", + "items": {"type":"number"}, + "maxItems": 4, + "minItems": 2}'; +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3]'); +ERROR HY000: Thread stack overrun: 'used bytes' used of a 'available' byte stack, and 'X' bytes needed. Consider increasing the thread_stack system variable. SET @@debug_dbug= @saved_dbug; # # End of 10.9 test diff --git a/mysql-test/main/json_debug_nonembedded.test b/mysql-test/main/json_debug_nonembedded.test index 5813b46e556..fb4fe67b5d3 100644 --- a/mysql-test/main/json_debug_nonembedded.test +++ b/mysql-test/main/json_debug_nonembedded.test @@ -15,6 +15,15 @@ SET @json2= '{"key1":"val1"}'; --error ER_STACK_OVERRUN_NEED_MORE SELECT JSON_OVERLAPS(@json1, @json2); +SET @schema_array= '{ + "type":"array", + "items": {"type":"number"}, + "maxItems": 4, + "minItems": 2}'; +--replace_regex /overrun: [0-9]* bytes used of a [0-9]* byte stack, and [0-9]* bytes needed/overrun: 'used bytes' used of a 'available' byte stack, and 'X' bytes needed/ +--error ER_STACK_OVERRUN_NEED_MORE +SELECT JSON_SCHEMA_VALID(@schema_array, '[1, 2, 3]'); + SET @@debug_dbug= @saved_dbug; --echo # diff --git a/mysql-test/main/log_state.result b/mysql-test/main/log_state.result index 5e7aac81b0c..18c8da708a9 100644 --- a/mysql-test/main/log_state.result +++ b/mysql-test/main/log_state.result @@ -243,7 +243,7 @@ rows_examined sql_text 4 UPDATE t1 SET a=a+sleep(.02) WHERE a>2 8 UPDATE t1 SET a=a+sleep(.02) ORDER BY a DESC 1 UPDATE t2 set b=b+sleep(.02) limit 1 -4 UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2) +6 UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2) 6 DELETE FROM t1 WHERE a=a+sleep(.02) ORDER BY a LIMIT 2 disconnect con2; connection default; diff --git a/mysql-test/main/mix2_myisam.result b/mysql-test/main/mix2_myisam.result index 842d5bcfb94..1044704c518 100644 --- a/mysql-test/main/mix2_myisam.result +++ b/mysql-test/main/mix2_myisam.result @@ -905,8 +905,8 @@ drop table t1,t2; create table t1 (id int unsigned not null auto_increment, code tinyint unsigned not null, name char(20) not null, primary key (id), key (code), unique (name)) engine=MyISAM; BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; -SELECT @@tx_isolation,@@global.tx_isolation; -@@tx_isolation @@global.tx_isolation +SELECT @@transaction_isolation,@@global.transaction_isolation; +@@transaction_isolation @@global.transaction_isolation SERIALIZABLE REPEATABLE-READ insert into t1 (code, name) values (1, 'Tim'), (1, 'Monty'), (2, 'David'); select id, code, name from t1 order by id; diff --git a/mysql-test/main/multi_update.result b/mysql-test/main/multi_update.result index 41377eec27b..2364ee732ce 100644 --- a/mysql-test/main/multi_update.result +++ b/mysql-test/main/multi_update.result @@ -441,12 +441,10 @@ create table t1 (col1 int); create table t2 (col1 int); update t1,t2 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1; delete t1 from t1,t2 where t1.col1 < (select max(col1) from t1) and t1.col1 = t2.col1; -ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data drop table t1,t2; create table t1(a int); create table t2(a int); delete from t1,t2 using t1,t2 where t1.a=(select a from t1); -ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data drop table t1, t2; create table t1 (a int, b int); insert into t1 values (1, 2), (2, 3), (3, 4); diff --git a/mysql-test/main/multi_update.test b/mysql-test/main/multi_update.test index 33d9e980878..325f63f696f 100644 --- a/mysql-test/main/multi_update.test +++ b/mysql-test/main/multi_update.test @@ -391,7 +391,6 @@ drop table t1, t2, t3; create table t1 (col1 int); create table t2 (col1 int); update t1,t2 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1; --- error ER_UPDATE_TABLE_USED delete t1 from t1,t2 where t1.col1 < (select max(col1) from t1) and t1.col1 = t2.col1; drop table t1,t2; @@ -400,7 +399,6 @@ drop table t1,t2; # create table t1(a int); create table t2(a int); ---error ER_UPDATE_TABLE_USED delete from t1,t2 using t1,t2 where t1.a=(select a from t1); drop table t1, t2; # End of 4.1 tests diff --git a/mysql-test/main/myisam_explain_non_select_all.result b/mysql-test/main/myisam_explain_non_select_all.result index 7a185d7fa1a..84b8d9ae4c5 100644 --- a/mysql-test/main/myisam_explain_non_select_all.result +++ b/mysql-test/main/myisam_explain_non_select_all.result @@ -57,7 +57,7 @@ EXPLAIN EXTENDED DELETE FROM t1 WHERE a < 10; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: -Note 1003 delete from `test`.`t1` where `test`.`t1`.`a` < 10 +Note 1003 delete from `test`.`t1` using dual where `test`.`t1`.`a` < 10 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 2 @@ -228,20 +228,19 @@ INSERT INTO t2 VALUES (1), (2), (3); # EXPLAIN UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3); id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where; FirstMatch 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 -2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3); id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 3 33.33 Using where; FirstMatch 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 -2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: -Note 1003 /* select#1 */ update `test`.`t1` set `test`.`t1`.`a` = 10 where <in_optimizer>(1,<exists>(/* select#2 */ select 1 from `test`.`t2` where `test`.`t2`.`b` < 3 and 1)) +Note 1003 update `test`.`t1` semi join (`test`.`t2`) set `test`.`t1`.`a` = 10 where `test`.`t2`.`b` < 3 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 4 -Handler_read_rnd_next 1 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3); @@ -260,7 +259,8 @@ Handler_read_rnd_next 5 # Status of testing query execution: Variable_name Value Handler_read_key 4 -Handler_read_rnd_next 5 +Handler_read_rnd 3 +Handler_read_rnd_next 9 Handler_update 3 DROP TABLE t1, t2; @@ -276,16 +276,16 @@ INSERT INTO t2 VALUES (1), (2), (3); EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where -2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where +1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where; FirstMatch(t1) FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where -2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where +1 PRIMARY t2 ALL NULL NULL NULL NULL 3 33.33 Using where; FirstMatch(t1) Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 -Note 1003 /* select#1 */ update `test`.`t1` set `test`.`t1`.`a` = 10 where <in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select `test`.`t2`.`b` from `test`.`t2` where `test`.`t1`.`a` < 3 and <cache>(`test`.`t1`.`a`) = `test`.`t2`.`b`)) +Note 1003 update `test`.`t1` semi join (`test`.`t2`) set `test`.`t1`.`a` = 10 where `test`.`t2`.`b` = `test`.`t1`.`a` and `test`.`t1`.`a` < 3 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 4 @@ -533,7 +533,7 @@ EXPLAIN EXTENDED DELETE FROM t1 WHERE a > 1 LIMIT 1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where Warnings: -Note 1003 delete from `test`.`t1` where `test`.`t1`.`a` > 1 limit 1 +Note 1003 delete from `test`.`t1` using dual where `test`.`t1`.`a` > 1 limit 1 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 2 @@ -574,7 +574,7 @@ EXPLAIN EXTENDED DELETE FROM t1 WHERE 0; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE Warnings: -Note 1003 delete from `test`.`t1` where 0 +Note 1003 delete from `test`.`t1` using dual where 0 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 2 @@ -650,7 +650,7 @@ EXPLAIN EXTENDED DELETE FROM t1 WHERE a = 3; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range a a 5 NULL 1 100.00 Using where Warnings: -Note 1003 delete from `test`.`t1` where `test`.`t1`.`a` = 3 +Note 1003 delete from `test`.`t1` using dual where `test`.`t1`.`a` = 3 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 5 @@ -689,7 +689,7 @@ EXPLAIN EXTENDED DELETE FROM t1 WHERE a < 3; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range a a 5 NULL 1 100.00 Using where Warnings: -Note 1003 delete from `test`.`t1` where `test`.`t1`.`a` < 3 +Note 1003 delete from `test`.`t1` using dual where `test`.`t1`.`a` < 3 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 5 @@ -726,7 +726,7 @@ EXPLAIN EXTENDED DELETE FROM t1 WHERE t1.a > 0 ORDER BY t1.a; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE Warnings: -Note 1003 delete from `test`.`t1` where `test`.`t1`.`a` > 0 order by `test`.`t1`.`a` +Note 1003 delete from `test`.`t1` using dual where `test`.`t1`.`a` > 0 order by `test`.`t1`.`a` # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 3 @@ -763,7 +763,7 @@ EXPLAIN EXTENDED DELETE FROM t1 WHERE t1.a > 0 ORDER BY t1.a; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 100.00 Using where Warnings: -Note 1003 delete from `test`.`t1` where `test`.`t1`.`a` > 0 order by `test`.`t1`.`a` +Note 1003 delete from `test`.`t1` using dual where `test`.`t1`.`a` > 0 order by `test`.`t1`.`a` # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 3 @@ -804,7 +804,7 @@ EXPLAIN EXTENDED DELETE FROM t1 WHERE (@a:= a) ORDER BY a LIMIT 1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 index NULL PRIMARY 4 NULL 1 100.00 Using where Warnings: -Note 1003 delete from `test`.`t1` where @a:=`test`.`t1`.`a` order by `test`.`t1`.`a` limit 1 +Note 1003 delete from `test`.`t1` using dual where @a:=`test`.`t1`.`a` order by `test`.`t1`.`a` limit 1 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 3 @@ -846,7 +846,7 @@ EXPLAIN EXTENDED DELETE FROM t1 ORDER BY a ASC, b ASC LIMIT 1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 100.00 Using filesort Warnings: -Note 1003 delete from `test`.`t1` order by `test`.`t1`.`a`,`test`.`t1`.`b` limit 1 +Note 1003 delete from `test`.`t1` using dual order by `test`.`t1`.`a`,`test`.`t1`.`b` limit 1 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 7 @@ -942,16 +942,16 @@ INSERT INTO t2 VALUES (1), (2), (3), (1000); # EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where -2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 4 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; FirstMatch(t1) FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2); id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where -2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 4 100.00 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 25.00 Using where; FirstMatch(t1) Warnings: -Note 1003 /* select#1 */ update `test`.`t1` set `test`.`t1`.`a` = 10 where <in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` where <cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`)) +Note 1003 update `test`.`t1` semi join (`test`.`t2`) set `test`.`t1`.`a` = 10 where `test`.`t2`.`a` = `test`.`t1`.`a` # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 4 @@ -998,7 +998,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00 Using where 2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where Warnings: -Note 1003 /* select#1 */ delete from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a1`,<exists>(/* select#2 */ select `test`.`t2`.`a2` from `test`.`t2` where `test`.`t2`.`a2` > 2 and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`a2`)) +Note 1003 /* select#1 */ delete from `test`.`t1` using dual where <in_optimizer>(`test`.`t1`.`a1`,<exists>(/* select#2 */ select `test`.`t2`.`a2` from `test`.`t2` where `test`.`t2`.`a2` > 2 and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`a2`)) # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 4 @@ -1032,16 +1032,16 @@ INSERT INTO t1 VALUES (1), (2), (3), (4), (5); # EXPLAIN DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where -2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 5 +1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where; FirstMatch(t1) FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2); id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00 Using where -2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00 +1 PRIMARY t2 ALL NULL NULL NULL NULL 5 20.00 Using where; FirstMatch(t1) Warnings: -Note 1003 /* select#1 */ delete from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a1`,<exists>(/* select#2 */ select `test`.`t2`.`a2` from `test`.`t2` where `test`.`t2`.`a2` > 2 and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`a2`)) +Note 1003 delete from `test`.`t1` using (`test`.`t2`) where `test`.`t2`.`a2` > 2 and `test`.`t1`.`a1` = `test`.`t2`.`a2` # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 4 @@ -1124,7 +1124,7 @@ EXPLAIN EXTENDED DELETE FROM t1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL 5 NULL Deleting all rows Warnings: -Note 1003 delete from `test`.`t1` +Note 1003 delete from `test`.`t1` using dual # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 3 @@ -1168,7 +1168,7 @@ EXPLAIN EXTENDED DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 index NULL a 15 NULL 5 100.00 Using where Warnings: -Note 1003 delete from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 +Note 1003 delete from `test`.`t2` using dual where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 8 @@ -1347,7 +1347,7 @@ EXPLAIN EXTENDED DELETE FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 5 100.00 Using where Warnings: -Note 1003 delete from `test`.`t1` where `test`.`t1`.`i` > 10 and `test`.`t1`.`i` <= 18 order by `test`.`t1`.`i` limit 5 +Note 1003 delete from `test`.`t1` using dual where `test`.`t1`.`i` > 10 and `test`.`t1`.`i` <= 18 order by `test`.`t1`.`i` limit 5 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 4 @@ -1390,7 +1390,7 @@ EXPLAIN EXTENDED DELETE FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: -Note 1003 delete from `test`.`t1` where `test`.`t1`.`i` > 10 and `test`.`t1`.`i` <= 18 order by `test`.`t1`.`i` limit 5 +Note 1003 delete from `test`.`t1` using dual where `test`.`t1`.`i` > 10 and `test`.`t1`.`i` <= 18 order by `test`.`t1`.`i` limit 5 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 4 @@ -1441,7 +1441,7 @@ EXPLAIN EXTENDED DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 index NULL a 15 NULL 5 100.00 Using where Warnings: -Note 1003 delete from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 +Note 1003 delete from `test`.`t2` using dual where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 8 @@ -1489,7 +1489,7 @@ EXPLAIN EXTENDED DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 index NULL a 15 NULL 5 100.00 Using where Warnings: -Note 1003 delete from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 +Note 1003 delete from `test`.`t2` using dual where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 8 @@ -1536,7 +1536,7 @@ EXPLAIN EXTENDED DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: -Note 1003 delete from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 +Note 1003 delete from `test`.`t2` using dual where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 8 @@ -1588,7 +1588,7 @@ EXPLAIN EXTENDED DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort Warnings: -Note 1003 delete from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 +Note 1003 delete from `test`.`t2` using dual where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 8 @@ -1641,7 +1641,7 @@ EXPLAIN EXTENDED DELETE FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 index_merge key1,key2 key1,key2 5,5 NULL 7 100.00 Using sort_union(key1,key2); Using where; Using filesort Warnings: -Note 1003 delete from `test`.`t2` where `test`.`t2`.`key1` < 13 or `test`.`t2`.`key2` < 14 order by `test`.`t2`.`key1` +Note 1003 delete from `test`.`t2` using dual where `test`.`t2`.`key1` < 13 or `test`.`t2`.`key2` < 14 order by `test`.`t2`.`key1` # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 6 @@ -1692,7 +1692,7 @@ EXPLAIN EXTENDED DELETE FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 5 100.00 Using where Warnings: -Note 1003 delete from `test`.`t2` where `test`.`t2`.`i` > 10 and `test`.`t2`.`i` <= 18 order by `test`.`t2`.`i` desc limit 5 +Note 1003 delete from `test`.`t2` using dual where `test`.`t2`.`i` > 10 and `test`.`t2`.`i` <= 18 order by `test`.`t2`.`i` desc limit 5 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 4 @@ -1737,7 +1737,7 @@ EXPLAIN EXTENDED DELETE FROM t2 ORDER BY a, b DESC LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using filesort Warnings: -Note 1003 delete from `test`.`t2` order by `test`.`t2`.`a`,`test`.`t2`.`b` desc limit 5 +Note 1003 delete from `test`.`t2` using dual order by `test`.`t2`.`a`,`test`.`t2`.`b` desc limit 5 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 6 @@ -1789,7 +1789,7 @@ EXPLAIN EXTENDED DELETE FROM t2 ORDER BY a DESC, b DESC LIMIT 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 index NULL a 6 NULL 5 100.00 Warnings: -Note 1003 delete from `test`.`t2` order by `test`.`t2`.`a` desc,`test`.`t2`.`b` desc limit 5 +Note 1003 delete from `test`.`t2` using dual order by `test`.`t2`.`a` desc,`test`.`t2`.`b` desc limit 5 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 6 @@ -2380,7 +2380,7 @@ EXPLAIN EXTENDED DELETE FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range c1_idx c1_idx 2 NULL 2 100.00 Using where; Using filesort Warnings: -Note 1003 delete from `test`.`t1` where `test`.`t1`.`c1_idx` = 'y' order by `test`.`t1`.`pk` desc limit 2 +Note 1003 delete from `test`.`t1` using dual where `test`.`t1`.`c1_idx` = 'y' order by `test`.`t1`.`pk` desc limit 2 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 6 @@ -2610,9 +2610,9 @@ DROP TABLE t1; #57 CREATE TABLE t1(f1 INT); EXPLAIN EXTENDED UPDATE t1 SET f2=1 ORDER BY f2; -ERROR 42S22: Unknown column 'f2' in 'order clause' +ERROR 42S22: Unknown column 'f2' in 'field list' UPDATE t1 SET f2=1 ORDER BY f2; -ERROR 42S22: Unknown column 'f2' in 'order clause' +ERROR 42S22: Unknown column 'f2' in 'field list' DROP TABLE t1; #62 CREATE TABLE t1 (a INT); @@ -2723,7 +2723,7 @@ EXPLAIN EXTENDED DELETE FROM v1 WHERE a < 4; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 100.00 Using where Warnings: -Note 1003 /* select#1 */ delete from `test`.`t1` where `test`.`t1`.`a` < 4 +Note 1003 /* select#1 */ delete from `test`.`t1` using dual where `test`.`t1`.`a` < 4 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 3 @@ -2950,17 +2950,17 @@ INSERT INTO t2 VALUES (1), (2), (3); EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where -2 DEPENDENT SUBQUERY <derived3> unique_subquery distinct_key distinct_key 5 func 1 +1 PRIMARY <derived3> eq_ref distinct_key distinct_key 5 test.t1.a 1 3 DERIVED t2 ALL NULL NULL NULL NULL 3 Using filesort FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where -2 DEPENDENT SUBQUERY <derived3> unique_subquery distinct_key distinct_key 5 func 1 100.00 +1 PRIMARY <derived3> eq_ref distinct_key distinct_key 5 test.t1.a 1 100.00 3 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using filesort Warnings: -Note 1003 /* select#1 */ update `test`.`t1` set `test`.`t1`.`a` = 10 where <in_optimizer>(`test`.`t1`.`a`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`a`) in <temporary table> on distinct_key))) +Note 1003 /* select#1 */ update (/* select#3 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x` join `test`.`t1` set `test`.`t1`.`a` = 10 where `x`.`b` = `test`.`t1`.`a` # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 4 diff --git a/mysql-test/main/mysql_upgrade-6984.result b/mysql-test/main/mysql_upgrade-6984.result index 301fdfc3bfd..dd266c2f208 100644 --- a/mysql-test/main/mysql_upgrade-6984.result +++ b/mysql-test/main/mysql_upgrade-6984.result @@ -167,5 +167,4 @@ OK connect con1,localhost,root,foo,,,; update mysql.global_priv set priv=json_compact(json_remove(priv, '$.plugin', '$.authentication_string')) where user='root'; flush privileges; -set global event_scheduler=OFF; # restart diff --git a/mysql-test/main/mysql_upgrade-6984.test b/mysql-test/main/mysql_upgrade-6984.test index f46c122cf02..93888d556d4 100644 --- a/mysql-test/main/mysql_upgrade-6984.test +++ b/mysql-test/main/mysql_upgrade-6984.test @@ -21,8 +21,6 @@ connect(con1,localhost,root,foo,,,); update mysql.global_priv set priv=json_compact(json_remove(priv, '$.plugin', '$.authentication_string')) where user='root'; flush privileges; -# Load event table -set global event_scheduler=OFF; let MYSQLD_DATADIR= `select @@datadir`; --remove_file $MYSQLD_DATADIR/mariadb_upgrade_info diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result index ba8135306dd..1342bc65f17 100644 --- a/mysql-test/main/opt_trace.result +++ b/mysql-test/main/opt_trace.result @@ -4272,6 +4272,16 @@ QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES explain delete from t0 where t0.a<3 { "steps": [ { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "delete from t0 using dual where t0.a < 3" + } + ] + } + }, + { "table": "t0", "range_analysis": { "table_scan": { @@ -4303,7 +4313,7 @@ explain delete from t0 where t0.a<3 { }, "group_index_range": { "chosen": false, - "cause": "no join" + "cause": "no group by or distinct" }, "chosen_range_access_summary": { "range_access_plan": { @@ -4467,6 +4477,16 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 { } }, { + "table": "t0", + "rowid_filters": [ + { + "key": "a", + "build_cost": 0.001129926, + "rows": 3 + } + ] + }, + { "selectivity_for_indexes": [ { "index_name": "a", @@ -4532,6 +4552,16 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 { } }, { + "table": "t1", + "rowid_filters": [ + { + "key": "a", + "build_cost": 0.001129926, + "rows": 3 + } + ] + }, + { "selectivity_for_indexes": [ { "index_name": "a", diff --git a/mysql-test/main/order_by.result b/mysql-test/main/order_by.result index 96f5d9a49c3..a6d148679b6 100644 --- a/mysql-test/main/order_by.result +++ b/mysql-test/main/order_by.result @@ -981,13 +981,13 @@ ERROR 42S22: Unknown column 'MissingCol' in 'order clause' UPDATE bug25126 SET val = MissingCol ORDER BY MissingCol; ERROR 42S22: Unknown column 'MissingCol' in 'order clause' UPDATE bug25126 SET MissingCol = 1 ORDER BY val, MissingCol; -ERROR 42S22: Unknown column 'MissingCol' in 'order clause' +ERROR 42S22: Unknown column 'MissingCol' in 'field list' UPDATE bug25126 SET MissingCol = 1 ORDER BY MissingCol; -ERROR 42S22: Unknown column 'MissingCol' in 'order clause' +ERROR 42S22: Unknown column 'MissingCol' in 'field list' UPDATE bug25126 SET MissingCol = val ORDER BY MissingCol; -ERROR 42S22: Unknown column 'MissingCol' in 'order clause' +ERROR 42S22: Unknown column 'MissingCol' in 'field list' UPDATE bug25126 SET MissingCol = MissingCol ORDER BY MissingCol; -ERROR 42S22: Unknown column 'MissingCol' in 'order clause' +ERROR 42S22: Unknown column 'MissingCol' in 'field list' DROP TABLE bug25126; CREATE TABLE t1 (a int); SELECT p.a AS val, q.a AS val1 FROM t1 p, t1 q ORDER BY val > 1; diff --git a/mysql-test/main/partition_innodb.result b/mysql-test/main/partition_innodb.result index 95ca989eabf..8238650012f 100644 --- a/mysql-test/main/partition_innodb.result +++ b/mysql-test/main/partition_innodb.result @@ -303,12 +303,12 @@ PARTITION p2 VALUES LESS THAN MAXVALUE ); INSERT INTO t1 VALUES (1,1), (2,2), (3,3), (4,4), (5,5), (6,6), (7,7), (8,8), (9,9), (10,10), (11,11); -SET @old_tx_isolation := @@session.tx_isolation; +SET @old_transaction_isolation := @@session.transaction_isolation; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; SET autocommit = 0; UPDATE t1 SET DATA = data*2 WHERE id = 3; UPDATE t1 SET data = data*2 WHERE data = 2; -SET @@session.tx_isolation = @old_tx_isolation; +SET @@session.transaction_isolation = @old_transaction_isolation; DROP TABLE t1; # Bug#37721, test of ORDER BY on PK and WHERE on INDEX CREATE TABLE t1 ( diff --git a/mysql-test/main/partition_innodb.test b/mysql-test/main/partition_innodb.test index 563a750b81b..aaca678750b 100644 --- a/mysql-test/main/partition_innodb.test +++ b/mysql-test/main/partition_innodb.test @@ -321,7 +321,7 @@ PARTITION BY RANGE(id) ( INSERT INTO t1 VALUES (1,1), (2,2), (3,3), (4,4), (5,5), (6,6), (7,7), (8,8), (9,9), (10,10), (11,11); -SET @old_tx_isolation := @@session.tx_isolation; +SET @old_transaction_isolation := @@session.transaction_isolation; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; SET autocommit = 0; @@ -344,7 +344,7 @@ UPDATE t1 SET data = data*2 WHERE data = 2; #--replace_regex /.*---TRANSACTION [0-9]+ [0-9]+, .*, OS thread id [0-9]+// /MariaDB thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/ #SHOW ENGINE InnoDB STATUS; -SET @@session.tx_isolation = @old_tx_isolation; +SET @@session.transaction_isolation = @old_transaction_isolation; DROP TABLE t1; diff --git a/mysql-test/main/ps.result b/mysql-test/main/ps.result index a2dbce216aa..cb7b215a110 100644 --- a/mysql-test/main/ps.result +++ b/mysql-test/main/ps.result @@ -696,21 +696,21 @@ set @@time_zone:='Japan'; execute stmt; @@time_zone Japan -prepare stmt from "select @@tx_isolation"; +prepare stmt from "select @@transaction_isolation"; execute stmt; -@@tx_isolation +@@transaction_isolation REPEATABLE-READ set transaction isolation level read committed; execute stmt; -@@tx_isolation +@@transaction_isolation REPEATABLE-READ set transaction isolation level serializable; execute stmt; -@@tx_isolation +@@transaction_isolation REPEATABLE-READ -set @@tx_isolation=default; +set @@transaction_isolation=default; execute stmt; -@@tx_isolation +@@transaction_isolation REPEATABLE-READ deallocate prepare stmt; prepare stmt from "create temporary table t1 (letter enum('','a','b','c') diff --git a/mysql-test/main/ps.test b/mysql-test/main/ps.test index bb6ce7d4048..e779eefcb4d 100644 --- a/mysql-test/main/ps.test +++ b/mysql-test/main/ps.test @@ -763,13 +763,13 @@ prepare stmt from "select @@time_zone"; execute stmt; set @@time_zone:='Japan'; execute stmt; -prepare stmt from "select @@tx_isolation"; +prepare stmt from "select @@transaction_isolation"; execute stmt; set transaction isolation level read committed; execute stmt; set transaction isolation level serializable; execute stmt; -set @@tx_isolation=default; +set @@transaction_isolation=default; execute stmt; deallocate prepare stmt; diff --git a/mysql-test/main/sargable_date_cond.result b/mysql-test/main/sargable_date_cond.result new file mode 100644 index 00000000000..11b6684789d --- /dev/null +++ b/mysql-test/main/sargable_date_cond.result @@ -0,0 +1,2007 @@ +drop table if exists t0,t1,t2,t3; +create table t0(a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1(a int); +insert into t1 select A.a + B.a* 10 from t0 A, t0 B; +create table t2 (pk int primary key, a datetime, b date, key(a), key(b)); +insert into t2 +select +A.a*10+B.a, +date_add(date_add('2017-01-01', interval A.a*8 day), interval B.a hour), +date_add('2017-01-01', interval A.a*7 day) +from t1 A, t0 B; +analyze table t2; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status Table is already up to date +# +# "YEAR(datetime_col) CMP year_value", basic checks +# +select count(*) from t2 where year(a) < 2018; +count(*) +460 +# Compare the results, they must be equal: +select count(*) from t2 where a < '2018-01-01'; +count(*) +460 +explain format=json select count(*) from t2 where year(a) < 2018; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.063940854, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 451, + "cost": 0.063940854, + "filtered": 100, + "attached_condition": "t2.a < '2018-01-01 00:00:00'", + "using_index": true + } + } + ] + } +} +# Check rewrite for a prepared statement: +execute immediate +"explain format=json select * from t2 where year(a) < ?" + using 2018; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.1671618, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "possible_keys": ["a"], + "loops": 1, + "rows": 1000, + "cost": 0.1671618, + "filtered": 45.09999847, + "attached_condition": "t2.a < '2018-01-01 00:00:00'" + } + } + ] + } +} +prepare stmt from "select count(*) from t2 where year(a) < 2018"; +execute stmt; +count(*) +460 +execute stmt; +count(*) +460 +create or replace view v1 as select count(*) from t2 where year(a) < 2018; +select * from v1; +count(*) +460 +create or replace procedure sp() select count(*) from t2 where year(a) < 2018; +call sp(); +count(*) +460 +call sp(); +count(*) +460 +# Prepared statement with a placeholder +prepare stmt from "select count(*) from t2 where year(a) < ?"; +execute stmt using 2018; +count(*) +460 +execute stmt using 2017; +count(*) +0 +select count(*) from t2 where year(a) <= 2018; +count(*) +920 +select count(*) from t2 where a < '2019-01-01'; +count(*) +920 +explain format=json select count(*) from t2 where year(a) <= 2018; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.126438894, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 903, + "cost": 0.126438894, + "filtered": 100, + "attached_condition": "t2.a <= '2018-12-31 23:59:59'", + "using_index": true + } + } + ] + } +} +select count(*) from t2 where year(a) > 2018; +count(*) +80 +select count(*) from t2 where a > '2018-12-31 23:59:59.999999'; +count(*) +80 +explain format=json select count(*) from t2 where year(a) > 2018; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.014752874, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 97, + "cost": 0.014752874, + "filtered": 100, + "attached_condition": "t2.a > '2018-12-31 23:59:59'", + "using_index": true + } + } + ] + } +} +select count(*) from t2 where year(a) >= 2018; +count(*) +540 +select count(*) from t2 where a >= '2018-01-01'; +count(*) +540 +explain format=json select count(*) from t2 where year(a) >= 2018; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.077250914, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 549, + "cost": 0.077250914, + "filtered": 100, + "attached_condition": "t2.a >= '2018-01-01 00:00:00'", + "using_index": true + } + } + ] + } +} +select count(*) from t2 where year(a) = 2017; +count(*) +460 +select count(*) from t2 where a >= '2017-01-01' and a < '2018-01-01'; +count(*) +460 +explain format=json select count(*) from t2 where year(a) = 2017; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.063940854, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 451, + "cost": 0.063940854, + "filtered": 100, + "attached_condition": "t2.a between '2017-01-01 00:00:00' and '2017-12-31 23:59:59'", + "using_index": true + } + } + ] + } +} +# +# "YEAR(datetime_col) CMP year_value", reverse argument order +# +select count(*) from t2 where 2017 < year(a); +count(*) +540 +select count(*) from t2 where a >= '2018-01-01'; +count(*) +540 +explain format=json select count(*) from t2 where 2017 < year(a); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.077250914, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 549, + "cost": 0.077250914, + "filtered": 100, + "attached_condition": "t2.a > '2017-12-31 23:59:59'", + "using_index": true + } + } + ] + } +} +select count(*) from t2 where a >= '2018-01-01'; +count(*) +540 +explain format=json select count(*) from t2 where 2018 <= year(a); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.077250914, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 549, + "cost": 0.077250914, + "filtered": 100, + "attached_condition": "t2.a >= '2018-01-01 00:00:00'", + "using_index": true + } + } + ] + } +} +select count(*) from t2 where 2018 > year(a); +count(*) +460 +select count(*) from t2 where a < '2018-01-01'; +count(*) +460 +explain format=json select count(*) from t2 where 2018 > year(a); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.063940854, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 451, + "cost": 0.063940854, + "filtered": 100, + "attached_condition": "t2.a < '2018-01-01 00:00:00'", + "using_index": true + } + } + ] + } +} +select count(*) from t2 where a < '2019-01-01'; +count(*) +920 +explain format=json select count(*) from t2 where 2018 >= year(a); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.126438894, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 903, + "cost": 0.126438894, + "filtered": 100, + "attached_condition": "t2.a <= '2018-12-31 23:59:59'", + "using_index": true + } + } + ] + } +} +select count(*) from t2 where 2018 = year(a); +count(*) +460 +select count(*) from t2 where a >= '2018-01-01' and a < '2019-01-01'; +count(*) +460 +explain format=json select count(*) from t2 where 2018 = year(a); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.064079124, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 452, + "cost": 0.064079124, + "filtered": 100, + "attached_condition": "t2.a between '2018-01-01 00:00:00' and '2018-12-31 23:59:59'", + "using_index": true + } + } + ] + } +} +# +# "DATE(datetime_col) CMP date_value", basic checks +# +select count(*) from t2 where date(a) < '2017-06-01'; +count(*) +190 +select count(*) from t2 where a < '2017-06-01'; +count(*) +190 +explain format=json select count(*) from t2 where date(a) < '2017-06-01'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.027058904, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 186, + "cost": 0.027058904, + "filtered": 100, + "attached_condition": "t2.a < '2017-06-01 00:00:00'", + "using_index": true + } + } + ] + } +} +select count(*) from t2 where date(a) <= '2017-06-03'; +count(*) +200 +select count(*) from t2 where a < '2017-06-04'; +count(*) +200 +explain format=json select count(*) from t2 where date(a) <= '2017-06-03'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.028441604, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 196, + "cost": 0.028441604, + "filtered": 100, + "attached_condition": "t2.a <= '2017-06-03 23:59:59'", + "using_index": true + } + } + ] + } +} +select count(*) from t2 where date(a) > '2018-06-01'; +count(*) +350 +select count(*) from t2 where a >= '2018-06-02'; +count(*) +350 +explain format=json select count(*) from t2 where date(a) > '2018-06-01'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.051773094, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 363, + "cost": 0.051773094, + "filtered": 100, + "attached_condition": "t2.a > '2018-06-01 23:59:59'", + "using_index": true + } + } + ] + } +} +select count(*) from t2 where date(a) >= '2018-06-01'; +count(*) +350 +select count(*) from t2 where a >= '2018-06-01'; +count(*) +350 +explain format=json select count(*) from t2 where date(a) >= '2018-06-01'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.051773094, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 363, + "cost": 0.051773094, + "filtered": 100, + "attached_condition": "t2.a >= '2018-06-01 00:00:00'", + "using_index": true + } + } + ] + } +} +select count(*) from t2 where date(a) = '2017-06-02'; +count(*) +10 +select count(*) from t2 where a >= '2017-06-02' and a < '2017-06-03'; +count(*) +10 +explain format=json select count(*) from t2 where date(a) = '2017-06-02'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.002723384, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 10, + "cost": 0.002723384, + "filtered": 100, + "attached_condition": "t2.a between '2017-06-02 00:00:00' and '2017-06-02 23:59:59'", + "using_index": true + } + } + ] + } +} +# +# "DATE(datetime_col) CMP date_value", reverse order +# +select count(*) from t2 where '2017-06-01' > date(a); +count(*) +190 +select count(*) from t2 where '2017-06-01' > a; +count(*) +190 +explain format=json select count(*) from t2 where '2017-06-01' > date(a); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.027058904, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 186, + "cost": 0.027058904, + "filtered": 100, + "attached_condition": "t2.a < '2017-06-01 00:00:00'", + "using_index": true + } + } + ] + } +} +select count(*) from t2 where '2017-06-03' >= date(a); +count(*) +200 +select count(*) from t2 where '2017-06-03' >= a; +count(*) +200 +explain format=json select count(*) from t2 where '2017-06-03' >= date(a); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.028441604, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 196, + "cost": 0.028441604, + "filtered": 100, + "attached_condition": "t2.a <= '2017-06-03 23:59:59'", + "using_index": true + } + } + ] + } +} +select count(*) from t2 where '2018-06-01' < date(a); +count(*) +350 +select count(*) from t2 where '2018-06-02' <= a; +count(*) +350 +explain format=json select count(*) from t2 where '2018-06-01' < date(a); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.051773094, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 363, + "cost": 0.051773094, + "filtered": 100, + "attached_condition": "t2.a > '2018-06-01 23:59:59'", + "using_index": true + } + } + ] + } +} +select count(*) from t2 where '2018-06-01' <= date(a); +count(*) +350 +select count(*) from t2 where '2018-06-01' <= a; +count(*) +350 +explain format=json select count(*) from t2 where '2018-06-01' <= date(a); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.051773094, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 363, + "cost": 0.051773094, + "filtered": 100, + "attached_condition": "t2.a >= '2018-06-01 00:00:00'", + "using_index": true + } + } + ] + } +} +select count(*) from t2 where '2017-06-02' = date(a); +count(*) +10 +select count(*) from t2 where a >= '2017-06-02' and a < '2017-06-03'; +count(*) +10 +explain format=json select count(*) from t2 where '2017-06-02' = date(a); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.002723384, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 10, + "cost": 0.002723384, + "filtered": 100, + "attached_condition": "t2.a between '2017-06-02 00:00:00' and '2017-06-02 23:59:59'", + "using_index": true + } + } + ] + } +} +# Check rewrite of a more complicated query +explain format=json select * from t2 as t21 force index(a), +t2 as t22 force index(a) +where year(t21.a) < 2018 and t21.b > '2017-11-01' + and date(t22.a) >= '2017-02-01' and t22.b > '2017-11-01'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 300.4906324, + "nested_loop": [ + { + "table": { + "table_name": "t21", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 451, + "cost": 0.558056003, + "filtered": 56, + "index_condition": "t21.a < '2018-01-01 00:00:00'", + "attached_condition": "t21.b > '2017-11-01'" + } + }, + { + "block-nl-join": { + "table": { + "table_name": "t22", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 252.56, + "rows": 961, + "cost": 299.9325764, + "filtered": 56, + "index_condition": "t22.a >= '2017-02-01 00:00:00'", + "attached_condition": "t22.a >= '2017-02-01 00:00:00' and t22.b > '2017-11-01'" + }, + "buffer_type": "flat", + "buffer_size": "7Kb", + "join_type": "BNL", + "attached_condition": "t22.b > '2017-11-01'" + } + } + ] + } +} +# +# Incorrect const values processing (no rewrite is possible) +# +explain format=json select * from t2 where year(a) = -1; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.1671618, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "loops": 1, + "rows": 1000, + "cost": 0.1671618, + "filtered": 100, + "attached_condition": "year(t2.a) = -1" + } + } + ] + } +} +explain format=json select * from t2 where year(a) > -5; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.1671618, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "loops": 1, + "rows": 1000, + "cost": 0.1671618, + "filtered": 100, + "attached_condition": "year(t2.a) > -5" + } + } + ] + } +} +explain format=json select * from t2 where year(a) < -1; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.1671618, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "loops": 1, + "rows": 1000, + "cost": 0.1671618, + "filtered": 100, + "attached_condition": "year(t2.a) < -1" + } + } + ] + } +} +explain format=json select * from t2 where year(a) <= 10000; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.1671618, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "loops": 1, + "rows": 1000, + "cost": 0.1671618, + "filtered": 100, + "attached_condition": "year(t2.a) <= 10000" + } + } + ] + } +} +explain format=json select * from t2 where year(a) >= 10020; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.1671618, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "loops": 1, + "rows": 1000, + "cost": 0.1671618, + "filtered": 100, + "attached_condition": "year(t2.a) >= 10020" + } + } + ] + } +} +explain format=json select * from t2 where date(a) = '10000-01-01'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.1671618, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "loops": 1, + "rows": 1000, + "cost": 0.1671618, + "filtered": 100, + "attached_condition": "cast(t2.a as date) = '10000-01-01'" + } + } + ] + } +} +Warnings: +Warning 1292 Incorrect datetime value: '10000-01-01' +explain format=json select * from t2 where date(a) < '-1-01-01'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.1671618, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "loops": 1, + "rows": 1000, + "cost": 0.1671618, + "filtered": 100, + "attached_condition": "cast(t2.a as date) < '-1-01-01'" + } + } + ] + } +} +Warnings: +Warning 1292 Incorrect datetime value: '-1-01-01' +# +# Try DATE function and DATE (not DATETIME) column: +# +select count(*) from t2 where date(b)< '2017-06-03'; +count(*) +220 +select count(*) from t2 where b < '2017-06-03'; +count(*) +220 +explain format=json select count(*) from t2 where date(b)< '2017-06-03'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.031207004, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["b"], + "key": "b", + "key_length": "4", + "used_key_parts": ["b"], + "loops": 1, + "rows": 216, + "cost": 0.031207004, + "filtered": 100, + "attached_condition": "t2.b < '2017-06-03'", + "using_index": true + } + } + ] + } +} +select count(*) from t2 where date(b)= '2017-06-04'; +count(*) +10 +select count(*) from t2 where b >= '2017-06-04' and b < '2017-06-05'; +count(*) +10 +explain format=json select count(*) from t2 where date(b)= '2017-06-04'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.002723384, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["b"], + "key": "b", + "key_length": "4", + "used_key_parts": ["b"], + "loops": 1, + "rows": 10, + "cost": 0.002723384, + "filtered": 100, + "attached_condition": "t2.b between '2017-06-04' and '2017-06-04'", + "using_index": true + } + } + ] + } +} +# +# Check actual query results +# +insert into t2 values (10001,'2006-12-31 23:59:59','2006-12-31'); +insert into t2 values (10002,'2007-01-01 00:00:00','2007-01-01'); +insert into t2 values (10003,'2007-12-31 23:59:59','2007-12-31'); +insert into t2 values (10004,'2008-01-01 00:00:00','2008-01-01'); +explain format=json +select * from t2 force index(b) where year(b)=2007; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.005042291, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["b"], + "key": "b", + "key_length": "4", + "used_key_parts": ["b"], + "loops": 1, + "rows": 3, + "cost": 0.005042291, + "filtered": 100, + "index_condition": "t2.b between '2007-01-01' and '2007-12-31'" + } + } + ] + } +} +select * from t2 force index(b) where year(b)=2007; +pk a b +10002 2007-01-01 00:00:00 2007-01-01 +10003 2007-12-31 23:59:59 2007-12-31 +insert into t2 values (10010,'2006-12-31 00:00:00','2006-12-31'); +insert into t2 values (10011,'2006-12-30 23:59:59','2006-12-30'); +explain format=json +select * from t2 force index(a) where date(a)='2006-12-31'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.005042291, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 3, + "cost": 0.005042291, + "filtered": 100, + "index_condition": "t2.a between '2006-12-31 00:00:00' and '2006-12-31 23:59:59'" + } + } + ] + } +} +select * from t2 force index(a) where date(a)='2006-12-31'; +pk a b +10010 2006-12-31 00:00:00 2006-12-31 +10001 2006-12-31 23:59:59 2006-12-31 +# +# Test the TIMESTAMP column +# +create table t3 (a timestamp, b date, key(a)); +# Insert data starting from 2016 since that year had a leap second +# (https://en.wikipedia.org/wiki/Leap_second) +set time_zone="UTC"; +insert into t3 +select +timestampadd(hour, B.a, date_add('2016-01-01', interval A.a*8 day)), +date_add('2016-01-01', interval A.a*7 day) +from t1 A, t0 B; +# Results of those two queries must be equal: +select count(*) from t3 force index(a) where year(a)= 2016; +count(*) +460 +# The result must be the same as this query's: +select count(*) from t3 force index(a) where a >= '2016-01-01 00:00:00' + and a <= '2016-12-31 23:59:59.999999'; +count(*) +460 +explain format=json +select count(*) from t3 force index(a) where year(a)= 2016; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.064493934, + "nested_loop": [ + { + "table": { + "table_name": "t3", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "5", + "used_key_parts": ["a"], + "loops": 1, + "rows": 455, + "cost": 0.064493934, + "filtered": 100, + "attached_condition": "t3.a between '2016-01-01 00:00:00' and '2016-12-31 23:59:59'", + "using_index": true + } + } + ] + } +} +set time_zone= @@global.time_zone; +# +# Incorrect const values processing (no rewrite is possible) +# +explain format=json select * from t2 where year(a) = -1; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.1671618, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "loops": 1, + "rows": 1000, + "cost": 0.1671618, + "filtered": 100, + "attached_condition": "year(t2.a) = -1" + } + } + ] + } +} +explain format=json select * from t2 where year(a) > -5; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.1671618, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "loops": 1, + "rows": 1000, + "cost": 0.1671618, + "filtered": 100, + "attached_condition": "year(t2.a) > -5" + } + } + ] + } +} +explain format=json select * from t2 where year(a) < -1; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.1671618, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "loops": 1, + "rows": 1000, + "cost": 0.1671618, + "filtered": 100, + "attached_condition": "year(t2.a) < -1" + } + } + ] + } +} +explain format=json select * from t2 where year(a) <= 10000; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.1671618, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "loops": 1, + "rows": 1000, + "cost": 0.1671618, + "filtered": 100, + "attached_condition": "year(t2.a) <= 10000" + } + } + ] + } +} +explain format=json select * from t2 where year(a) >= 10020; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.1671618, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "loops": 1, + "rows": 1000, + "cost": 0.1671618, + "filtered": 100, + "attached_condition": "year(t2.a) >= 10020" + } + } + ] + } +} +explain format=json select * from t2 where date(a) = '10000-01-01'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.1671618, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "loops": 1, + "rows": 1000, + "cost": 0.1671618, + "filtered": 100, + "attached_condition": "cast(t2.a as date) = '10000-01-01'" + } + } + ] + } +} +Warnings: +Warning 1292 Incorrect datetime value: '10000-01-01' +explain format=json select * from t2 where date(a) < '-1-01-01'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.1671618, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "loops": 1, + "rows": 1000, + "cost": 0.1671618, + "filtered": 100, + "attached_condition": "cast(t2.a as date) < '-1-01-01'" + } + } + ] + } +} +Warnings: +Warning 1292 Incorrect datetime value: '-1-01-01' +# +# Composite indexes +# +create table t4 (a datetime, b int, key(a, b)) ; +insert into t4 values ('2009-11-29 13:43:32', 2); +insert into t4 values ('2009-10-15 12:15:11', 2); +insert into t4 values ('2009-09-01 15:55:00', 3); +insert into t4 values ('2009-08-23 12:07:47', 4); +explain format=json select * from t4 where year(a) = 2009; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.001893764, + "nested_loop": [ + { + "table": { + "table_name": "t4", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 4, + "cost": 0.001893764, + "filtered": 100, + "attached_condition": "t4.a between '2009-01-01 00:00:00' and '2009-12-31 23:59:59'", + "using_index": true + } + } + ] + } +} +explain format=json select * from t4 where year(a) >= 2009; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.001893764, + "nested_loop": [ + { + "table": { + "table_name": "t4", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 4, + "cost": 0.001893764, + "filtered": 100, + "attached_condition": "t4.a >= '2009-01-01 00:00:00'", + "using_index": true + } + } + ] + } +} +explain format=json select * from t4 where year(a) < 2018; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.001893764, + "nested_loop": [ + { + "table": { + "table_name": "t4", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 4, + "cost": 0.001893764, + "filtered": 100, + "attached_condition": "t4.a < '2018-01-01 00:00:00'", + "using_index": true + } + } + ] + } +} +explain format=json select * from t4 where date(a) = '2009-12-01'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.001478954, + "nested_loop": [ + { + "table": { + "table_name": "t4", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 1, + "cost": 0.001478954, + "filtered": 100, + "attached_condition": "t4.a between '2009-12-01 00:00:00' and '2009-12-01 23:59:59'", + "using_index": true + } + } + ] + } +} +explain format=json select * from t4 where b = 2 and year(a) = 2009; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.001893764, + "nested_loop": [ + { + "table": { + "table_name": "t4", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "11", + "used_key_parts": ["a", "b"], + "loops": 1, + "rows": 4, + "cost": 0.001893764, + "filtered": 100, + "attached_condition": "t4.b = 2 and t4.a between '2009-01-01 00:00:00' and '2009-12-31 23:59:59'", + "using_index": true + } + } + ] + } +} +explain format=json select * from t4 where b = 10 and year(a) > 2001; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.001893764, + "nested_loop": [ + { + "table": { + "table_name": "t4", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 4, + "cost": 0.001893764, + "filtered": 100, + "attached_condition": "t4.b = 10 and t4.a > '2001-12-31 23:59:59'", + "using_index": true + } + } + ] + } +} +explain format=json select * from t4 where b = 2 and date(a) = '2009-11-02'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.001478954, + "nested_loop": [ + { + "table": { + "table_name": "t4", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "11", + "used_key_parts": ["a", "b"], + "loops": 1, + "rows": 1, + "cost": 0.001478954, + "filtered": 100, + "attached_condition": "t4.b = 2 and t4.a between '2009-11-02 00:00:00' and '2009-11-02 23:59:59'", + "using_index": true + } + } + ] + } +} +# Reverse order of fields in the index +create table t5 (a datetime, b int, c varchar(20), key(b, a)); +insert into t5 values ('2009-11-29 13:43:32', 2, 'abc'); +insert into t5 values ('2009-10-15 12:15:11', 2, 'def'); +insert into t5 values ('2009-09-01 15:55:00', 3, 'gfd'); +insert into t5 values ('2009-08-23 12:07:47', 4, 'xyz'); +explain format=json select * from t5 where year(a) = 2009; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.01066122, + "nested_loop": [ + { + "table": { + "table_name": "t5", + "access_type": "ALL", + "loops": 1, + "rows": 4, + "cost": 0.01066122, + "filtered": 100, + "attached_condition": "t5.a between <cache>('2009-01-01 00:00:00') and <cache>('2009-12-31 23:59:59')" + } + } + ] + } +} +explain format=json select * from t4 where date(a) = '2009-12-01'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.001478954, + "nested_loop": [ + { + "table": { + "table_name": "t4", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 1, + "cost": 0.001478954, + "filtered": 100, + "attached_condition": "t4.a between '2009-12-01 00:00:00' and '2009-12-01 23:59:59'", + "using_index": true + } + } + ] + } +} +explain format=json select * from t5 where b = 2 and year(a) = 2009; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.002037211, + "nested_loop": [ + { + "table": { + "table_name": "t5", + "access_type": "range", + "possible_keys": ["b"], + "key": "b", + "key_length": "11", + "used_key_parts": ["b", "a"], + "loops": 1, + "rows": 2, + "cost": 0.002037211, + "filtered": 70, + "index_condition": "t5.b = 2 and t5.a between '2009-01-01 00:00:00' and '2009-12-31 23:59:59'" + } + } + ] + } +} +explain format=json select * from t5 where b = 10 and year(a) > 2001; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.002574553, + "nested_loop": [ + { + "table": { + "table_name": "t5", + "access_type": "range", + "possible_keys": ["b"], + "key": "b", + "key_length": "11", + "used_key_parts": ["b", "a"], + "loops": 1, + "rows": 1, + "cost": 0.002574553, + "filtered": 100, + "index_condition": "t5.b = 10 and t5.a > '2001-12-31 23:59:59'" + } + } + ] + } +} +explain format=json select * from t5 where b = 3 and date(a) > '2009-09-01'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.002574553, + "nested_loop": [ + { + "table": { + "table_name": "t5", + "access_type": "range", + "possible_keys": ["b"], + "key": "b", + "key_length": "11", + "used_key_parts": ["b", "a"], + "loops": 1, + "rows": 1, + "cost": 0.002574553, + "filtered": 100, + "index_condition": "t5.b = 3 and t5.a > '2009-09-01 23:59:59'" + } + } + ] + } +} +# +# No rewrite for a non-indexed column +# +create table t6 (a datetime); +insert into t6 values ('2009-11-29 13:43:32'); +insert into t6 values ('2009-10-15 12:15:11'); +insert into t6 values ('2009-09-01 15:55:00'); +insert into t6 values ('2009-08-23 12:07:47'); +explain format=json select * from t6 where year(a) = 2009; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.01066122, + "nested_loop": [ + { + "table": { + "table_name": "t6", + "access_type": "ALL", + "loops": 1, + "rows": 4, + "cost": 0.01066122, + "filtered": 100, + "attached_condition": "year(t6.a) = 2009" + } + } + ] + } +} +explain format=json select * from t6 where date(a) = '2009-12-01'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.01066122, + "nested_loop": [ + { + "table": { + "table_name": "t6", + "access_type": "ALL", + "loops": 1, + "rows": 4, + "cost": 0.01066122, + "filtered": 100, + "attached_condition": "cast(t6.a as date) = '2009-12-01'" + } + } + ] + } +} +drop table t0,t1,t2,t3,t4,t5,t6; +drop view v1; +drop procedure sp; +# +# MDEV-30946 Index usage for DATE(datetime_column) = const +# does not work for DELETE and UPDATE +# +create table t1 (pk int primary key, a datetime, c int, key(a)); +insert into t1 (pk,a,c) values (1,'2009-11-29 13:43:32', 2); +insert into t1 (pk,a,c) values (2,'2009-11-29 03:23:32', 2); +insert into t1 (pk,a,c) values (3,'2009-10-16 05:56:32', 2); +insert into t1 (pk,a,c) values (4,'2010-11-29 13:43:32', 2); +insert into t1 (pk,a,c) values (5,'2010-10-16 05:56:32', 2); +insert into t1 (pk,a,c) values (6,'2011-11-29 13:43:32', 2); +insert into t1 (pk,a,c) values (7,'2012-10-16 05:56:32', 2); +# YEAR() conditions, UPDATE +explain format=json update t1 set c = 0 where year(a) = 2010; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "update": 1, + "table_name": "t1", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "rows": 2, + "attached_condition": "t1.a between '2010-01-01 00:00:00' and '2010-12-31 23:59:59'" + } + } +} +update t1 set c = 0 where year(a) = 2010; +select * from t1; +pk a c +1 2009-11-29 13:43:32 2 +2 2009-11-29 03:23:32 2 +3 2009-10-16 05:56:32 2 +4 2010-11-29 13:43:32 0 +5 2010-10-16 05:56:32 0 +6 2011-11-29 13:43:32 2 +7 2012-10-16 05:56:32 2 +explain format=json update t1 set c = 1 +where c < (select count(*) from t1 where year(a) = 2010); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.011130435, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "loops": 1, + "rows": 7, + "cost": 0.011130435, + "filtered": 100, + "attached_condition": "t1.c < (subquery#2)" + } + } + ], + "subqueries": [ + { + "query_block": { + "select_id": 2, + "cost": 0.001617224, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 2, + "cost": 0.001617224, + "filtered": 100, + "attached_condition": "t1.a between '2010-01-01 00:00:00' and '2010-12-31 23:59:59'", + "using_index": true + } + } + ] + } + } + ] + } +} +explain format=json update t1 set c = 0 +where year(a) = 2010 and c < (select count(*) from t1 where year(a) = 2010); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.003808422, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 2, + "cost": 0.003808422, + "filtered": 100, + "index_condition": "t1.a between '2010-01-01 00:00:00' and '2010-12-31 23:59:59'", + "attached_condition": "t1.c < (subquery#2)" + } + } + ], + "subqueries": [ + { + "query_block": { + "select_id": 2, + "cost": 0.001617224, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 2, + "cost": 0.001617224, + "filtered": 100, + "attached_condition": "t1.a between '2010-01-01 00:00:00' and '2010-12-31 23:59:59'", + "using_index": true + } + } + ] + } + } + ] + } +} +# Multi-table update +create table t2 (a int); +insert into t2 values (4),(5),(6); +explain format=json update t1, t2 set c = 0 +where year(t1.a) = 2010 and t1.c = t2.a; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.014992165, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 2, + "cost": 0.003808422, + "filtered": 100, + "attached_condition": "t1.a between '2010-01-01 00:00:00' and '2010-12-31 23:59:59'" + } + }, + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "loops": 2, + "rows": 3, + "cost": 0.011183743, + "filtered": 100, + "attached_condition": "t2.a = t1.c" + } + } + ] + } +} +prepare stmt from "update t1 set c = 0 where year(a) = 2010"; +execute stmt; +execute stmt; +# YEAR() conditions, DELETE +explain format=json delete from t1 where year(a) = 2010; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "delete": 1, + "table_name": "t1", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "rows": 2, + "attached_condition": "t1.a between '2010-01-01 00:00:00' and '2010-12-31 23:59:59'" + } + } +} +delete from t1 where year(a) = 2010; +select * from t1; +pk a c +1 2009-11-29 13:43:32 2 +2 2009-11-29 03:23:32 2 +3 2009-10-16 05:56:32 2 +6 2011-11-29 13:43:32 2 +7 2012-10-16 05:56:32 2 +explain format=json delete from t1 +where c < (select count(*) from t1 where year(a) = 2010); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.010817625, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "loops": 1, + "rows": 5, + "cost": 0.010817625, + "filtered": 100, + "attached_condition": "t1.c < (subquery#2)" + } + } + ], + "subqueries": [ + { + "query_block": { + "select_id": 2, + "cost": 0.001478954, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "loops": 1, + "rows": 1, + "cost": 0.001478954, + "filtered": 100, + "attached_condition": "t1.a between '2010-01-01 00:00:00' and '2010-12-31 23:59:59'", + "using_index": true + } + } + ] + } + } + ] + } +} +delete from t1 where c < (select count(*) from t1 where year(a) = 2010); +prepare stmt from "delete from t1 where year(a) = 2009"; +execute stmt; +execute stmt; +select * from t1; +pk a c +6 2011-11-29 13:43:32 2 +7 2012-10-16 05:56:32 2 +# DATE() conditions, UPDATE +explain format=json update t1 set c = 0 where date(a) = '2010-10-16'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "update": 1, + "table_name": "t1", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "rows": 1, + "attached_condition": "t1.a between '2010-10-16 00:00:00' and '2010-10-16 23:59:59'" + } + } +} +explain format=json update t1 set c = 0 where date(a) <= '2011-10-16'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "update": 1, + "table_name": "t1", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "rows": 1, + "attached_condition": "t1.a <= '2011-10-16 23:59:59'" + } + } +} +prepare stmt from "update t1 set c = 3 where date(a) = '2011-11-29'"; +execute stmt; +execute stmt; +select * from t1; +pk a c +6 2011-11-29 13:43:32 3 +7 2012-10-16 05:56:32 2 +# DATE() conditions, DELETE +explain format=json delete from t1 where date(a) = '2010-10-16'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "delete": 1, + "table_name": "t1", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "rows": 1, + "attached_condition": "t1.a between '2010-10-16 00:00:00' and '2010-10-16 23:59:59'" + } + } +} +explain format=json delete from t1 where date(a) <= '2011-10-16'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "delete": 1, + "table_name": "t1", + "access_type": "range", + "possible_keys": ["a"], + "key": "a", + "key_length": "6", + "used_key_parts": ["a"], + "rows": 1, + "attached_condition": "t1.a <= '2011-10-16 23:59:59'" + } + } +} +prepare stmt from "delete from t1 where date(a) <= '2012-01-01'"; +execute stmt; +execute stmt; +select * from t1; +pk a c +7 2012-10-16 05:56:32 2 +# Test partition pruning +create table t3 ( +a datetime, +key(a) +) partition by range(year(a)) ( +partition p0 values less than (2022), +partition p1 values less than (MAXVALUE) +); +insert into t3 +select date_add('2020-01-01', interval seq*10 day) +from seq_1_to_100; +# Must be only "p0" partition +explain partitions select * from t3 where year(a) = 2020; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t3 p0 range a a 6 NULL 36 Using where; Using index +explain partitions delete from t3 where year(a) = 2020; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t3 p0 ALL a NULL NULL NULL 73 Using where +explain partitions update t3 set a = a + 1 where year(a) = 2020; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t3 p0 ALL a NULL NULL NULL 73 Using where; Using buffer +drop tables t1,t2,t3; diff --git a/mysql-test/main/sargable_date_cond.test b/mysql-test/main/sargable_date_cond.test new file mode 100644 index 00000000000..e1fa08177d8 --- /dev/null +++ b/mysql-test/main/sargable_date_cond.test @@ -0,0 +1,363 @@ +--source include/have_partition.inc +--source include/have_sequence.inc + +# +# MDEV-8320: Allow index usage for DATE(datetime_column) = const +# + +--disable_warnings +drop table if exists t0,t1,t2,t3; +--enable_warnings + +create table t0(a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +create table t1(a int); +insert into t1 select A.a + B.a* 10 from t0 A, t0 B; + +create table t2 (pk int primary key, a datetime, b date, key(a), key(b)); +insert into t2 +select + A.a*10+B.a, + date_add(date_add('2017-01-01', interval A.a*8 day), interval B.a hour), + date_add('2017-01-01', interval A.a*7 day) +from t1 A, t0 B; + +analyze table t2; + +--echo # +--echo # "YEAR(datetime_col) CMP year_value", basic checks +--echo # +let $q= select count(*) from t2 where year(a) < 2018; +eval $q; +--echo # Compare the results, they must be equal: +select count(*) from t2 where a < '2018-01-01'; +eval explain format=json $q; +--echo # Check rewrite for a prepared statement: +execute immediate + "explain format=json select * from t2 where year(a) < ?" + using 2018; +eval prepare stmt from "$q"; +execute stmt; +execute stmt; +eval create or replace view v1 as $q; +select * from v1; +eval create or replace procedure sp() $q; +call sp(); +call sp(); +--echo # Prepared statement with a placeholder +prepare stmt from "select count(*) from t2 where year(a) < ?"; +execute stmt using 2018; +execute stmt using 2017; + +let $q= select count(*) from t2 where year(a) <= 2018; +eval $q; +select count(*) from t2 where a < '2019-01-01'; +eval explain format=json $q; + +let $q= select count(*) from t2 where year(a) > 2018; +eval $q; +select count(*) from t2 where a > '2018-12-31 23:59:59.999999'; +eval explain format=json $q; + +let $q= select count(*) from t2 where year(a) >= 2018; +eval $q; +select count(*) from t2 where a >= '2018-01-01'; +eval explain format=json $q; + +let $q= select count(*) from t2 where year(a) = 2017; +eval $q; +select count(*) from t2 where a >= '2017-01-01' and a < '2018-01-01'; +eval explain format=json $q; + +--echo # +--echo # "YEAR(datetime_col) CMP year_value", reverse argument order +--echo # +let $q= select count(*) from t2 where 2017 < year(a); +eval $q; +select count(*) from t2 where a >= '2018-01-01'; +eval explain format=json $q; + +let $q= select count(*) from t2 where 2018 <= year(a); +select count(*) from t2 where a >= '2018-01-01'; +eval explain format=json $q; + +let $q= select count(*) from t2 where 2018 > year(a); +eval $q; +select count(*) from t2 where a < '2018-01-01'; +eval explain format=json $q; + +let $q= select count(*) from t2 where 2018 >= year(a); +select count(*) from t2 where a < '2019-01-01'; +eval explain format=json $q; + +let $q= select count(*) from t2 where 2018 = year(a); +eval $q; +select count(*) from t2 where a >= '2018-01-01' and a < '2019-01-01'; +eval explain format=json $q; + +--echo # +--echo # "DATE(datetime_col) CMP date_value", basic checks +--echo # +let $q= select count(*) from t2 where date(a) < '2017-06-01'; +eval $q; +select count(*) from t2 where a < '2017-06-01'; +eval explain format=json $q; + +let $q= select count(*) from t2 where date(a) <= '2017-06-03'; +eval $q; +select count(*) from t2 where a < '2017-06-04'; +eval explain format=json $q; + +let $q= select count(*) from t2 where date(a) > '2018-06-01'; +eval $q; +select count(*) from t2 where a >= '2018-06-02'; +eval explain format=json $q; + +let $q= select count(*) from t2 where date(a) >= '2018-06-01'; +eval $q; +select count(*) from t2 where a >= '2018-06-01'; +eval explain format=json $q; + +let $q= select count(*) from t2 where date(a) = '2017-06-02'; +eval $q; +select count(*) from t2 where a >= '2017-06-02' and a < '2017-06-03'; +eval explain format=json $q; + +--echo # +--echo # "DATE(datetime_col) CMP date_value", reverse order +--echo # +let $q= select count(*) from t2 where '2017-06-01' > date(a); +eval $q; +select count(*) from t2 where '2017-06-01' > a; +eval explain format=json $q; + +let $q= select count(*) from t2 where '2017-06-03' >= date(a); +eval $q; +select count(*) from t2 where '2017-06-03' >= a; +eval explain format=json $q; + +let $q= select count(*) from t2 where '2018-06-01' < date(a); +eval $q; +select count(*) from t2 where '2018-06-02' <= a; +eval explain format=json $q; + +let $q= select count(*) from t2 where '2018-06-01' <= date(a); +eval $q; +select count(*) from t2 where '2018-06-01' <= a; +eval explain format=json $q; + +let $q= select count(*) from t2 where '2017-06-02' = date(a); +eval $q; +select count(*) from t2 where a >= '2017-06-02' and a < '2017-06-03'; +eval explain format=json $q; + +--echo # Check rewrite of a more complicated query +explain format=json select * from t2 as t21 force index(a), + t2 as t22 force index(a) + where year(t21.a) < 2018 and t21.b > '2017-11-01' + and date(t22.a) >= '2017-02-01' and t22.b > '2017-11-01'; + +--echo # +--echo # Incorrect const values processing (no rewrite is possible) +--echo # +explain format=json select * from t2 where year(a) = -1; +explain format=json select * from t2 where year(a) > -5; +explain format=json select * from t2 where year(a) < -1; +explain format=json select * from t2 where year(a) <= 10000; +explain format=json select * from t2 where year(a) >= 10020; +explain format=json select * from t2 where date(a) = '10000-01-01'; +explain format=json select * from t2 where date(a) < '-1-01-01'; + +--echo # +--echo # Try DATE function and DATE (not DATETIME) column: +--echo # +let $q= select count(*) from t2 where date(b)< '2017-06-03'; +eval $q; +select count(*) from t2 where b < '2017-06-03'; +eval explain format=json $q; + +let $q= select count(*) from t2 where date(b)= '2017-06-04'; +eval $q; +select count(*) from t2 where b >= '2017-06-04' and b < '2017-06-05'; +eval explain format=json $q; + +--echo # +--echo # Check actual query results +--echo # +insert into t2 values (10001,'2006-12-31 23:59:59','2006-12-31'); +insert into t2 values (10002,'2007-01-01 00:00:00','2007-01-01'); +insert into t2 values (10003,'2007-12-31 23:59:59','2007-12-31'); +insert into t2 values (10004,'2008-01-01 00:00:00','2008-01-01'); + +explain format=json +select * from t2 force index(b) where year(b)=2007; +select * from t2 force index(b) where year(b)=2007; + +insert into t2 values (10010,'2006-12-31 00:00:00','2006-12-31'); +insert into t2 values (10011,'2006-12-30 23:59:59','2006-12-30'); + +explain format=json +select * from t2 force index(a) where date(a)='2006-12-31'; +select * from t2 force index(a) where date(a)='2006-12-31'; + +--echo # +--echo # Test the TIMESTAMP column +--echo # +create table t3 (a timestamp, b date, key(a)); +--echo # Insert data starting from 2016 since that year had a leap second +--echo # (https://en.wikipedia.org/wiki/Leap_second) +set time_zone="UTC"; # To make sure we avoid daylight saving time shifts +insert into t3 + select + timestampadd(hour, B.a, date_add('2016-01-01', interval A.a*8 day)), + date_add('2016-01-01', interval A.a*7 day) + from t1 A, t0 B; + +--echo # Results of those two queries must be equal: +let $q= select count(*) from t3 force index(a) where year(a)= 2016; +eval $q; +--echo # The result must be the same as this query's: +select count(*) from t3 force index(a) where a >= '2016-01-01 00:00:00' + and a <= '2016-12-31 23:59:59.999999'; +explain format=json + select count(*) from t3 force index(a) where year(a)= 2016; +set time_zone= @@global.time_zone; + +--echo # +--echo # Incorrect const values processing (no rewrite is possible) +--echo # +explain format=json select * from t2 where year(a) = -1; +explain format=json select * from t2 where year(a) > -5; +explain format=json select * from t2 where year(a) < -1; +explain format=json select * from t2 where year(a) <= 10000; +explain format=json select * from t2 where year(a) >= 10020; +explain format=json select * from t2 where date(a) = '10000-01-01'; +explain format=json select * from t2 where date(a) < '-1-01-01'; + +--echo # +--echo # Composite indexes +--echo # +create table t4 (a datetime, b int, key(a, b)) ; +insert into t4 values ('2009-11-29 13:43:32', 2); +insert into t4 values ('2009-10-15 12:15:11', 2); +insert into t4 values ('2009-09-01 15:55:00', 3); +insert into t4 values ('2009-08-23 12:07:47', 4); +explain format=json select * from t4 where year(a) = 2009; +explain format=json select * from t4 where year(a) >= 2009; +explain format=json select * from t4 where year(a) < 2018; +explain format=json select * from t4 where date(a) = '2009-12-01'; +explain format=json select * from t4 where b = 2 and year(a) = 2009; +explain format=json select * from t4 where b = 10 and year(a) > 2001; +explain format=json select * from t4 where b = 2 and date(a) = '2009-11-02'; + +--echo # Reverse order of fields in the index +create table t5 (a datetime, b int, c varchar(20), key(b, a)); +insert into t5 values ('2009-11-29 13:43:32', 2, 'abc'); +insert into t5 values ('2009-10-15 12:15:11', 2, 'def'); +insert into t5 values ('2009-09-01 15:55:00', 3, 'gfd'); +insert into t5 values ('2009-08-23 12:07:47', 4, 'xyz'); +explain format=json select * from t5 where year(a) = 2009; +explain format=json select * from t4 where date(a) = '2009-12-01'; +explain format=json select * from t5 where b = 2 and year(a) = 2009; +explain format=json select * from t5 where b = 10 and year(a) > 2001; +explain format=json select * from t5 where b = 3 and date(a) > '2009-09-01'; + +--echo # +--echo # No rewrite for a non-indexed column +--echo # +create table t6 (a datetime); +insert into t6 values ('2009-11-29 13:43:32'); +insert into t6 values ('2009-10-15 12:15:11'); +insert into t6 values ('2009-09-01 15:55:00'); +insert into t6 values ('2009-08-23 12:07:47'); +explain format=json select * from t6 where year(a) = 2009; +explain format=json select * from t6 where date(a) = '2009-12-01'; + +drop table t0,t1,t2,t3,t4,t5,t6; +drop view v1; +drop procedure sp; + +--echo # +--echo # MDEV-30946 Index usage for DATE(datetime_column) = const +--echo # does not work for DELETE and UPDATE +--echo # +create table t1 (pk int primary key, a datetime, c int, key(a)); + +insert into t1 (pk,a,c) values (1,'2009-11-29 13:43:32', 2); +insert into t1 (pk,a,c) values (2,'2009-11-29 03:23:32', 2); +insert into t1 (pk,a,c) values (3,'2009-10-16 05:56:32', 2); +insert into t1 (pk,a,c) values (4,'2010-11-29 13:43:32', 2); +insert into t1 (pk,a,c) values (5,'2010-10-16 05:56:32', 2); +insert into t1 (pk,a,c) values (6,'2011-11-29 13:43:32', 2); +insert into t1 (pk,a,c) values (7,'2012-10-16 05:56:32', 2); + +--echo # YEAR() conditions, UPDATE +explain format=json update t1 set c = 0 where year(a) = 2010; +update t1 set c = 0 where year(a) = 2010; +select * from t1; +explain format=json update t1 set c = 1 + where c < (select count(*) from t1 where year(a) = 2010); +explain format=json update t1 set c = 0 + where year(a) = 2010 and c < (select count(*) from t1 where year(a) = 2010); + +--echo # Multi-table update +create table t2 (a int); +insert into t2 values (4),(5),(6); +explain format=json update t1, t2 set c = 0 + where year(t1.a) = 2010 and t1.c = t2.a; + +prepare stmt from "update t1 set c = 0 where year(a) = 2010"; +execute stmt; +execute stmt; + +--echo # YEAR() conditions, DELETE +explain format=json delete from t1 where year(a) = 2010; +delete from t1 where year(a) = 2010; +select * from t1; +explain format=json delete from t1 + where c < (select count(*) from t1 where year(a) = 2010); +delete from t1 where c < (select count(*) from t1 where year(a) = 2010); + +prepare stmt from "delete from t1 where year(a) = 2009"; +execute stmt; +execute stmt; +select * from t1; + +--echo # DATE() conditions, UPDATE +explain format=json update t1 set c = 0 where date(a) = '2010-10-16'; +explain format=json update t1 set c = 0 where date(a) <= '2011-10-16'; +prepare stmt from "update t1 set c = 3 where date(a) = '2011-11-29'"; +execute stmt; +execute stmt; +select * from t1; + +--echo # DATE() conditions, DELETE +explain format=json delete from t1 where date(a) = '2010-10-16'; +explain format=json delete from t1 where date(a) <= '2011-10-16'; +prepare stmt from "delete from t1 where date(a) <= '2012-01-01'"; +execute stmt; +execute stmt; +select * from t1; + +--echo # Test partition pruning +create table t3 ( + a datetime, + key(a) +) partition by range(year(a)) ( +partition p0 values less than (2022), +partition p1 values less than (MAXVALUE) +); + +insert into t3 +select date_add('2020-01-01', interval seq*10 day) +from seq_1_to_100; + +--echo # Must be only "p0" partition +explain partitions select * from t3 where year(a) = 2020; + +explain partitions delete from t3 where year(a) = 2020; + +explain partitions update t3 set a = a + 1 where year(a) = 2020; + +drop tables t1,t2,t3; diff --git a/mysql-test/main/set_statement.result b/mysql-test/main/set_statement.result index f0a362e9fe2..a1b1d3659ff 100644 --- a/mysql-test/main/set_statement.result +++ b/mysql-test/main/set_statement.result @@ -1215,8 +1215,6 @@ set @@long_query_time= @save_long_query_time; truncate table mysql.slow_log; set statement autocommit=default for select 1; ERROR 42000: The system variable autocommit cannot be set in SET STATEMENT. -set statement tx_isolation=default for select 1; -ERROR 42000: The system variable tx_isolation cannot be set in SET STATEMENT. set statement skip_replication=default for select 1; ERROR 42000: The system variable skip_replication cannot be set in SET STATEMENT. set statement sql_log_off=default for select 1; diff --git a/mysql-test/main/set_statement.test b/mysql-test/main/set_statement.test index cc191a014a1..029310cdc7c 100644 --- a/mysql-test/main/set_statement.test +++ b/mysql-test/main/set_statement.test @@ -1063,8 +1063,6 @@ truncate table mysql.slow_log; --error ER_SET_STATEMENT_NOT_SUPPORTED set statement autocommit=default for select 1; --error ER_SET_STATEMENT_NOT_SUPPORTED -set statement tx_isolation=default for select 1; ---error ER_SET_STATEMENT_NOT_SUPPORTED set statement skip_replication=default for select 1; --error ER_SET_STATEMENT_NOT_SUPPORTED set statement sql_log_off=default for select 1; diff --git a/mysql-test/main/skip_grants.result b/mysql-test/main/skip_grants.result index fdd7be41095..292358fad4c 100644 --- a/mysql-test/main/skip_grants.result +++ b/mysql-test/main/skip_grants.result @@ -1,3 +1,4 @@ +call mtr.add_suppression("Event Scheduler will not function when starting with --skip-grant-tables or --bootstrap."); use test; CREATE TABLE t1(c INT); CREATE TRIGGER t1_bi BEFORE INSERT ON t1 @@ -52,7 +53,7 @@ DROP FUNCTION f3; # Bug #26807 "set global event_scheduler=1" and --skip-grant-tables crashes server # set global event_scheduler=1; -set global event_scheduler=0; +ERROR HY000: The MariaDB server is running with the --event-scheduler=DISABLED or --skip-grant-tables option so it cannot execute this statement # # Bug#26285 Selecting information_schema crahes server # diff --git a/mysql-test/main/skip_grants.test b/mysql-test/main/skip_grants.test index b74cd41b039..db2d24bc760 100644 --- a/mysql-test/main/skip_grants.test +++ b/mysql-test/main/skip_grants.test @@ -1,5 +1,7 @@ # This tests not performed with embedded server -- source include/not_embedded.inc +call mtr.add_suppression("Event Scheduler will not function when starting with --skip-grant-tables or --bootstrap."); + -- disable_ps_protocol use test; @@ -92,10 +94,8 @@ DROP FUNCTION f3; --echo # --echo # Bug #26807 "set global event_scheduler=1" and --skip-grant-tables crashes server --echo # ---disable_warnings +--error ER_OPTION_PREVENTS_STATEMENT set global event_scheduler=1; ---enable_warnings -set global event_scheduler=0; --echo # --echo # Bug#26285 Selecting information_schema crahes server diff --git a/mysql-test/main/subselect.result b/mysql-test/main/subselect.result index 0467415f40e..6e0c956b77e 100644 --- a/mysql-test/main/subselect.result +++ b/mysql-test/main/subselect.result @@ -660,7 +660,18 @@ a b 22 11 2 12 delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t12 where t11.a = t12.a); -ERROR HY000: Table 't12' is specified twice, both as a target for 'DELETE' and as a separate source for data +select * from t11; +a b +0 10 +1 11 +select * from t12; +a b +33 10 +22 11 +delete from t11; +delete from t12; +insert into t11 values (0, 10),(1, 11),(2, 12); +insert into t12 values (33, 10),(22, 11),(2, 12); delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2); ERROR 21000: Subquery returns more than 1 row delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2 where t11.a = t2.a); diff --git a/mysql-test/main/subselect.test b/mysql-test/main/subselect.test index 67499911d5c..089eb10b6f0 100644 --- a/mysql-test/main/subselect.test +++ b/mysql-test/main/subselect.test @@ -399,8 +399,13 @@ insert into t12 values (33, 10),(22, 11),(2, 12); insert into t2 values (1, 21),(2, 12),(3, 23); select * from t11; select * from t12; --- error ER_UPDATE_TABLE_USED delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t12 where t11.a = t12.a); +select * from t11; +select * from t12; +delete from t11; +delete from t12; +insert into t11 values (0, 10),(1, 11),(2, 12); +insert into t12 values (33, 10),(22, 11),(2, 12); -- error ER_SUBQUERY_NO_1_ROW delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2); delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2 where t11.a = t2.a); diff --git a/mysql-test/main/subselect_no_exists_to_in.result b/mysql-test/main/subselect_no_exists_to_in.result index 352e7ba2ccb..3750c96871b 100644 --- a/mysql-test/main/subselect_no_exists_to_in.result +++ b/mysql-test/main/subselect_no_exists_to_in.result @@ -664,7 +664,18 @@ a b 22 11 2 12 delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t12 where t11.a = t12.a); -ERROR HY000: Table 't12' is specified twice, both as a target for 'DELETE' and as a separate source for data +select * from t11; +a b +0 10 +1 11 +select * from t12; +a b +33 10 +22 11 +delete from t11; +delete from t12; +insert into t11 values (0, 10),(1, 11),(2, 12); +insert into t12 values (33, 10),(22, 11),(2, 12); delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2); ERROR 21000: Subquery returns more than 1 row delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2 where t11.a = t2.a); diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result index b60f0fe238b..f837e20be8b 100644 --- a/mysql-test/main/subselect_no_mat.result +++ b/mysql-test/main/subselect_no_mat.result @@ -667,7 +667,18 @@ a b 22 11 2 12 delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t12 where t11.a = t12.a); -ERROR HY000: Table 't12' is specified twice, both as a target for 'DELETE' and as a separate source for data +select * from t11; +a b +0 10 +1 11 +select * from t12; +a b +33 10 +22 11 +delete from t11; +delete from t12; +insert into t11 values (0, 10),(1, 11),(2, 12); +insert into t12 values (33, 10),(22, 11),(2, 12); delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2); ERROR 21000: Subquery returns more than 1 row delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2 where t11.a = t2.a); diff --git a/mysql-test/main/subselect_no_opts.result b/mysql-test/main/subselect_no_opts.result index eefbfcae986..e2352090797 100644 --- a/mysql-test/main/subselect_no_opts.result +++ b/mysql-test/main/subselect_no_opts.result @@ -663,7 +663,18 @@ a b 22 11 2 12 delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t12 where t11.a = t12.a); -ERROR HY000: Table 't12' is specified twice, both as a target for 'DELETE' and as a separate source for data +select * from t11; +a b +0 10 +1 11 +select * from t12; +a b +33 10 +22 11 +delete from t11; +delete from t12; +insert into t11 values (0, 10),(1, 11),(2, 12); +insert into t12 values (33, 10),(22, 11),(2, 12); delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2); ERROR 21000: Subquery returns more than 1 row delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2 where t11.a = t2.a); diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result index 9c75f4f2655..0e5216eb120 100644 --- a/mysql-test/main/subselect_no_scache.result +++ b/mysql-test/main/subselect_no_scache.result @@ -666,7 +666,18 @@ a b 22 11 2 12 delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t12 where t11.a = t12.a); -ERROR HY000: Table 't12' is specified twice, both as a target for 'DELETE' and as a separate source for data +select * from t11; +a b +0 10 +1 11 +select * from t12; +a b +33 10 +22 11 +delete from t11; +delete from t12; +insert into t11 values (0, 10),(1, 11),(2, 12); +insert into t12 values (33, 10),(22, 11),(2, 12); delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2); ERROR 21000: Subquery returns more than 1 row delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2 where t11.a = t2.a); diff --git a/mysql-test/main/subselect_no_semijoin.result b/mysql-test/main/subselect_no_semijoin.result index 0766bd9b4f3..c7acdc2990c 100644 --- a/mysql-test/main/subselect_no_semijoin.result +++ b/mysql-test/main/subselect_no_semijoin.result @@ -663,7 +663,18 @@ a b 22 11 2 12 delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t12 where t11.a = t12.a); -ERROR HY000: Table 't12' is specified twice, both as a target for 'DELETE' and as a separate source for data +select * from t11; +a b +0 10 +1 11 +select * from t12; +a b +33 10 +22 11 +delete from t11; +delete from t12; +insert into t11 values (0, 10),(1, 11),(2, 12); +insert into t12 values (33, 10),(22, 11),(2, 12); delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2); ERROR 21000: Subquery returns more than 1 row delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2 where t11.a = t2.a); diff --git a/mysql-test/main/trans_read_only.result b/mysql-test/main/trans_read_only.result index 5e86b0993cd..acced0a059f 100644 --- a/mysql-test/main/trans_read_only.result +++ b/mysql-test/main/trans_read_only.result @@ -4,22 +4,22 @@ # # Test9: The --transaction-read-only startup option. # Check that the option was set by the .opt file. -SELECT @@tx_read_only; -@@tx_read_only +SELECT @@transaction_read_only; +@@transaction_read_only 1 # Also for new connections. connect con1, localhost, root; -SELECT @@tx_read_only; -@@tx_read_only +SELECT @@transaction_read_only; +@@transaction_read_only 1 SET SESSION TRANSACTION READ WRITE; -SELECT @@tx_read_only; -@@tx_read_only +SELECT @@transaction_read_only; +@@transaction_read_only 0 disconnect con1; connection default; -SELECT @@tx_read_only; -@@tx_read_only +SELECT @@transaction_read_only; +@@transaction_read_only 1 # # Test 10: SET TRANSACTION / START TRANSACTION + implicit commit. diff --git a/mysql-test/main/trans_read_only.test b/mysql-test/main/trans_read_only.test index 38b2a833216..d8c2f20b6a9 100644 --- a/mysql-test/main/trans_read_only.test +++ b/mysql-test/main/trans_read_only.test @@ -8,18 +8,18 @@ --echo # Test9: The --transaction-read-only startup option. --echo # Check that the option was set by the .opt file. -SELECT @@tx_read_only; +SELECT @@transaction_read_only; --echo # Also for new connections. connect (con1, localhost, root); -SELECT @@tx_read_only; +SELECT @@transaction_read_only; SET SESSION TRANSACTION READ WRITE; -SELECT @@tx_read_only; +SELECT @@transaction_read_only; disconnect con1; --source include/wait_until_disconnected.inc connection default; -SELECT @@tx_read_only; +SELECT @@transaction_read_only; --echo # diff --git a/mysql-test/main/unsafe_binlog_innodb.result b/mysql-test/main/unsafe_binlog_innodb.result index ced29926400..19956cfc84d 100644 --- a/mysql-test/main/unsafe_binlog_innodb.result +++ b/mysql-test/main/unsafe_binlog_innodb.result @@ -1,6 +1,6 @@ SET @save_timeout = @@GLOBAL.innodb_lock_wait_timeout; SET GLOBAL innodb_lock_wait_timeout = 1; -SET @save_isolation = @@GLOBAL.tx_isolation; +SET @save_isolation = @@GLOBAL.transaction_isolation; SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10; create table t1 (id int not null, f_id int not null, f int not null, @@ -192,4 +192,4 @@ disconnect i; disconnect j; drop table t1, t2, t3, t5, t6, t8, t9; SET GLOBAL innodb_lock_wait_timeout = @save_timeout; -SET GLOBAL tx_isolation = @save_isolation; +SET GLOBAL transaction_isolation = @save_isolation; diff --git a/mysql-test/main/unsafe_binlog_innodb.test b/mysql-test/main/unsafe_binlog_innodb.test index abd2c58de30..0f57c60cd61 100644 --- a/mysql-test/main/unsafe_binlog_innodb.test +++ b/mysql-test/main/unsafe_binlog_innodb.test @@ -15,10 +15,10 @@ let $engine_type= InnoDB; SET @save_timeout = @@GLOBAL.innodb_lock_wait_timeout; SET GLOBAL innodb_lock_wait_timeout = 1; -SET @save_isolation = @@GLOBAL.tx_isolation; +SET @save_isolation = @@GLOBAL.transaction_isolation; SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; --source include/unsafe_binlog.inc SET GLOBAL innodb_lock_wait_timeout = @save_timeout; -SET GLOBAL tx_isolation = @save_isolation; +SET GLOBAL transaction_isolation = @save_isolation; diff --git a/mysql-test/main/update.result b/mysql-test/main/update.result index b9b80fb48de..8dda69e4e78 100644 --- a/mysql-test/main/update.result +++ b/mysql-test/main/update.result @@ -399,7 +399,7 @@ update t1 set `*f2`=1; drop table t1; create table t1(f1 int); update t1 set f2=1 order by f2; -ERROR 42S22: Unknown column 'f2' in 'order clause' +ERROR 42S22: Unknown column 'f2' in 'field list' drop table t1; CREATE TABLE t1 ( request_id int unsigned NOT NULL auto_increment, @@ -763,3 +763,41 @@ ccc yyy u xxb drop table t1; # End of MariaDB 10.4 tests +# +# MDEV-29189: Second execution of SF using UPDATE?DELETE +# after reported error by the first execution +# +CREATE TABLE t1 (c int); +CREATE FUNCTION f1() RETURNS int +BEGIN +UPDATE t1 SET c=c+1; +RETURN 1; +END;// +CREATE FUNCTION f2() RETURNS int +BEGIN +DELETE FROM t1 WHERE c < 7; +RETURN 1; +END;// +INSERT INTO t1 VALUES (3), (7), (1); +SELECT * FROM t1 WHERE f1() = 1; +ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger +SELECT f1(); +f1() +1 +SELECT * FROM t1; +c +4 +8 +2 +SELECT * FROM t1 WHERE f2() = 1; +ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger +SELECT f2(); +f2() +1 +SELECT * FROM t1; +c +8 +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP TABLE t1; +# End of MariaDB 10.10 tests diff --git a/mysql-test/main/update.test b/mysql-test/main/update.test index 147d69d50c9..c10c1b82a50 100644 --- a/mysql-test/main/update.test +++ b/mysql-test/main/update.test @@ -699,3 +699,41 @@ select * from t1; drop table t1; --echo # End of MariaDB 10.4 tests + +--echo # +--echo # MDEV-29189: Second execution of SF using UPDATE?DELETE +--echo # after reported error by the first execution +--echo # + +CREATE TABLE t1 (c int); + +DELIMITER //; +CREATE FUNCTION f1() RETURNS int +BEGIN + UPDATE t1 SET c=c+1; + RETURN 1; +END;// +CREATE FUNCTION f2() RETURNS int +BEGIN + DELETE FROM t1 WHERE c < 7; + RETURN 1; +END;// +DELIMITER ;// + +INSERT INTO t1 VALUES (3), (7), (1); + +--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG +SELECT * FROM t1 WHERE f1() = 1; +SELECT f1(); +SELECT * FROM t1; + +--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG +SELECT * FROM t1 WHERE f2() = 1; +SELECT f2(); +SELECT * FROM t1; + +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP TABLE t1; + +--echo # End of MariaDB 10.10 tests diff --git a/mysql-test/main/update_single_to_multi.result b/mysql-test/main/update_single_to_multi.result new file mode 100644 index 00000000000..679237837cc --- /dev/null +++ b/mysql-test/main/update_single_to_multi.result @@ -0,0 +1,3860 @@ +DROP DATABASE IF EXISTS dbt3_s001; +CREATE DATABASE dbt3_s001; +use dbt3_s001; +create index i_n_name on nation(n_name); +analyze table +nation, lineitem, customer, orders, part, supplier, partsupp, region +persistent for all; +Table Op Msg_type Msg_text +dbt3_s001.nation analyze status Engine-independent statistics collected +dbt3_s001.nation analyze status OK +dbt3_s001.lineitem analyze status Engine-independent statistics collected +dbt3_s001.lineitem analyze status OK +dbt3_s001.customer analyze status Engine-independent statistics collected +dbt3_s001.customer analyze status OK +dbt3_s001.orders analyze status Engine-independent statistics collected +dbt3_s001.orders analyze status OK +dbt3_s001.part analyze status Engine-independent statistics collected +dbt3_s001.part analyze status OK +dbt3_s001.supplier analyze status Engine-independent statistics collected +dbt3_s001.supplier analyze status OK +dbt3_s001.partsupp analyze status Engine-independent statistics collected +dbt3_s001.partsupp analyze status OK +dbt3_s001.region analyze status Engine-independent statistics collected +dbt3_s001.region analyze status OK +# Pullout +# ======= +explain +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (7%) Using where; Using rowid filter +explain format=json +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.052271677, + "nested_loop": [ + { + "table": { + "table_name": "nation", + "access_type": "ref", + "possible_keys": ["PRIMARY", "i_n_name"], + "key": "i_n_name", + "key_length": "26", + "used_key_parts": ["n_name"], + "ref": ["const"], + "loops": 1, + "rows": 1, + "cost": 0.002024411, + "filtered": 100, + "index_condition": "nation.n_name = 'PERU'" + } + }, + { + "table": { + "table_name": "customer", + "access_type": "ref", + "possible_keys": ["PRIMARY", "i_c_nationkey"], + "key": "i_c_nationkey", + "key_length": "5", + "used_key_parts": ["c_nationkey"], + "ref": ["dbt3_s001.nation.n_nationkey"], + "loops": 1, + "rows": 6, + "cost": 0.008193756, + "filtered": 100 + } + }, + { + "table": { + "table_name": "orders", + "access_type": "ref", + "possible_keys": ["i_o_orderdate", "i_o_custkey"], + "key": "i_o_custkey", + "key_length": "5", + "used_key_parts": ["o_custkey"], + "ref": ["dbt3_s001.customer.c_custkey"], + "rowid_filter": { + "range": { + "key": "i_o_orderdate", + "used_key_parts": ["o_orderDATE"] + }, + "rows": 108, + "selectivity_pct": 7.2 + }, + "loops": 6, + "rows": 15, + "cost": 0.04205351, + "filtered": 7.199999809, + "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'" + } + } + ] + } +} +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +644 201268.06 +2880 145761.99 +3142 16030.15 +5382 138423.03 +5095 184583.99 +737 12984.85 +1729 12137.76 +5121 150334.57 +explain +update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (7%) Using where; Using rowid filter +explain format=json +update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.052271677, + "nested_loop": [ + { + "table": { + "table_name": "nation", + "access_type": "ref", + "possible_keys": ["PRIMARY", "i_n_name"], + "key": "i_n_name", + "key_length": "26", + "used_key_parts": ["n_name"], + "ref": ["const"], + "loops": 1, + "rows": 1, + "cost": 0.002024411, + "filtered": 100, + "index_condition": "nation.n_name = 'PERU'" + } + }, + { + "table": { + "table_name": "customer", + "access_type": "ref", + "possible_keys": ["PRIMARY", "i_c_nationkey"], + "key": "i_c_nationkey", + "key_length": "5", + "used_key_parts": ["c_nationkey"], + "ref": ["dbt3_s001.nation.n_nationkey"], + "loops": 1, + "rows": 6, + "cost": 0.008193756, + "filtered": 100 + } + }, + { + "table": { + "table_name": "orders", + "access_type": "ref", + "possible_keys": ["i_o_orderdate", "i_o_custkey"], + "key": "i_o_custkey", + "key_length": "5", + "used_key_parts": ["o_custkey"], + "ref": ["dbt3_s001.customer.c_custkey"], + "rowid_filter": { + "range": { + "key": "i_o_orderdate", + "used_key_parts": ["o_orderDATE"] + }, + "rows": 108, + "selectivity_pct": 7.2 + }, + "loops": 6, + "rows": 15, + "cost": 0.04205351, + "filtered": 7.199999809, + "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'" + } + } + ] + } +} +update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +644 201218.06 +2880 145711.99 +3142 15980.15 +5382 138373.03 +5095 184533.99 +737 12934.85 +1729 12087.76 +5121 150284.57 +update orders set o_totalprice= o_totalprice+50 where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +644 201268.06 +2880 145761.99 +3142 16030.15 +5382 138423.03 +5095 184583.99 +737 12984.85 +1729 12137.76 +5121 150334.57 +explain +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 910 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 +1 PRIMARY part ALL PRIMARY NULL NULL NULL 200 Using where; Using join buffer (flat, BNL join) +1 PRIMARY partsupp eq_ref PRIMARY,i_ps_partkey,i_ps_suppkey PRIMARY 8 dbt3_s001.part.p_partkey,dbt3_s001.supplier.s_suppkey 1 +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 910 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +ps_partkey ps_suppkey ps_supplycost +1 8 357.84 +3 8 645.4 +4 1 444.37 +5 8 50.52 +6 1 642.13 +7 8 763.98 +8 1 957.34 +explain +update partsupp set ps_supplycost = ps_supplycost+2 where (ps_partkey, ps_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 910 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 +1 PRIMARY part ALL PRIMARY NULL NULL NULL 200 Using where +1 PRIMARY partsupp eq_ref PRIMARY,i_ps_partkey,i_ps_suppkey PRIMARY 8 dbt3_s001.part.p_partkey,dbt3_s001.supplier.s_suppkey 1 +update partsupp set ps_supplycost = ps_supplycost+2 where (ps_partkey, ps_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 910 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 910 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +ps_partkey ps_suppkey ps_supplycost +1 8 359.84 +3 8 647.4 +4 1 446.37 +5 8 52.52 +6 1 644.13 +7 8 765.98 +8 1 959.34 +update partsupp set ps_supplycost = ps_supplycost-2 where (ps_partkey, ps_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 910 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 910 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +ps_partkey ps_suppkey ps_supplycost +1 8 357.84 +3 8 645.4 +4 1 444.37 +5 8 50.52 +6 1 642.13 +7 8 763.98 +8 1 957.34 +explain +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part +where p_retailprice between 901 and 910) and +ps_suppkey in (select s_suppkey from supplier +where s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 +1 PRIMARY part ALL PRIMARY NULL NULL NULL 200 Using where; Using join buffer (flat, BNL join) +1 PRIMARY partsupp eq_ref PRIMARY,i_ps_partkey,i_ps_suppkey PRIMARY 8 dbt3_s001.part.p_partkey,dbt3_s001.supplier.s_suppkey 1 +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part +where p_retailprice between 901 and 910) and +ps_suppkey in (select s_suppkey from supplier +where s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +ps_partkey ps_suppkey ps_supplycost +1 8 357.84 +3 8 645.4 +4 1 444.37 +5 8 50.52 +6 1 642.13 +7 8 763.98 +8 1 957.34 +explain +update partsupp set ps_supplycost = ps_supplycost+10 where ps_partkey in (select p_partkey from part +where p_retailprice between 901 and 910) and +ps_suppkey in (select s_suppkey from supplier +where s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 +1 PRIMARY part ALL PRIMARY NULL NULL NULL 200 Using where +1 PRIMARY partsupp eq_ref PRIMARY,i_ps_partkey,i_ps_suppkey PRIMARY 8 dbt3_s001.part.p_partkey,dbt3_s001.supplier.s_suppkey 1 +update partsupp set ps_supplycost = ps_supplycost+10 where ps_partkey in (select p_partkey from part +where p_retailprice between 901 and 910) and +ps_suppkey in (select s_suppkey from supplier +where s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part +where p_retailprice between 901 and 910) and +ps_suppkey in (select s_suppkey from supplier +where s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +ps_partkey ps_suppkey ps_supplycost +1 8 367.84 +3 8 655.4 +4 1 454.37 +5 8 60.52 +6 1 652.13 +7 8 773.98 +8 1 967.34 +update partsupp set ps_supplycost = ps_supplycost-10 where ps_partkey in (select p_partkey from part +where p_retailprice between 901 and 910) and +ps_suppkey in (select s_suppkey from supplier +where s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part +where p_retailprice between 901 and 910) and +ps_suppkey in (select s_suppkey from supplier +where s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +ps_partkey ps_suppkey ps_supplycost +1 8 357.84 +3 8 645.4 +4 1 444.37 +5 8 50.52 +6 1 642.13 +7 8 763.98 +8 1 957.34 +explain +select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders +where o_custkey in +(select c_custkey from customer +where c_nationkey in +(select n_nationkey from nation +where n_name='PERU')) +and +o_orderDATE between '1992-06-30' and '1992-12-31') +and +(l_partkey, l_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 1000 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY orders ref|filter PRIMARY,i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (7%) Using where; Using rowid filter +1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 dbt3_s001.orders.o_orderkey 4 Using where +1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where +select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders +where o_custkey in +(select c_custkey from customer +where c_nationkey in +(select n_nationkey from nation +where n_name='PERU')) +and +o_orderDATE between '1992-06-30' and '1992-12-31') +and +(l_partkey, l_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 1000 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +l_orderkey l_linenumber l_tax +4996 1 0.01 +933 1 0.04 +2500 2 0.02 +2500 4 0.02 +explain +update lineitem set l_tax = (l_tax*100+1)/100 where l_orderkey in (select o_orderkey from orders +where o_custkey in +(select c_custkey from customer +where c_nationkey in +(select n_nationkey from nation +where n_name='PERU')) +and +o_orderDATE between '1992-06-30' and '1992-12-31') +and +(l_partkey, l_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 1000 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY orders ref|filter PRIMARY,i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (7%) Using where; Using rowid filter +1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 dbt3_s001.orders.o_orderkey 4 Using where +1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where +update lineitem set l_tax = (l_tax*100+1)/100 where l_orderkey in (select o_orderkey from orders +where o_custkey in +(select c_custkey from customer +where c_nationkey in +(select n_nationkey from nation +where n_name='PERU')) +and +o_orderDATE between '1992-06-30' and '1992-12-31') +and +(l_partkey, l_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 1000 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders +where o_custkey in +(select c_custkey from customer +where c_nationkey in +(select n_nationkey from nation +where n_name='PERU')) +and +o_orderDATE between '1992-06-30' and '1992-12-31') +and +(l_partkey, l_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 1000 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +l_orderkey l_linenumber l_tax +4996 1 0.02 +933 1 0.05 +2500 2 0.03 +2500 4 0.03 +update lineitem set l_tax = (l_tax*100-1)/100 where l_orderkey in (select o_orderkey from orders +where o_custkey in +(select c_custkey from customer +where c_nationkey in +(select n_nationkey from nation +where n_name='PERU')) +and +o_orderDATE between '1992-06-30' and '1992-12-31') +and +(l_partkey, l_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 1000 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders +where o_custkey in +(select c_custkey from customer +where c_nationkey in +(select n_nationkey from nation +where n_name='PERU')) +and +o_orderDATE between '1992-06-30' and '1992-12-31') +and +(l_partkey, l_suppkey) in +(select p_partkey, s_suppkey from part, supplier +where p_retailprice between 901 and 1000 and +s_nationkey in (select n_nationkey from nation +where n_name='PERU')); +l_orderkey l_linenumber l_tax +4996 1 0.01 +933 1 0.04 +2500 2 0.02 +2500 4 0.02 +# FirstMatch +# ========== +set optimizer_switch='materialization=off'; +explain +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ALL PRIMARY,i_n_regionkey NULL NULL NULL 25 Using where +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (9%) Using where; FirstMatch(customer); Using rowid filter +explain format=json +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.40015207, + "nested_loop": [ + { + "table": { + "table_name": "nation", + "access_type": "ALL", + "possible_keys": ["PRIMARY", "i_n_regionkey"], + "loops": 1, + "rows": 25, + "cost": 0.013945725, + "filtered": 40, + "attached_condition": "nation.n_regionkey in (1,2)" + } + }, + { + "table": { + "table_name": "customer", + "access_type": "ref", + "possible_keys": ["PRIMARY", "i_c_nationkey"], + "key": "i_c_nationkey", + "key_length": "5", + "used_key_parts": ["c_nationkey"], + "ref": ["dbt3_s001.nation.n_nationkey"], + "loops": 10, + "rows": 6, + "cost": 0.08009436, + "filtered": 100 + } + }, + { + "table": { + "table_name": "orders", + "access_type": "ref", + "possible_keys": ["i_o_orderdate", "i_o_custkey"], + "key": "i_o_custkey", + "key_length": "5", + "used_key_parts": ["o_custkey"], + "ref": ["dbt3_s001.customer.c_custkey"], + "rowid_filter": { + "range": { + "key": "i_o_orderdate", + "used_key_parts": ["o_orderDATE"] + }, + "rows": 140, + "selectivity_pct": 9.333333333 + }, + "loops": 60, + "rows": 15, + "cost": 0.306111985, + "filtered": 6.666666508, + "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-06-08'", + "first_match": "customer" + } + } + ] + } +} +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000059 3458.6 +Customer#000000106 3288.42 +Customer#000000017 6.34 +Customer#000000047 274.58 +Customer#000000092 1182.91 +Customer#000000101 7470.96 +Customer#000000022 591.98 +Customer#000000040 1335.3 +Customer#000000064 -646.64 +Customer#000000122 7865.46 +Customer#000000028 1007.18 +Customer#000000037 -917.75 +Customer#000000091 4643.14 +Customer#000000115 7508.92 +Customer#000000067 8166.59 +Customer#000000094 5500.11 +Customer#000000103 2757.45 +Customer#000000130 5073.58 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +Customer#000000025 7133.7 +Customer#000000008 6819.74 +Customer#000000061 1536.24 +Customer#000000077 1738.87 +Customer#000000097 2164.48 +Customer#000000121 6428.32 +Customer#000000133 2314.67 +Customer#000000007 9561.95 +Customer#000000019 8914.71 +Customer#000000082 9468.34 +Customer#000000124 1842.49 +Customer#000000127 9280.71 +explain +update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ALL PRIMARY,i_n_regionkey NULL NULL NULL 25 Using where +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (9%) Using where; FirstMatch(customer); Using rowid filter +explain format=json +update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.40015207, + "nested_loop": [ + { + "table": { + "table_name": "nation", + "access_type": "ALL", + "possible_keys": ["PRIMARY", "i_n_regionkey"], + "loops": 1, + "rows": 25, + "cost": 0.013945725, + "filtered": 40, + "attached_condition": "nation.n_regionkey in (1,2)" + } + }, + { + "table": { + "table_name": "customer", + "access_type": "ref", + "possible_keys": ["PRIMARY", "i_c_nationkey"], + "key": "i_c_nationkey", + "key_length": "5", + "used_key_parts": ["c_nationkey"], + "ref": ["dbt3_s001.nation.n_nationkey"], + "loops": 10, + "rows": 6, + "cost": 0.08009436, + "filtered": 100 + } + }, + { + "table": { + "table_name": "orders", + "access_type": "ref", + "possible_keys": ["i_o_orderdate", "i_o_custkey"], + "key": "i_o_custkey", + "key_length": "5", + "used_key_parts": ["o_custkey"], + "ref": ["dbt3_s001.customer.c_custkey"], + "rowid_filter": { + "range": { + "key": "i_o_orderdate", + "used_key_parts": ["o_orderDATE"] + }, + "rows": 140, + "selectivity_pct": 9.333333333 + }, + "loops": 60, + "rows": 15, + "cost": 0.306111985, + "filtered": 6.666666508, + "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-06-08'", + "first_match": "customer" + } + } + ] + } +} +update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000059 3468.6 +Customer#000000106 3298.42 +Customer#000000017 16.34 +Customer#000000047 284.58 +Customer#000000092 1192.91 +Customer#000000101 7480.96 +Customer#000000022 601.98 +Customer#000000040 1345.3 +Customer#000000064 -636.64 +Customer#000000122 7875.46 +Customer#000000028 1017.18 +Customer#000000037 -907.75 +Customer#000000091 4653.14 +Customer#000000115 7518.92 +Customer#000000067 8176.59 +Customer#000000094 5510.11 +Customer#000000103 2767.45 +Customer#000000130 5083.58 +Customer#000000139 7907.78 +Customer#000000142 2219.81 +Customer#000000025 7143.7 +Customer#000000008 6829.74 +Customer#000000061 1546.24 +Customer#000000077 1748.87 +Customer#000000097 2174.48 +Customer#000000121 6438.32 +Customer#000000133 2324.67 +Customer#000000007 9571.95 +Customer#000000019 8924.71 +Customer#000000082 9478.34 +Customer#000000124 1852.49 +Customer#000000127 9290.71 +update customer set c_acctbal = c_acctbal-10 where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000059 3458.6 +Customer#000000106 3288.42 +Customer#000000017 6.34 +Customer#000000047 274.58 +Customer#000000092 1182.91 +Customer#000000101 7470.96 +Customer#000000022 591.98 +Customer#000000040 1335.3 +Customer#000000064 -646.64 +Customer#000000122 7865.46 +Customer#000000028 1007.18 +Customer#000000037 -917.75 +Customer#000000091 4643.14 +Customer#000000115 7508.92 +Customer#000000067 8166.59 +Customer#000000094 5500.11 +Customer#000000103 2757.45 +Customer#000000130 5073.58 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +Customer#000000025 7133.7 +Customer#000000008 6819.74 +Customer#000000061 1536.24 +Customer#000000077 1738.87 +Customer#000000097 2164.48 +Customer#000000121 6428.32 +Customer#000000133 2314.67 +Customer#000000007 9561.95 +Customer#000000019 8914.71 +Customer#000000082 9468.34 +Customer#000000124 1842.49 +Customer#000000127 9280.71 +set optimizer_switch='materialization=default'; +explain +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU') +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1993-01-08"); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (14%) Using where; FirstMatch(customer); Using rowid filter +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU') +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1993-01-08"); +c_name c_acctbal +Customer#000000008 6819.74 +Customer#000000035 1228.24 +Customer#000000061 1536.24 +Customer#000000097 2164.48 +Customer#000000121 6428.32 +Customer#000000133 2314.67 +explain +update customer set c_acctbal = c_acctbal+20 where c_nationkey in (select n_nationkey from nation where n_name='PERU') +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1993-01-08"); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (14%) Using where; FirstMatch(customer); Using rowid filter +update customer set c_acctbal = c_acctbal+20 where c_nationkey in (select n_nationkey from nation where n_name='PERU') +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1993-01-08"); +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU') +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1993-01-08"); +c_name c_acctbal +Customer#000000008 6839.74 +Customer#000000035 1248.24 +Customer#000000061 1556.24 +Customer#000000097 2184.48 +Customer#000000121 6448.32 +Customer#000000133 2334.67 +update customer set c_acctbal = c_acctbal-20 where c_nationkey in (select n_nationkey from nation where n_name='PERU') +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1993-01-08"); +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU') +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1993-01-08"); +c_name c_acctbal +Customer#000000008 6819.74 +Customer#000000035 1228.24 +Customer#000000061 1536.24 +Customer#000000097 2164.48 +Customer#000000121 6428.32 +Customer#000000133 2314.67 +# Materialization +# =============== +set optimizer_switch='firstmatch=off'; +explain +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where +n_name in ('JAPAN', 'INDONESIA', 'PERU', 'ARGENTINA')) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1995-01-08"); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation range PRIMARY,i_n_name i_n_name 26 NULL 4 Using index condition +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 +3 MATERIALIZED orders ALL i_o_orderdate,i_o_custkey NULL NULL NULL 1500 Using where +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where +n_name in ('JAPAN', 'INDONESIA', 'PERU', 'ARGENTINA')) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1995-01-08"); +c_name c_acctbal +Customer#000000014 5266.3 +Customer#000000059 3458.6 +Customer#000000106 3288.42 +Customer#000000067 8166.59 +Customer#000000094 5500.11 +Customer#000000103 2757.45 +Customer#000000130 5073.58 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +Customer#000000025 7133.7 +Customer#000000038 6345.11 +Customer#000000098 -551.37 +Customer#000000113 2912 +Customer#000000008 6819.74 +Customer#000000035 1228.24 +Customer#000000061 1536.24 +Customer#000000077 1738.87 +Customer#000000097 2164.48 +Customer#000000121 6428.32 +Customer#000000133 2314.67 +explain +update customer set c_acctbal = c_acctbal+20 where c_nationkey in (select n_nationkey from nation where +n_name in ('JAPAN', 'INDONESIA', 'PERU', 'ARGENTINA')) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1995-01-08"); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY nation range PRIMARY,i_n_name i_n_name 26 NULL 4 Using index condition +1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 +3 MATERIALIZED orders ALL i_o_orderdate,i_o_custkey NULL NULL NULL 1500 Using where +update customer set c_acctbal = c_acctbal+20 where c_nationkey in (select n_nationkey from nation where +n_name in ('JAPAN', 'INDONESIA', 'PERU', 'ARGENTINA')) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1995-01-08"); +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where +n_name in ('JAPAN', 'INDONESIA', 'PERU', 'ARGENTINA')) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1995-01-08"); +c_name c_acctbal +Customer#000000014 5286.3 +Customer#000000059 3478.6 +Customer#000000106 3308.42 +Customer#000000067 8186.59 +Customer#000000094 5520.11 +Customer#000000103 2777.45 +Customer#000000130 5093.58 +Customer#000000139 7917.78 +Customer#000000142 2229.81 +Customer#000000025 7153.7 +Customer#000000038 6365.11 +Customer#000000098 -531.37 +Customer#000000113 2932 +Customer#000000008 6839.74 +Customer#000000035 1248.24 +Customer#000000061 1556.24 +Customer#000000077 1758.87 +Customer#000000097 2184.48 +Customer#000000121 6448.32 +Customer#000000133 2334.67 +update customer set c_acctbal = c_acctbal-20 where c_nationkey in (select n_nationkey from nation where +n_name in ('JAPAN', 'INDONESIA', 'PERU', 'ARGENTINA')) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1995-01-08"); +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where +n_name in ('JAPAN', 'INDONESIA', 'PERU', 'ARGENTINA')) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between "1992-01-09" and "1995-01-08"); +c_name c_acctbal +Customer#000000014 5266.3 +Customer#000000059 3458.6 +Customer#000000106 3288.42 +Customer#000000067 8166.59 +Customer#000000094 5500.11 +Customer#000000103 2757.45 +Customer#000000130 5073.58 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +Customer#000000025 7133.7 +Customer#000000038 6345.11 +Customer#000000098 -551.37 +Customer#000000113 2912 +Customer#000000008 6819.74 +Customer#000000035 1228.24 +Customer#000000061 1536.24 +Customer#000000077 1738.87 +Customer#000000097 2164.48 +Customer#000000121 6428.32 +Customer#000000133 2314.67 +set optimizer_switch='firstmatch=default'; +explain +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED orders ALL i_o_orderdate,i_o_custkey NULL NULL NULL 1500 Using where +explain format=json +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.382051418, + "nested_loop": [ + { + "table": { + "table_name": "customer", + "access_type": "ALL", + "possible_keys": ["PRIMARY"], + "loops": 1, + "rows": 150, + "cost": 0.03493875, + "filtered": 100 + } + }, + { + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "4", + "used_key_parts": ["o_custkey"], + "ref": ["func"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "nested_loop": [ + { + "table": { + "table_name": "orders", + "access_type": "ALL", + "possible_keys": ["i_o_orderdate", "i_o_custkey"], + "loops": 1, + "rows": 1500, + "cost": 0.2532975, + "filtered": 16.13333321, + "attached_condition": "orders.o_orderDATE between '1992-01-09' and '1993-03-08'" + } + } + ] + } + } + } + } + ] + } +} +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000005 794.47 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000013 3857.34 +Customer#000000014 5266.3 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000032 3471.53 +Customer#000000034 8589.7 +Customer#000000035 1228.24 +Customer#000000037 -917.75 +Customer#000000038 6345.11 +Customer#000000040 1335.3 +Customer#000000041 270.95 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000052 5630.28 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000056 6530.86 +Customer#000000058 6478.46 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000062 595.61 +Customer#000000064 -646.64 +Customer#000000065 8795.16 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000089 1530.76 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000107 2514.15 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000115 7508.92 +Customer#000000116 8403.99 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000128 -986.96 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000140 9963.15 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000145 9748.93 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +explain +update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED orders ALL i_o_orderdate,i_o_custkey NULL NULL NULL 1500 Using where +explain format=json +update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.382051418, + "nested_loop": [ + { + "table": { + "table_name": "customer", + "access_type": "ALL", + "possible_keys": ["PRIMARY"], + "loops": 1, + "rows": 150, + "cost": 0.03493875, + "filtered": 100 + } + }, + { + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "4", + "used_key_parts": ["o_custkey"], + "ref": ["func"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "nested_loop": [ + { + "table": { + "table_name": "orders", + "access_type": "ALL", + "possible_keys": ["i_o_orderdate", "i_o_custkey"], + "loops": 1, + "rows": 1500, + "cost": 0.2532975, + "filtered": 16.13333321, + "attached_condition": "orders.o_orderDATE between '1992-01-09' and '1993-03-08'" + } + } + ] + } + } + } + } + ] + } +} +update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 716.56 +Customer#000000002 126.65 +Customer#000000005 799.47 +Customer#000000007 9566.95 +Customer#000000008 6824.74 +Customer#000000010 2758.54 +Customer#000000011 -267.6 +Customer#000000013 3862.34 +Customer#000000014 5271.3 +Customer#000000016 4686.03 +Customer#000000017 11.34 +Customer#000000019 8919.71 +Customer#000000022 596.98 +Customer#000000023 3337.02 +Customer#000000025 7138.7 +Customer#000000028 1012.18 +Customer#000000029 7623.27 +Customer#000000031 5241.89 +Customer#000000032 3476.53 +Customer#000000034 8594.7 +Customer#000000035 1233.24 +Customer#000000037 -912.75 +Customer#000000038 6350.11 +Customer#000000040 1340.3 +Customer#000000041 275.95 +Customer#000000043 9909.28 +Customer#000000044 7320.94 +Customer#000000046 5749.59 +Customer#000000047 279.58 +Customer#000000049 4578.94 +Customer#000000052 5635.28 +Customer#000000053 4118.64 +Customer#000000055 4577.11 +Customer#000000056 6535.86 +Customer#000000058 6483.46 +Customer#000000059 3463.6 +Customer#000000061 1541.24 +Customer#000000062 600.61 +Customer#000000064 -641.64 +Customer#000000065 8800.16 +Customer#000000067 8171.59 +Customer#000000070 4872.52 +Customer#000000071 -606.19 +Customer#000000073 4293.5 +Customer#000000074 2769.43 +Customer#000000076 5750.33 +Customer#000000079 5126.28 +Customer#000000080 7388.53 +Customer#000000082 9473.34 +Customer#000000083 6468.51 +Customer#000000085 3391.64 +Customer#000000086 3311.32 +Customer#000000088 8036.44 +Customer#000000089 1535.76 +Customer#000000091 4648.14 +Customer#000000092 1187.91 +Customer#000000094 5505.11 +Customer#000000095 5332.38 +Customer#000000097 2169.48 +Customer#000000098 -546.37 +Customer#000000100 9894.89 +Customer#000000101 7475.96 +Customer#000000103 2762.45 +Customer#000000104 -583.38 +Customer#000000106 3293.42 +Customer#000000107 2519.15 +Customer#000000109 -711.1 +Customer#000000110 7467.99 +Customer#000000112 2958.35 +Customer#000000115 7513.92 +Customer#000000116 8408.99 +Customer#000000118 3587.37 +Customer#000000121 6433.32 +Customer#000000122 7870.46 +Customer#000000127 9285.71 +Customer#000000128 -981.96 +Customer#000000130 5078.58 +Customer#000000131 8600.53 +Customer#000000133 2319.67 +Customer#000000134 4613.9 +Customer#000000136 -837.39 +Customer#000000137 7843.3 +Customer#000000139 7902.78 +Customer#000000140 9968.15 +Customer#000000142 2214.81 +Customer#000000143 2191.5 +Customer#000000145 9753.93 +Customer#000000148 2140.6 +Customer#000000149 8964.65 +update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000005 794.47 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000013 3857.34 +Customer#000000014 5266.3 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000032 3471.53 +Customer#000000034 8589.7 +Customer#000000035 1228.24 +Customer#000000037 -917.75 +Customer#000000038 6345.11 +Customer#000000040 1335.3 +Customer#000000041 270.95 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000052 5630.28 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000056 6530.86 +Customer#000000058 6478.46 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000062 595.61 +Customer#000000064 -646.64 +Customer#000000065 8795.16 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000089 1530.76 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000107 2514.15 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000115 7508.92 +Customer#000000116 8403.99 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000128 -986.96 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000140 9963.15 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000145 9748.93 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +explain +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-06-09' and '1993-01-08'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-06-09' and '1993-01-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000034 8589.7 +Customer#000000037 -917.75 +Customer#000000040 1335.3 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000061 1536.24 +Customer#000000064 -646.64 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +explain +update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-06-09' and '1993-01-08'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where +update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-06-09' and '1993-01-08'); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-06-09' and '1993-01-08'); +c_name c_acctbal +Customer#000000001 712.56 +Customer#000000002 122.65 +Customer#000000007 9562.95 +Customer#000000008 6820.74 +Customer#000000010 2754.54 +Customer#000000011 -271.6 +Customer#000000016 4682.03 +Customer#000000017 7.34 +Customer#000000019 8915.71 +Customer#000000022 592.98 +Customer#000000023 3333.02 +Customer#000000025 7134.7 +Customer#000000028 1008.18 +Customer#000000029 7619.27 +Customer#000000031 5237.89 +Customer#000000034 8590.7 +Customer#000000037 -916.75 +Customer#000000040 1336.3 +Customer#000000043 9905.28 +Customer#000000044 7316.94 +Customer#000000046 5745.59 +Customer#000000047 275.58 +Customer#000000049 4574.94 +Customer#000000053 4114.64 +Customer#000000055 4573.11 +Customer#000000061 1537.24 +Customer#000000064 -645.64 +Customer#000000067 8167.59 +Customer#000000070 4868.52 +Customer#000000071 -610.19 +Customer#000000073 4289.5 +Customer#000000074 2765.43 +Customer#000000076 5746.33 +Customer#000000079 5122.28 +Customer#000000080 7384.53 +Customer#000000082 9469.34 +Customer#000000083 6464.51 +Customer#000000085 3387.64 +Customer#000000086 3307.32 +Customer#000000088 8032.44 +Customer#000000091 4644.14 +Customer#000000092 1183.91 +Customer#000000095 5328.38 +Customer#000000097 2165.48 +Customer#000000100 9890.89 +Customer#000000101 7471.96 +Customer#000000103 2758.45 +Customer#000000104 -587.38 +Customer#000000106 3289.42 +Customer#000000109 -715.1 +Customer#000000110 7463.99 +Customer#000000112 2954.35 +Customer#000000118 3583.37 +Customer#000000121 6429.32 +Customer#000000122 7866.46 +Customer#000000127 9281.71 +Customer#000000130 5074.58 +Customer#000000131 8596.53 +Customer#000000133 2315.67 +Customer#000000134 4609.9 +Customer#000000136 -841.39 +Customer#000000137 7839.3 +Customer#000000139 7898.78 +Customer#000000142 2210.81 +Customer#000000143 2187.5 +Customer#000000148 2136.6 +Customer#000000149 8960.65 +update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-06-09' and '1993-01-08'); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-06-09' and '1993-01-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.18 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000034 8589.7 +Customer#000000037 -917.75 +Customer#000000040 1335.3 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000061 1536.24 +Customer#000000064 -646.64 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +# Materialization SJM +# =================== +explain +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28 +1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1 +2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary +explain format=json +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.085533248, + "nested_loop": [ + { + "table": { + "table_name": "<subquery2>", + "access_type": "ALL", + "possible_keys": ["distinct_key"], + "loops": 1, + "rows": 28, + "cost": 0.03691572, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "cost": 0.053826401, + "having_condition": "count(orders.o_custkey) > 1", + "temporary_table": { + "nested_loop": [ + { + "table": { + "table_name": "orders", + "access_type": "range", + "possible_keys": ["i_o_orderdate"], + "key": "i_o_orderdate", + "key_length": "4", + "used_key_parts": ["o_orderDATE"], + "loops": 1, + "rows": 28, + "cost": 0.035889016, + "filtered": 100, + "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'" + } + } + ] + } + } + } + } + }, + { + "table": { + "table_name": "customer", + "access_type": "eq_ref", + "possible_keys": ["PRIMARY"], + "key": "PRIMARY", + "key_length": "4", + "used_key_parts": ["c_custkey"], + "ref": ["<subquery2>.o_custkey"], + "loops": 28, + "rows": 1, + "cost": 0.048617528, + "filtered": 100 + } + } + ] + } +} +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3857.34 +Customer#000000032 3471.53 +Customer#000000037 -917.75 +Customer#000000118 3582.37 +Customer#000000056 6530.86 +explain +update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28 +1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1 +2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary +explain format=json +update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.085533248, + "nested_loop": [ + { + "table": { + "table_name": "<subquery2>", + "access_type": "ALL", + "possible_keys": ["distinct_key"], + "loops": 1, + "rows": 28, + "cost": 0.03691572, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "cost": 0.053826401, + "having_condition": "count(orders.o_custkey) > 1", + "temporary_table": { + "nested_loop": [ + { + "table": { + "table_name": "orders", + "access_type": "range", + "possible_keys": ["i_o_orderdate"], + "key": "i_o_orderdate", + "key_length": "4", + "used_key_parts": ["o_orderDATE"], + "loops": 1, + "rows": 28, + "cost": 0.035889016, + "filtered": 100, + "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'" + } + } + ] + } + } + } + } + }, + { + "table": { + "table_name": "customer", + "access_type": "eq_ref", + "possible_keys": ["PRIMARY"], + "key": "PRIMARY", + "key_length": "4", + "used_key_parts": ["c_custkey"], + "ref": ["<subquery2>.o_custkey"], + "loops": 28, + "rows": 1, + "cost": 0.048617528, + "filtered": 100 + } + } + ] + } +} +update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3852.34 +Customer#000000032 3466.53 +Customer#000000037 -922.75 +Customer#000000118 3577.37 +Customer#000000056 6525.86 +update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3857.34 +Customer#000000032 3471.53 +Customer#000000037 -917.75 +Customer#000000118 3582.37 +Customer#000000056 6530.86 +explain +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08' + group by o_custkey having count(o_custkey) > 5); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1 +2 MATERIALIZED orders ALL i_o_orderdate NULL NULL NULL 1500 Using where; Using temporary +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08' + group by o_custkey having count(o_custkey) > 5); +c_name c_acctbal +Customer#000000007 9561.95 +Customer#000000016 4681.03 +Customer#000000037 -917.75 +Customer#000000046 5744.59 +Customer#000000091 4643.14 +Customer#000000103 2757.45 +Customer#000000118 3582.37 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +explain +update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08' + group by o_custkey having count(o_custkey) > 5); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1 +2 MATERIALIZED orders ALL i_o_orderdate NULL NULL NULL 1500 Using where; Using temporary +update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08' + group by o_custkey having count(o_custkey) > 5); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08' + group by o_custkey having count(o_custkey) > 5); +c_name c_acctbal +Customer#000000007 9560.95 +Customer#000000016 4680.03 +Customer#000000037 -918.75 +Customer#000000046 5743.59 +Customer#000000091 4642.14 +Customer#000000103 2756.45 +Customer#000000118 3581.37 +Customer#000000133 2313.67 +Customer#000000134 4607.9 +update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08' + group by o_custkey having count(o_custkey) > 5); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08' + group by o_custkey having count(o_custkey) > 5); +c_name c_acctbal +Customer#000000007 9561.95 +Customer#000000016 4681.03 +Customer#000000037 -917.75 +Customer#000000046 5744.59 +Customer#000000091 4643.14 +Customer#000000103 2757.45 +Customer#000000118 3582.37 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +# Pullout PS +# ========== +prepare stmt from " +update orders set o_totalprice = o_totalprice+? where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +"; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +644 201268.06 +2880 145761.99 +3142 16030.15 +5382 138423.03 +5095 184583.99 +737 12984.85 +1729 12137.76 +5121 150334.57 +set @a1=-20; +execute stmt using @a1; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +644 201248.06 +2880 145741.99 +3142 16010.15 +5382 138403.03 +5095 184563.99 +737 12964.85 +1729 12117.76 +5121 150314.57 +set @a2=-10; +execute stmt using @a2; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +644 201238.06 +2880 145731.99 +3142 16000.15 +5382 138393.03 +5095 184553.99 +737 12954.85 +1729 12107.76 +5121 150304.57 +execute stmt using -(@a1+@a2); +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +644 201268.06 +2880 145761.99 +3142 16030.15 +5382 138423.03 +5095 184583.99 +737 12984.85 +1729 12137.76 +5121 150334.57 +deallocate prepare stmt; +# FirstMatch PS +# ============= +set optimizer_switch='materialization=off'; +prepare stmt from " +update customer set c_acctbal = c_acctbal+? where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +"; +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000059 3458.6 +Customer#000000106 3288.42 +Customer#000000017 6.34 +Customer#000000047 274.58 +Customer#000000092 1182.91 +Customer#000000101 7470.96 +Customer#000000022 591.98 +Customer#000000040 1335.3 +Customer#000000064 -646.64 +Customer#000000122 7865.46 +Customer#000000028 1007.18 +Customer#000000037 -917.75 +Customer#000000091 4643.14 +Customer#000000115 7508.92 +Customer#000000067 8166.59 +Customer#000000094 5500.11 +Customer#000000103 2757.45 +Customer#000000130 5073.58 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +Customer#000000025 7133.7 +Customer#000000008 6819.74 +Customer#000000061 1536.24 +Customer#000000077 1738.87 +Customer#000000097 2164.48 +Customer#000000121 6428.32 +Customer#000000133 2314.67 +Customer#000000007 9561.95 +Customer#000000019 8914.71 +Customer#000000082 9468.34 +Customer#000000124 1842.49 +Customer#000000127 9280.71 +set @a1=15; +execute stmt using @a1; +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000059 3473.6 +Customer#000000106 3303.42 +Customer#000000017 21.34 +Customer#000000047 289.58 +Customer#000000092 1197.91 +Customer#000000101 7485.96 +Customer#000000022 606.98 +Customer#000000040 1350.3 +Customer#000000064 -631.64 +Customer#000000122 7880.46 +Customer#000000028 1022.18 +Customer#000000037 -902.75 +Customer#000000091 4658.14 +Customer#000000115 7523.92 +Customer#000000067 8181.59 +Customer#000000094 5515.11 +Customer#000000103 2772.45 +Customer#000000130 5088.58 +Customer#000000139 7912.78 +Customer#000000142 2224.81 +Customer#000000025 7148.7 +Customer#000000008 6834.74 +Customer#000000061 1551.24 +Customer#000000077 1753.87 +Customer#000000097 2179.48 +Customer#000000121 6443.32 +Customer#000000133 2329.67 +Customer#000000007 9576.95 +Customer#000000019 8929.71 +Customer#000000082 9483.34 +Customer#000000124 1857.49 +Customer#000000127 9295.71 +set @a2=5; +execute stmt using @a2; +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000059 3478.6 +Customer#000000106 3308.42 +Customer#000000017 26.34 +Customer#000000047 294.58 +Customer#000000092 1202.91 +Customer#000000101 7490.96 +Customer#000000022 611.98 +Customer#000000040 1355.3 +Customer#000000064 -626.64 +Customer#000000122 7885.46 +Customer#000000028 1027.1799999999998 +Customer#000000037 -897.75 +Customer#000000091 4663.14 +Customer#000000115 7528.92 +Customer#000000067 8186.59 +Customer#000000094 5520.11 +Customer#000000103 2777.45 +Customer#000000130 5093.58 +Customer#000000139 7917.78 +Customer#000000142 2229.81 +Customer#000000025 7153.7 +Customer#000000008 6839.74 +Customer#000000061 1556.24 +Customer#000000077 1758.87 +Customer#000000097 2184.48 +Customer#000000121 6448.32 +Customer#000000133 2334.67 +Customer#000000007 9581.95 +Customer#000000019 8934.71 +Customer#000000082 9488.34 +Customer#000000124 1862.49 +Customer#000000127 9300.71 +execute stmt using -(@a1+@a2); +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000059 3458.6 +Customer#000000106 3288.42 +Customer#000000017 6.34 +Customer#000000047 274.58 +Customer#000000092 1182.91 +Customer#000000101 7470.96 +Customer#000000022 591.98 +Customer#000000040 1335.3 +Customer#000000064 -646.64 +Customer#000000122 7865.46 +Customer#000000028 1007.1799999999998 +Customer#000000037 -917.75 +Customer#000000091 4643.14 +Customer#000000115 7508.92 +Customer#000000067 8166.59 +Customer#000000094 5500.11 +Customer#000000103 2757.45 +Customer#000000130 5073.58 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +Customer#000000025 7133.7 +Customer#000000008 6819.74 +Customer#000000061 1536.24 +Customer#000000077 1738.87 +Customer#000000097 2164.48 +Customer#000000121 6428.32 +Customer#000000133 2314.67 +Customer#000000007 9561.95 +Customer#000000019 8914.71 +Customer#000000082 9468.34 +Customer#000000124 1842.49 +Customer#000000127 9280.71 +deallocate prepare stmt; +set optimizer_switch='materialization=default'; +# Materialization PS +# ================== +prepare stmt from " +update customer set c_acctbal = c_acctbal+? where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +"; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000005 794.47 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000013 3857.34 +Customer#000000014 5266.3 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.1799999999998 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000032 3471.53 +Customer#000000034 8589.7 +Customer#000000035 1228.24 +Customer#000000037 -917.75 +Customer#000000038 6345.11 +Customer#000000040 1335.3 +Customer#000000041 270.95 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000052 5630.28 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000056 6530.86 +Customer#000000058 6478.46 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000062 595.61 +Customer#000000064 -646.64 +Customer#000000065 8795.16 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000089 1530.76 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000107 2514.15 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000115 7508.92 +Customer#000000116 8403.99 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000128 -986.96 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000140 9963.15 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000145 9748.93 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +set @a1=7; +execute stmt using @a1; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 718.56 +Customer#000000002 128.65 +Customer#000000005 801.47 +Customer#000000007 9568.95 +Customer#000000008 6826.74 +Customer#000000010 2760.54 +Customer#000000011 -265.6 +Customer#000000013 3864.34 +Customer#000000014 5273.3 +Customer#000000016 4688.03 +Customer#000000017 13.34 +Customer#000000019 8921.71 +Customer#000000022 598.98 +Customer#000000023 3339.02 +Customer#000000025 7140.7 +Customer#000000028 1014.1799999999998 +Customer#000000029 7625.27 +Customer#000000031 5243.89 +Customer#000000032 3478.53 +Customer#000000034 8596.7 +Customer#000000035 1235.24 +Customer#000000037 -910.75 +Customer#000000038 6352.11 +Customer#000000040 1342.3 +Customer#000000041 277.95 +Customer#000000043 9911.28 +Customer#000000044 7322.94 +Customer#000000046 5751.59 +Customer#000000047 281.58 +Customer#000000049 4580.94 +Customer#000000052 5637.28 +Customer#000000053 4120.64 +Customer#000000055 4579.11 +Customer#000000056 6537.86 +Customer#000000058 6485.46 +Customer#000000059 3465.6 +Customer#000000061 1543.24 +Customer#000000062 602.61 +Customer#000000064 -639.64 +Customer#000000065 8802.16 +Customer#000000067 8173.59 +Customer#000000070 4874.52 +Customer#000000071 -604.19 +Customer#000000073 4295.5 +Customer#000000074 2771.43 +Customer#000000076 5752.33 +Customer#000000079 5128.28 +Customer#000000080 7390.53 +Customer#000000082 9475.34 +Customer#000000083 6470.51 +Customer#000000085 3393.64 +Customer#000000086 3313.32 +Customer#000000088 8038.44 +Customer#000000089 1537.76 +Customer#000000091 4650.14 +Customer#000000092 1189.91 +Customer#000000094 5507.11 +Customer#000000095 5334.38 +Customer#000000097 2171.48 +Customer#000000098 -544.37 +Customer#000000100 9896.89 +Customer#000000101 7477.96 +Customer#000000103 2764.45 +Customer#000000104 -581.38 +Customer#000000106 3295.42 +Customer#000000107 2521.15 +Customer#000000109 -709.1 +Customer#000000110 7469.99 +Customer#000000112 2960.35 +Customer#000000115 7515.92 +Customer#000000116 8410.99 +Customer#000000118 3589.37 +Customer#000000121 6435.32 +Customer#000000122 7872.46 +Customer#000000127 9287.71 +Customer#000000128 -979.96 +Customer#000000130 5080.58 +Customer#000000131 8602.53 +Customer#000000133 2321.67 +Customer#000000134 4615.9 +Customer#000000136 -835.39 +Customer#000000137 7845.3 +Customer#000000139 7904.78 +Customer#000000140 9970.15 +Customer#000000142 2216.81 +Customer#000000143 2193.5 +Customer#000000145 9755.93 +Customer#000000148 2142.6 +Customer#000000149 8966.65 +set @a2=3; +execute stmt using @a2; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 721.56 +Customer#000000002 131.65 +Customer#000000005 804.47 +Customer#000000007 9571.95 +Customer#000000008 6829.74 +Customer#000000010 2763.54 +Customer#000000011 -262.6 +Customer#000000013 3867.34 +Customer#000000014 5276.3 +Customer#000000016 4691.03 +Customer#000000017 16.34 +Customer#000000019 8924.71 +Customer#000000022 601.98 +Customer#000000023 3342.02 +Customer#000000025 7143.7 +Customer#000000028 1017.1799999999998 +Customer#000000029 7628.27 +Customer#000000031 5246.89 +Customer#000000032 3481.53 +Customer#000000034 8599.7 +Customer#000000035 1238.24 +Customer#000000037 -907.75 +Customer#000000038 6355.11 +Customer#000000040 1345.3 +Customer#000000041 280.95 +Customer#000000043 9914.28 +Customer#000000044 7325.94 +Customer#000000046 5754.59 +Customer#000000047 284.58 +Customer#000000049 4583.94 +Customer#000000052 5640.28 +Customer#000000053 4123.64 +Customer#000000055 4582.11 +Customer#000000056 6540.86 +Customer#000000058 6488.46 +Customer#000000059 3468.6 +Customer#000000061 1546.24 +Customer#000000062 605.61 +Customer#000000064 -636.64 +Customer#000000065 8805.16 +Customer#000000067 8176.59 +Customer#000000070 4877.52 +Customer#000000071 -601.19 +Customer#000000073 4298.5 +Customer#000000074 2774.43 +Customer#000000076 5755.33 +Customer#000000079 5131.28 +Customer#000000080 7393.53 +Customer#000000082 9478.34 +Customer#000000083 6473.51 +Customer#000000085 3396.64 +Customer#000000086 3316.32 +Customer#000000088 8041.44 +Customer#000000089 1540.76 +Customer#000000091 4653.14 +Customer#000000092 1192.91 +Customer#000000094 5510.11 +Customer#000000095 5337.38 +Customer#000000097 2174.48 +Customer#000000098 -541.37 +Customer#000000100 9899.89 +Customer#000000101 7480.96 +Customer#000000103 2767.45 +Customer#000000104 -578.38 +Customer#000000106 3298.42 +Customer#000000107 2524.15 +Customer#000000109 -706.1 +Customer#000000110 7472.99 +Customer#000000112 2963.35 +Customer#000000115 7518.92 +Customer#000000116 8413.99 +Customer#000000118 3592.37 +Customer#000000121 6438.32 +Customer#000000122 7875.46 +Customer#000000127 9290.71 +Customer#000000128 -976.96 +Customer#000000130 5083.58 +Customer#000000131 8605.53 +Customer#000000133 2324.67 +Customer#000000134 4618.9 +Customer#000000136 -832.39 +Customer#000000137 7848.3 +Customer#000000139 7907.78 +Customer#000000140 9973.15 +Customer#000000142 2219.81 +Customer#000000143 2196.5 +Customer#000000145 9758.93 +Customer#000000148 2145.6 +Customer#000000149 8969.65 +execute stmt using -(@a1+@a2); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000005 794.47 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000013 3857.34 +Customer#000000014 5266.3 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.1799999999998 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000032 3471.53 +Customer#000000034 8589.7 +Customer#000000035 1228.24 +Customer#000000037 -917.75 +Customer#000000038 6345.11 +Customer#000000040 1335.3 +Customer#000000041 270.95 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000052 5630.28 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000056 6530.86 +Customer#000000058 6478.46 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000062 595.61 +Customer#000000064 -646.64 +Customer#000000065 8795.16 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000089 1530.76 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000107 2514.15 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000115 7508.92 +Customer#000000116 8403.99 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000128 -986.96 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000140 9963.15 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000145 9748.93 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +deallocate prepare stmt; +# Materialization SJM PS +# ====================== +prepare stmt from " +update customer set c_acctbal = c_acctbal+? where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +"; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3857.34 +Customer#000000032 3471.53 +Customer#000000037 -917.75 +Customer#000000118 3582.37 +Customer#000000056 6530.86 +set @a1=-2; +execute stmt using @a1; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3855.34 +Customer#000000032 3469.53 +Customer#000000037 -919.75 +Customer#000000118 3580.37 +Customer#000000056 6528.86 +set @a2=-1; +execute stmt using @a2; +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3854.34 +Customer#000000032 3468.53 +Customer#000000037 -920.75 +Customer#000000118 3579.37 +Customer#000000056 6527.86 +execute stmt using -(@a1+@a2); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3857.34 +Customer#000000032 3471.53 +Customer#000000037 -917.75 +Customer#000000118 3582.37 +Customer#000000056 6530.86 +deallocate prepare stmt; +# Pullout SP +# ========== +create procedure p(d int) +update orders set o_totalprice = o_totalprice+d where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +644 201268.06 +2880 145761.99 +3142 16030.15 +5382 138423.03 +5095 184583.99 +737 12984.85 +1729 12137.76 +5121 150334.57 +call p(-10); +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +644 201258.06 +2880 145751.99 +3142 16020.15 +5382 138413.03 +5095 184573.99 +737 12974.85 +1729 12127.76 +5121 150324.57 +call p(-20); +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +644 201238.06 +2880 145731.99 +3142 16000.15 +5382 138393.03 +5095 184553.99 +737 12954.85 +1729 12107.76 +5121 150304.57 +call p(10+20); +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (select n_nationkey from nation +where n_name='PERU')); +o_orderkey o_totalprice +644 201268.06 +2880 145761.99 +3142 16030.15 +5382 138423.03 +5095 184583.99 +737 12984.85 +1729 12137.76 +5121 150334.57 +drop procedure p; +# FirstMatch SP +# ============= +set optimizer_switch='materialization=off'; +create procedure p(d int) +update customer set c_acctbal = c_acctbal+d where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000059 3458.6 +Customer#000000106 3288.42 +Customer#000000017 6.34 +Customer#000000047 274.58 +Customer#000000092 1182.91 +Customer#000000101 7470.96 +Customer#000000022 591.98 +Customer#000000040 1335.3 +Customer#000000064 -646.64 +Customer#000000122 7865.46 +Customer#000000028 1007.1799999999998 +Customer#000000037 -917.75 +Customer#000000091 4643.14 +Customer#000000115 7508.92 +Customer#000000067 8166.59 +Customer#000000094 5500.11 +Customer#000000103 2757.45 +Customer#000000130 5073.58 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +Customer#000000025 7133.7 +Customer#000000008 6819.74 +Customer#000000061 1536.24 +Customer#000000077 1738.87 +Customer#000000097 2164.48 +Customer#000000121 6428.32 +Customer#000000133 2314.67 +Customer#000000007 9561.95 +Customer#000000019 8914.71 +Customer#000000082 9468.34 +Customer#000000124 1842.49 +Customer#000000127 9280.71 +call p(5); +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000059 3463.6 +Customer#000000106 3293.42 +Customer#000000017 11.34 +Customer#000000047 279.58 +Customer#000000092 1187.91 +Customer#000000101 7475.96 +Customer#000000022 596.98 +Customer#000000040 1340.3 +Customer#000000064 -641.64 +Customer#000000122 7870.46 +Customer#000000028 1012.1799999999998 +Customer#000000037 -912.75 +Customer#000000091 4648.14 +Customer#000000115 7513.92 +Customer#000000067 8171.59 +Customer#000000094 5505.11 +Customer#000000103 2762.45 +Customer#000000130 5078.58 +Customer#000000139 7902.78 +Customer#000000142 2214.81 +Customer#000000025 7138.7 +Customer#000000008 6824.74 +Customer#000000061 1541.24 +Customer#000000077 1743.87 +Customer#000000097 2169.48 +Customer#000000121 6433.32 +Customer#000000133 2319.67 +Customer#000000007 9566.95 +Customer#000000019 8919.71 +Customer#000000082 9473.34 +Customer#000000124 1847.49 +Customer#000000127 9285.71 +call p(15); +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000059 3478.6 +Customer#000000106 3308.42 +Customer#000000017 26.34 +Customer#000000047 294.58 +Customer#000000092 1202.91 +Customer#000000101 7490.96 +Customer#000000022 611.98 +Customer#000000040 1355.3 +Customer#000000064 -626.64 +Customer#000000122 7885.46 +Customer#000000028 1027.1799999999998 +Customer#000000037 -897.75 +Customer#000000091 4663.14 +Customer#000000115 7528.92 +Customer#000000067 8186.59 +Customer#000000094 5520.11 +Customer#000000103 2777.45 +Customer#000000130 5093.58 +Customer#000000139 7917.78 +Customer#000000142 2229.81 +Customer#000000025 7153.7 +Customer#000000008 6839.74 +Customer#000000061 1556.24 +Customer#000000077 1758.87 +Customer#000000097 2184.48 +Customer#000000121 6448.32 +Customer#000000133 2334.67 +Customer#000000007 9581.95 +Customer#000000019 8934.71 +Customer#000000082 9488.34 +Customer#000000124 1862.49 +Customer#000000127 9300.71 +call p(-(5+15)); +select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation +where n_regionkey in (1,2)) +and +c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-10-09' and '1993-06-08'); +c_name c_acctbal +Customer#000000059 3458.6 +Customer#000000106 3288.42 +Customer#000000017 6.34 +Customer#000000047 274.58 +Customer#000000092 1182.91 +Customer#000000101 7470.96 +Customer#000000022 591.98 +Customer#000000040 1335.3 +Customer#000000064 -646.64 +Customer#000000122 7865.46 +Customer#000000028 1007.1799999999998 +Customer#000000037 -917.75 +Customer#000000091 4643.14 +Customer#000000115 7508.92 +Customer#000000067 8166.59 +Customer#000000094 5500.11 +Customer#000000103 2757.45 +Customer#000000130 5073.58 +Customer#000000139 7897.78 +Customer#000000142 2209.81 +Customer#000000025 7133.7 +Customer#000000008 6819.74 +Customer#000000061 1536.24 +Customer#000000077 1738.87 +Customer#000000097 2164.48 +Customer#000000121 6428.32 +Customer#000000133 2314.67 +Customer#000000007 9561.95 +Customer#000000019 8914.71 +Customer#000000082 9468.34 +Customer#000000124 1842.49 +Customer#000000127 9280.71 +drop procedure p; +set optimizer_switch='materialization=default'; +# Materialization SP +# ================== +create procedure p(d int) +update customer set c_acctbal = c_acctbal+d where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000005 794.47 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000013 3857.34 +Customer#000000014 5266.3 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.1799999999998 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000032 3471.53 +Customer#000000034 8589.7 +Customer#000000035 1228.24 +Customer#000000037 -917.75 +Customer#000000038 6345.11 +Customer#000000040 1335.3 +Customer#000000041 270.95 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000052 5630.28 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000056 6530.86 +Customer#000000058 6478.46 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000062 595.61 +Customer#000000064 -646.64 +Customer#000000065 8795.16 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000089 1530.76 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000107 2514.15 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000115 7508.92 +Customer#000000116 8403.99 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000128 -986.96 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000140 9963.15 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000145 9748.93 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +call p(3); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 714.56 +Customer#000000002 124.65 +Customer#000000005 797.47 +Customer#000000007 9564.95 +Customer#000000008 6822.74 +Customer#000000010 2756.54 +Customer#000000011 -269.6 +Customer#000000013 3860.34 +Customer#000000014 5269.3 +Customer#000000016 4684.03 +Customer#000000017 9.34 +Customer#000000019 8917.71 +Customer#000000022 594.98 +Customer#000000023 3335.02 +Customer#000000025 7136.7 +Customer#000000028 1010.1799999999998 +Customer#000000029 7621.27 +Customer#000000031 5239.89 +Customer#000000032 3474.53 +Customer#000000034 8592.7 +Customer#000000035 1231.24 +Customer#000000037 -914.75 +Customer#000000038 6348.11 +Customer#000000040 1338.3 +Customer#000000041 273.95 +Customer#000000043 9907.28 +Customer#000000044 7318.94 +Customer#000000046 5747.59 +Customer#000000047 277.58 +Customer#000000049 4576.94 +Customer#000000052 5633.28 +Customer#000000053 4116.64 +Customer#000000055 4575.11 +Customer#000000056 6533.86 +Customer#000000058 6481.46 +Customer#000000059 3461.6 +Customer#000000061 1539.24 +Customer#000000062 598.61 +Customer#000000064 -643.64 +Customer#000000065 8798.16 +Customer#000000067 8169.59 +Customer#000000070 4870.52 +Customer#000000071 -608.19 +Customer#000000073 4291.5 +Customer#000000074 2767.43 +Customer#000000076 5748.33 +Customer#000000079 5124.28 +Customer#000000080 7386.53 +Customer#000000082 9471.34 +Customer#000000083 6466.51 +Customer#000000085 3389.64 +Customer#000000086 3309.32 +Customer#000000088 8034.44 +Customer#000000089 1533.76 +Customer#000000091 4646.14 +Customer#000000092 1185.91 +Customer#000000094 5503.11 +Customer#000000095 5330.38 +Customer#000000097 2167.48 +Customer#000000098 -548.37 +Customer#000000100 9892.89 +Customer#000000101 7473.96 +Customer#000000103 2760.45 +Customer#000000104 -585.38 +Customer#000000106 3291.42 +Customer#000000107 2517.15 +Customer#000000109 -713.1 +Customer#000000110 7465.99 +Customer#000000112 2956.35 +Customer#000000115 7511.92 +Customer#000000116 8406.99 +Customer#000000118 3585.37 +Customer#000000121 6431.32 +Customer#000000122 7868.46 +Customer#000000127 9283.71 +Customer#000000128 -983.96 +Customer#000000130 5076.58 +Customer#000000131 8598.53 +Customer#000000133 2317.67 +Customer#000000134 4611.9 +Customer#000000136 -839.39 +Customer#000000137 7841.3 +Customer#000000139 7900.78 +Customer#000000140 9966.15 +Customer#000000142 2212.81 +Customer#000000143 2189.5 +Customer#000000145 9751.93 +Customer#000000148 2138.6 +Customer#000000149 8962.65 +call p(7); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 721.56 +Customer#000000002 131.65 +Customer#000000005 804.47 +Customer#000000007 9571.95 +Customer#000000008 6829.74 +Customer#000000010 2763.54 +Customer#000000011 -262.6 +Customer#000000013 3867.34 +Customer#000000014 5276.3 +Customer#000000016 4691.03 +Customer#000000017 16.34 +Customer#000000019 8924.71 +Customer#000000022 601.98 +Customer#000000023 3342.02 +Customer#000000025 7143.7 +Customer#000000028 1017.1799999999998 +Customer#000000029 7628.27 +Customer#000000031 5246.89 +Customer#000000032 3481.53 +Customer#000000034 8599.7 +Customer#000000035 1238.24 +Customer#000000037 -907.75 +Customer#000000038 6355.11 +Customer#000000040 1345.3 +Customer#000000041 280.95 +Customer#000000043 9914.28 +Customer#000000044 7325.94 +Customer#000000046 5754.59 +Customer#000000047 284.58 +Customer#000000049 4583.94 +Customer#000000052 5640.28 +Customer#000000053 4123.64 +Customer#000000055 4582.11 +Customer#000000056 6540.86 +Customer#000000058 6488.46 +Customer#000000059 3468.6 +Customer#000000061 1546.24 +Customer#000000062 605.61 +Customer#000000064 -636.64 +Customer#000000065 8805.16 +Customer#000000067 8176.59 +Customer#000000070 4877.52 +Customer#000000071 -601.19 +Customer#000000073 4298.5 +Customer#000000074 2774.43 +Customer#000000076 5755.33 +Customer#000000079 5131.28 +Customer#000000080 7393.53 +Customer#000000082 9478.34 +Customer#000000083 6473.51 +Customer#000000085 3396.64 +Customer#000000086 3316.32 +Customer#000000088 8041.44 +Customer#000000089 1540.76 +Customer#000000091 4653.14 +Customer#000000092 1192.91 +Customer#000000094 5510.11 +Customer#000000095 5337.38 +Customer#000000097 2174.48 +Customer#000000098 -541.37 +Customer#000000100 9899.89 +Customer#000000101 7480.96 +Customer#000000103 2767.45 +Customer#000000104 -578.38 +Customer#000000106 3298.42 +Customer#000000107 2524.15 +Customer#000000109 -706.1 +Customer#000000110 7472.99 +Customer#000000112 2963.35 +Customer#000000115 7518.92 +Customer#000000116 8413.99 +Customer#000000118 3592.37 +Customer#000000121 6438.32 +Customer#000000122 7875.46 +Customer#000000127 9290.71 +Customer#000000128 -976.96 +Customer#000000130 5083.58 +Customer#000000131 8605.53 +Customer#000000133 2324.67 +Customer#000000134 4618.9 +Customer#000000136 -832.39 +Customer#000000137 7848.3 +Customer#000000139 7907.78 +Customer#000000140 9973.15 +Customer#000000142 2219.81 +Customer#000000143 2196.5 +Customer#000000145 9758.93 +Customer#000000148 2145.6 +Customer#000000149 8969.65 +call p(-(3+7)); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1993-03-08'); +c_name c_acctbal +Customer#000000001 711.56 +Customer#000000002 121.65 +Customer#000000005 794.47 +Customer#000000007 9561.95 +Customer#000000008 6819.74 +Customer#000000010 2753.54 +Customer#000000011 -272.6 +Customer#000000013 3857.34 +Customer#000000014 5266.3 +Customer#000000016 4681.03 +Customer#000000017 6.34 +Customer#000000019 8914.71 +Customer#000000022 591.98 +Customer#000000023 3332.02 +Customer#000000025 7133.7 +Customer#000000028 1007.1799999999998 +Customer#000000029 7618.27 +Customer#000000031 5236.89 +Customer#000000032 3471.53 +Customer#000000034 8589.7 +Customer#000000035 1228.24 +Customer#000000037 -917.75 +Customer#000000038 6345.11 +Customer#000000040 1335.3 +Customer#000000041 270.95 +Customer#000000043 9904.28 +Customer#000000044 7315.94 +Customer#000000046 5744.59 +Customer#000000047 274.58 +Customer#000000049 4573.94 +Customer#000000052 5630.28 +Customer#000000053 4113.64 +Customer#000000055 4572.11 +Customer#000000056 6530.86 +Customer#000000058 6478.46 +Customer#000000059 3458.6 +Customer#000000061 1536.24 +Customer#000000062 595.61 +Customer#000000064 -646.64 +Customer#000000065 8795.16 +Customer#000000067 8166.59 +Customer#000000070 4867.52 +Customer#000000071 -611.19 +Customer#000000073 4288.5 +Customer#000000074 2764.43 +Customer#000000076 5745.33 +Customer#000000079 5121.28 +Customer#000000080 7383.53 +Customer#000000082 9468.34 +Customer#000000083 6463.51 +Customer#000000085 3386.64 +Customer#000000086 3306.32 +Customer#000000088 8031.44 +Customer#000000089 1530.76 +Customer#000000091 4643.14 +Customer#000000092 1182.91 +Customer#000000094 5500.11 +Customer#000000095 5327.38 +Customer#000000097 2164.48 +Customer#000000098 -551.37 +Customer#000000100 9889.89 +Customer#000000101 7470.96 +Customer#000000103 2757.45 +Customer#000000104 -588.38 +Customer#000000106 3288.42 +Customer#000000107 2514.15 +Customer#000000109 -716.1 +Customer#000000110 7462.99 +Customer#000000112 2953.35 +Customer#000000115 7508.92 +Customer#000000116 8403.99 +Customer#000000118 3582.37 +Customer#000000121 6428.32 +Customer#000000122 7865.46 +Customer#000000127 9280.71 +Customer#000000128 -986.96 +Customer#000000130 5073.58 +Customer#000000131 8595.53 +Customer#000000133 2314.67 +Customer#000000134 4608.9 +Customer#000000136 -842.39 +Customer#000000137 7838.3 +Customer#000000139 7897.78 +Customer#000000140 9963.15 +Customer#000000142 2209.81 +Customer#000000143 2186.5 +Customer#000000145 9748.93 +Customer#000000148 2135.6 +Customer#000000149 8959.65 +drop procedure p; +# Materialization SJM SP +# ====================== +create procedure p(d int) +update customer set c_acctbal = c_acctbal+d where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3857.34 +Customer#000000032 3471.53 +Customer#000000037 -917.75 +Customer#000000118 3582.37 +Customer#000000056 6530.86 +call p(-1); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3856.34 +Customer#000000032 3470.53 +Customer#000000037 -918.75 +Customer#000000118 3581.37 +Customer#000000056 6529.86 +call p(-2); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3854.34 +Customer#000000032 3468.53 +Customer#000000037 -920.75 +Customer#000000118 3579.37 +Customer#000000056 6527.86 +call p(1+2); +select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders +where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); +c_name c_acctbal +Customer#000000013 3857.34 +Customer#000000032 3471.53 +Customer#000000037 -917.75 +Customer#000000118 3582.37 +Customer#000000056 6530.86 +drop procedure p; +# Checking limitations +# ==================== +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +o_orderkey o_totalprice +1221 117397.16 +324 26868.85 +1856 189361.42 +1344 43809.37 +1925 146382.71 +3139 40975.96 +4903 34363.63 +5607 24660.06 +# Should not use semi-join conversion because has ORDER BY ... LIMIT +explain +update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)) +order by o_totalprice limit 500; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY orders range i_o_orderdate i_o_orderdate 4 NULL 108 Using where; Using filesort +2 DEPENDENT SUBQUERY customer unique_subquery PRIMARY,i_c_nationkey PRIMARY 4 func 1 Using where +update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)) +order by o_totalprice limit 500; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +o_orderkey o_totalprice +1221 117347.16 +324 26818.85 +1856 189311.42 +1344 43759.37 +1925 146332.71 +3139 40925.96 +4903 34313.63 +5607 24610.06 +update orders set o_totalprice = o_totalprice+50 where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)) +order by o_totalprice limit 500; +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +o_orderkey o_totalprice +1221 117397.16 +324 26868.85 +1856 189361.42 +1344 43809.37 +1925 146382.71 +3139 40975.96 +4903 34363.63 +5607 24660.06 +# Should use semi-join converion +explain +update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY customer range PRIMARY,i_c_nationkey i_c_nationkey 5 NULL 15 Using index condition +1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 15 (7%) Using where; Using rowid filter +update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +o_orderkey o_totalprice +1221 117347.16 +324 26818.85 +1856 189311.42 +1344 43759.37 +1925 146332.71 +3139 40925.96 +4903 34313.63 +5607 24610.06 +update orders set o_totalprice = o_totalprice+50 where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and +o_custkey in (select c_custkey from customer +where c_nationkey in (1,2)); +o_orderkey o_totalprice +1221 117397.16 +324 26868.85 +1856 189361.42 +1344 43809.37 +1925 146382.71 +3139 40975.96 +4903 34363.63 +5607 24660.06 +CREATE TABLE partsupp_small ( +ps_partkey int(11) NOT NULL DEFAULT '0', +ps_suppkey int(11) NOT NULL DEFAULT '0', +ps_availqty int(11) DEFAULT NULL, +ps_supplycost double DEFAULT NULL, +ps_comment varchar(199) DEFAULT NULL, +PRIMARY KEY (ps_partkey,ps_suppkey), +KEY i_ps_partkey (ps_partkey), +KEY i_ps_suppkey (ps_suppkey) +); +create index i_ps_sup_part on partsupp_small(ps_suppkey, ps_partkey); +insert into partsupp_small select * from partsupp where ps_partkey <50; +analyze table partsupp_small persistent for all; +Table Op Msg_type Msg_text +dbt3_s001.partsupp_small analyze status Engine-independent statistics collected +dbt3_s001.partsupp_small analyze status OK +# LooseScan +# ========= +explain +select count(*) from lineitem where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY partsupp_small index PRIMARY,i_ps_partkey,i_ps_suppkey,i_ps_sup_part i_ps_sup_part 8 NULL 176 Using where; Using index; LooseScan +1 PRIMARY lineitem ref i_l_suppkey i_l_suppkey 5 dbt3_s001.partsupp_small.ps_suppkey 600 Using index +explain format=json +select count(*) from lineitem where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.776623555, + "nested_loop": [ + { + "table": { + "table_name": "partsupp_small", + "access_type": "index", + "possible_keys": [ + "PRIMARY", + "i_ps_partkey", + "i_ps_suppkey", + "i_ps_sup_part" + ], + "key": "i_ps_sup_part", + "key_length": "8", + "used_key_parts": ["ps_suppkey", "ps_partkey"], + "loops": 1, + "rows": 176, + "cost": 0.019403477, + "filtered": 5.113636494, + "attached_condition": "partsupp_small.ps_partkey in (1,2,3)", + "using_index": true, + "loose_scan": true + } + }, + { + "table": { + "table_name": "lineitem", + "access_type": "ref", + "possible_keys": ["i_l_suppkey"], + "key": "i_l_suppkey", + "key_length": "5", + "used_key_parts": ["l_suppkey"], + "ref": ["dbt3_s001.partsupp_small.ps_suppkey"], + "loops": 9, + "rows": 600, + "cost": 0.757220078, + "filtered": 11.11111069, + "using_index": true + } + } + ] + } +} +select count(*) from lineitem where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +count(*) +5373 +select 5373 as count, 136458704.22 as old_sum; +count old_sum +5373 136458704.22 +explain +update lineitem set l_extendedprice=l_extendedprice+10 where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY lineitem ALL i_l_suppkey NULL NULL NULL 6005 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED partsupp_small range PRIMARY,i_ps_partkey,i_ps_suppkey,i_ps_sup_part PRIMARY 4 NULL 9 Using where; Using index +explain format=json +update lineitem set l_extendedprice=l_extendedprice+10 where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 2.191459679, + "nested_loop": [ + { + "table": { + "table_name": "lineitem", + "access_type": "ALL", + "possible_keys": ["i_l_suppkey"], + "loops": 1, + "rows": 6005, + "cost": 0.988432825, + "filtered": 100 + } + }, + { + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "4", + "used_key_parts": ["ps_suppkey"], + "ref": ["func"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "nested_loop": [ + { + "table": { + "table_name": "partsupp_small", + "access_type": "range", + "possible_keys": [ + "PRIMARY", + "i_ps_partkey", + "i_ps_suppkey", + "i_ps_sup_part" + ], + "key": "PRIMARY", + "key_length": "4", + "used_key_parts": ["ps_partkey"], + "loops": 1, + "rows": 9, + "cost": 0.003756598, + "filtered": 100, + "attached_condition": "partsupp_small.ps_partkey in (1,2,3)", + "using_index": true + } + } + ] + } + } + } + } + ] + } +} +update lineitem set l_extendedprice=l_extendedprice+10 where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +select ROUND(sum(l_extendedprice),2), 5373 as count, +(136458704.22+10*5373) as 'old_sum+10*count' + from lineitem where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +ROUND(sum(l_extendedprice),2) count old_sum+10*count +136512434.22 5373 136512434.22 +update lineitem set l_extendedprice=l_extendedprice-10 where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +select ROUND(sum(l_extendedprice),2), 5373 as count, +136458704.22 as old_sum from lineitem where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +ROUND(sum(l_extendedprice),2) count old_sum +136458704.22 5373 136458704.22 +# LooseScan PS +# ============ +prepare stmt from " +update lineitem set l_extendedprice=l_extendedprice+? where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +"; +select 5373 as count, 136458704.22 as old_sum; +count old_sum +5373 136458704.22 +set @a1=20; +execute stmt using @a1; +select ROUND(sum(l_extendedprice),2), 5373 as count, +(136458704.22+20*5373) as 'old_sum+20*count' + from lineitem where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +ROUND(sum(l_extendedprice),2) count old_sum+20*count +136566164.22 5373 136566164.22 +set @a2=10; +execute stmt using @a2; +select ROUND(sum(l_extendedprice),2), 5373 as count, +(136458704.22+30*5373) as 'old_sum+30*count' + from lineitem where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +ROUND(sum(l_extendedprice),2) count old_sum+30*count +136619894.22 5373 136619894.22 +execute stmt using -(@a1+@a2); +select ROUND(sum(l_extendedprice),2), 5373 as count, +136458704.22 as old_sum from lineitem where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +ROUND(sum(l_extendedprice),2) count old_sum +136458704.22 5373 136458704.22 +deallocate prepare stmt; +# LooseScan SP +# ============ +create procedure p(d int) +update lineitem set l_extendedprice=l_extendedprice+d where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +select 5373 as count, 136458704.22 as old_sum; +count old_sum +5373 136458704.22 +call p(10); +select ROUND(sum(l_extendedprice),2), 5373 as count, +(136458704.22+10*5373) as 'old_sum+10*count' + from lineitem where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +ROUND(sum(l_extendedprice),2) count old_sum+10*count +136512434.22 5373 136512434.22 +call p(20); +select ROUND(sum(l_extendedprice),2), 5373 as count, +(136458704.22+30*5373) as 'old_sum+30*count' + from lineitem where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +ROUND(sum(l_extendedprice),2) count old_sum+30*count +136619894.22 5373 136619894.22 +call p(-(10+20)); +select ROUND(sum(l_extendedprice),2), 5373 as count, +136458704.22 as old_sum from lineitem where l_suppkey in +(select ps_suppkey from partsupp_small +where ps_partkey in (1,2,3)); +ROUND(sum(l_extendedprice),2) count old_sum +136458704.22 5373 136458704.22 +drop procedure p; +# DuplicateWeedout +# ================ +set @tmp_optimizer_switch= @@optimizer_switch; +set optimizer_switch='materialization=off'; +analyze table lineitem; +Table Op Msg_type Msg_text +dbt3_s001.lineitem analyze status Engine-independent statistics collected +dbt3_s001.lineitem analyze status OK +analyze table orders; +Table Op Msg_type Msg_text +dbt3_s001.orders analyze status Engine-independent statistics collected +dbt3_s001.orders analyze status OK +explain +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY supplier range PRIMARY PRIMARY 4 NULL 1 Using where; Using index; Start temporary +1 PRIMARY partsupp_small ref PRIMARY,i_ps_partkey,i_ps_suppkey,i_ps_sup_part i_ps_sup_part 4 dbt3_s001.supplier.s_suppkey 17 Using where; Using index +1 PRIMARY lineitem ref i_l_suppkey_partkey,i_l_partkey i_l_suppkey_partkey 5 dbt3_s001.partsupp_small.ps_partkey 30 Using index +1 PRIMARY lineitem ref i_l_suppkey_partkey,i_l_partkey i_l_partkey 5 dbt3_s001.partsupp_small.ps_partkey 30 Using index; End temporary +explain format=json +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 4.129940741, + "nested_loop": [ + { + "duplicates_removal": [ + { + "table": { + "table_name": "supplier", + "access_type": "range", + "possible_keys": ["PRIMARY"], + "key": "PRIMARY", + "key_length": "4", + "used_key_parts": ["s_suppkey"], + "loops": 1, + "rows": 1, + "cost": 0.001478954, + "filtered": 100, + "attached_condition": "supplier.s_suppkey < 2", + "using_index": true + } + }, + { + "table": { + "table_name": "partsupp_small", + "access_type": "ref", + "possible_keys": [ + "PRIMARY", + "i_ps_partkey", + "i_ps_suppkey", + "i_ps_sup_part" + ], + "key": "i_ps_sup_part", + "key_length": "4", + "used_key_parts": ["ps_suppkey"], + "ref": ["dbt3_s001.supplier.s_suppkey"], + "loops": 1, + "rows": 17, + "cost": 0.003160332, + "filtered": 79.54545593, + "attached_condition": "partsupp_small.ps_partkey is not null", + "using_index": true + } + }, + { + "table": { + "table_name": "lineitem", + "access_type": "ref", + "possible_keys": ["i_l_suppkey_partkey", "i_l_partkey"], + "key": "i_l_suppkey_partkey", + "key_length": "5", + "used_key_parts": ["l_partkey"], + "ref": ["dbt3_s001.partsupp_small.ps_partkey"], + "loops": 14, + "rows": 30, + "cost": 0.069152188, + "filtered": 100, + "using_index": true + } + }, + { + "table": { + "table_name": "lineitem", + "access_type": "ref", + "possible_keys": ["i_l_suppkey_partkey", "i_l_partkey"], + "key": "i_l_partkey", + "key_length": "5", + "used_key_parts": ["l_partkey"], + "ref": ["dbt3_s001.partsupp_small.ps_partkey"], + "loops": 420.35, + "rows": 30, + "cost": 1.994712365, + "filtered": 0.237896994, + "using_index": true + } + } + ] + } + ] + } +} +select count(*) from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +count(*) +471 +select 471 as count, 10751458.66 as old_sum; +count old_sum +471 10751458.66 +explain +update lineitem set l_extendedprice=l_extendedprice+10 where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY supplier range PRIMARY PRIMARY 4 NULL 1 Using where; Using index; Start temporary +1 PRIMARY partsupp_small ref PRIMARY,i_ps_partkey,i_ps_suppkey,i_ps_sup_part i_ps_sup_part 4 dbt3_s001.supplier.s_suppkey 17 Using where; Using index +1 PRIMARY lineitem ref i_l_suppkey_partkey,i_l_partkey i_l_suppkey_partkey 5 dbt3_s001.partsupp_small.ps_partkey 30 +1 PRIMARY lineitem ref i_l_suppkey_partkey,i_l_partkey i_l_partkey 5 dbt3_s001.partsupp_small.ps_partkey 30 Using index; End temporary +explain format=json +update lineitem set l_extendedprice=l_extendedprice+10 where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 4.590092321, + "nested_loop": [ + { + "duplicates_removal": [ + { + "table": { + "table_name": "supplier", + "access_type": "range", + "possible_keys": ["PRIMARY"], + "key": "PRIMARY", + "key_length": "4", + "used_key_parts": ["s_suppkey"], + "loops": 1, + "rows": 1, + "cost": 0.001478954, + "filtered": 100, + "attached_condition": "supplier.s_suppkey < 2", + "using_index": true + } + }, + { + "table": { + "table_name": "partsupp_small", + "access_type": "ref", + "possible_keys": [ + "PRIMARY", + "i_ps_partkey", + "i_ps_suppkey", + "i_ps_sup_part" + ], + "key": "i_ps_sup_part", + "key_length": "4", + "used_key_parts": ["ps_suppkey"], + "ref": ["dbt3_s001.supplier.s_suppkey"], + "loops": 1, + "rows": 17, + "cost": 0.003160332, + "filtered": 79.54545593, + "attached_condition": "partsupp_small.ps_partkey is not null", + "using_index": true + } + }, + { + "table": { + "table_name": "lineitem", + "access_type": "ref", + "possible_keys": ["i_l_suppkey_partkey", "i_l_partkey"], + "key": "i_l_suppkey_partkey", + "key_length": "5", + "used_key_parts": ["l_partkey"], + "ref": ["dbt3_s001.partsupp_small.ps_partkey"], + "loops": 14, + "rows": 30, + "cost": 0.529303768, + "filtered": 100 + } + }, + { + "table": { + "table_name": "lineitem", + "access_type": "ref", + "possible_keys": ["i_l_suppkey_partkey", "i_l_partkey"], + "key": "i_l_partkey", + "key_length": "5", + "used_key_parts": ["l_partkey"], + "ref": ["dbt3_s001.partsupp_small.ps_partkey"], + "loops": 420.35, + "rows": 30, + "cost": 1.994712365, + "filtered": 0.237896994, + "using_index": true + } + } + ] + } + ] + } +} +update lineitem set l_extendedprice=l_extendedprice+10 where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +select ROUND(sum(l_extendedprice),2), 471 as count, +(10751458.66+10*471) as 'old_sum+10*count' + from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +ROUND(sum(l_extendedprice),2) count old_sum+10*count +10756168.66 471 10756168.66 +update lineitem set l_extendedprice=l_extendedprice-10 where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +select ROUND(sum(l_extendedprice),2), 471 as count, +10751458.66 as old_sum from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +ROUND(sum(l_extendedprice),2) count old_sum +10751458.66 471 10751458.66 +# DuplicateWeedout PS +# =================== +prepare stmt from " +update lineitem set l_extendedprice=l_extendedprice+? where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +"; +select 471 as count, 10751458.66 as old_sum; +count old_sum +471 10751458.66 +set @a1=20; +execute stmt using @a1; +select ROUND(sum(l_extendedprice),2), 471 as count, +(10751458.66+20*471) as 'old_sum+20*count' + from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +ROUND(sum(l_extendedprice),2) count old_sum+20*count +10760878.66 471 10760878.66 +set @a2=10; +execute stmt using @a2; +select ROUND(sum(l_extendedprice),2), 471 as count, +(10751458.66+30*471) as 'old_sum+30*count' + from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +ROUND(sum(l_extendedprice),2) count old_sum+30*count +10765588.66 471 10765588.66 +execute stmt using -(@a1+@a2); +select ROUND(sum(l_extendedprice),2), 471 as count, +10751458.66 as old_sum from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +ROUND(sum(l_extendedprice),2) count old_sum +10751458.66 471 10751458.66 +deallocate prepare stmt; +# DuplicateWeedout SP +# =================== +create procedure p(d int) +update lineitem set l_extendedprice=l_extendedprice+d where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +select 471 as count, 10751458.66 as old_sum; +count old_sum +471 10751458.66 +call p(10); +select ROUND(sum(l_extendedprice),2), 471 as count, +(10751458.66+10*471) as 'old_sum+10*count' + from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +ROUND(sum(l_extendedprice),2) count old_sum+10*count +10756168.66 471 10756168.66 +call p(20); +select ROUND(sum(l_extendedprice),2), 471 as count, +(10751458.66+30*471) as 'old_sum+30*count' + from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +ROUND(sum(l_extendedprice),2) count old_sum+30*count +10765588.66 471 10765588.66 +call p(-(10+20)); +select ROUND(sum(l_extendedprice),2), 471 as count, +10751458.66 as old_sum from lineitem where l_partkey in ( +select ps_partkey +from partsupp_small join lineitem on ps_partkey=l_partkey +where ps_suppkey in ( +select s_suppkey from supplier where s_suppkey < 2 +) +); +ROUND(sum(l_extendedprice),2) count old_sum +10751458.66 471 10751458.66 +drop procedure p; +set @@optimizer_switch=@tmp_optimizer_switch; +drop table partsupp_small; +DROP DATABASE dbt3_s001; diff --git a/mysql-test/main/update_single_to_multi.test b/mysql-test/main/update_single_to_multi.test new file mode 100644 index 00000000000..7364806e65d --- /dev/null +++ b/mysql-test/main/update_single_to_multi.test @@ -0,0 +1,832 @@ +--disable_warnings +DROP DATABASE IF EXISTS dbt3_s001; +--enable_warnings + +CREATE DATABASE dbt3_s001; + +use dbt3_s001; + +--disable_query_log +--disable_result_log +--disable_warnings +--source include/dbt3_s001.inc +--enable_warnings +--enable_result_log +--enable_query_log + +create index i_n_name on nation(n_name); +analyze table + nation, lineitem, customer, orders, part, supplier, partsupp, region +persistent for all; + +--echo # Pullout +--echo # ======= + +let $c1= + o_orderDATE between '1992-01-01' and '1992-06-30' and + o_custkey in (select c_custkey from customer + where c_nationkey in (select n_nationkey from nation + where n_name='PERU')); + +eval +explain +select o_orderkey, o_totalprice from orders where $c1; +eval +explain format=json +select o_orderkey, o_totalprice from orders where $c1; +eval +select o_orderkey, o_totalprice from orders where $c1; + +eval +explain +update orders set o_totalprice = o_totalprice-50 where $c1; +eval +explain format=json +update orders set o_totalprice = o_totalprice-50 where $c1; +eval +update orders set o_totalprice = o_totalprice-50 where $c1; +eval +select o_orderkey, o_totalprice from orders where $c1; + +eval +update orders set o_totalprice= o_totalprice+50 where $c1; +eval +select o_orderkey, o_totalprice from orders where $c1; + + +let $c2= + (ps_partkey, ps_suppkey) in + (select p_partkey, s_suppkey from part, supplier + where p_retailprice between 901 and 910 and + s_nationkey in (select n_nationkey from nation + where n_name='PERU')); + +eval +explain +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2; +eval +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2; + +eval +explain +update partsupp set ps_supplycost = ps_supplycost+2 where $c2; +eval +update partsupp set ps_supplycost = ps_supplycost+2 where $c2; +eval +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2; + +eval +update partsupp set ps_supplycost = ps_supplycost-2 where $c2; +eval +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2; + + +let $c3= + ps_partkey in (select p_partkey from part + where p_retailprice between 901 and 910) and + ps_suppkey in (select s_suppkey from supplier + where s_nationkey in (select n_nationkey from nation + where n_name='PERU')); +eval +explain +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3; +eval +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3; + +eval +explain +update partsupp set ps_supplycost = ps_supplycost+10 where $c3; +eval +update partsupp set ps_supplycost = ps_supplycost+10 where $c3; +eval +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3; + +eval +update partsupp set ps_supplycost = ps_supplycost-10 where $c3; +eval +select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3; + + +let $c4= + l_orderkey in (select o_orderkey from orders + where o_custkey in + (select c_custkey from customer + where c_nationkey in + (select n_nationkey from nation + where n_name='PERU')) + and + o_orderDATE between '1992-06-30' and '1992-12-31') + and + (l_partkey, l_suppkey) in + (select p_partkey, s_suppkey from part, supplier + where p_retailprice between 901 and 1000 and + s_nationkey in (select n_nationkey from nation + where n_name='PERU')); + +eval +explain +select l_orderkey, l_linenumber, l_tax from lineitem where $c4; +eval +select l_orderkey, l_linenumber, l_tax from lineitem where $c4; + +eval +explain +update lineitem set l_tax = (l_tax*100+1)/100 where $c4; +eval +update lineitem set l_tax = (l_tax*100+1)/100 where $c4; +eval +select l_orderkey, l_linenumber, l_tax from lineitem where $c4; + +eval +update lineitem set l_tax = (l_tax*100-1)/100 where $c4; +eval +select l_orderkey, l_linenumber, l_tax from lineitem where $c4; + + +--echo # FirstMatch +--echo # ========== + +set optimizer_switch='materialization=off'; + +let $c5= + c_nationkey in (select n_nationkey from nation + where n_regionkey in (1,2)) + and + c_custkey in (select o_custkey from orders + where o_orderDATE between '1992-10-09' and '1993-06-08'); + +eval +explain +select c_name, c_acctbal from customer where $c5; +eval +explain format=json +select c_name, c_acctbal from customer where $c5; +eval +select c_name, c_acctbal from customer where $c5; + +eval +explain +update customer set c_acctbal = c_acctbal+10 where $c5; +eval +explain format=json +update customer set c_acctbal = c_acctbal+10 where $c5; +eval +update customer set c_acctbal = c_acctbal+10 where $c5; +eval +select c_name, c_acctbal from customer where $c5; + +eval +update customer set c_acctbal = c_acctbal-10 where $c5; +eval +select c_name, c_acctbal from customer where $c5; + +set optimizer_switch='materialization=default'; + +let $c6= + c_nationkey in (select n_nationkey from nation where n_name='PERU') + and + c_custkey in (select o_custkey from orders + where o_orderDATE between "1992-01-09" and "1993-01-08"); + +eval +explain +select c_name, c_acctbal from customer where $c6; +eval +select c_name, c_acctbal from customer where $c6; + +eval +explain +update customer set c_acctbal = c_acctbal+20 where $c6; +eval +update customer set c_acctbal = c_acctbal+20 where $c6; +eval +select c_name, c_acctbal from customer where $c6; + +eval +update customer set c_acctbal = c_acctbal-20 where $c6; +eval +select c_name, c_acctbal from customer where $c6; + +--echo # Materialization +--echo # =============== + +set optimizer_switch='firstmatch=off'; + +let $c7= + c_nationkey in (select n_nationkey from nation where + n_name in ('JAPAN', 'INDONESIA', 'PERU', 'ARGENTINA')) + and + c_custkey in (select o_custkey from orders + where o_orderDATE between "1992-01-09" and "1995-01-08"); + +eval +explain +select c_name, c_acctbal from customer where $c7; +eval +select c_name, c_acctbal from customer where $c7; + +eval +explain +update customer set c_acctbal = c_acctbal+20 where $c7; +eval +update customer set c_acctbal = c_acctbal+20 where $c7; +eval +select c_name, c_acctbal from customer where $c7; + +eval +update customer set c_acctbal = c_acctbal-20 where $c7; +eval +select c_name, c_acctbal from customer where $c7; + +set optimizer_switch='firstmatch=default'; + +let $c8= + c_custkey in (select o_custkey from orders + where o_orderDATE between '1992-01-09' and '1993-03-08'); + +eval +explain +select c_name, c_acctbal from customer where $c8; +eval +explain format=json +select c_name, c_acctbal from customer where $c8; +eval +select c_name, c_acctbal from customer where $c8; + +eval +explain +update customer set c_acctbal = c_acctbal+5 where $c8; +eval +explain format=json +update customer set c_acctbal = c_acctbal+5 where $c8; +eval +update customer set c_acctbal = c_acctbal+5 where $c8; +eval +select c_name, c_acctbal from customer where $c8; + +eval +update customer set c_acctbal = c_acctbal-5 where $c8; +eval +select c_name, c_acctbal from customer where $c8; + + +let $c9= + c_custkey in (select o_custkey from orders + where o_orderDATE between '1992-06-09' and '1993-01-08'); + +eval +explain +select c_name, c_acctbal from customer where $c9; +eval +select c_name, c_acctbal from customer where $c9; + +eval +explain +update customer set c_acctbal = c_acctbal+1 where $c9; +eval +update customer set c_acctbal = c_acctbal+1 where $c9; +eval +select c_name, c_acctbal from customer where $c9; + +eval +update customer set c_acctbal = c_acctbal-1 where $c9; +eval +select c_name, c_acctbal from customer where $c9; + + + +--echo # Materialization SJM +--echo # =================== + +let $c10= + c_custkey in (select o_custkey from orders + where o_orderDATE between '1992-01-09' and '1992-03-08' + group by o_custkey having count(o_custkey) > 1); + +eval +explain +select c_name, c_acctbal from customer where $c10; +eval +explain format=json +select c_name, c_acctbal from customer where $c10; +eval +select c_name, c_acctbal from customer where $c10; + +eval +explain +update customer set c_acctbal = c_acctbal-5 where $c10; +eval +explain format=json +update customer set c_acctbal = c_acctbal-5 where $c10; +eval +update customer set c_acctbal = c_acctbal-5 where $c10; +eval +select c_name, c_acctbal from customer where $c10; + +eval +update customer set c_acctbal = c_acctbal+5 where $c10; +eval +select c_name, c_acctbal from customer where $c10; + + +let $c11= + c_custkey in (select o_custkey from orders + where o_orderDATE between '1992-01-09' and '1993-03-08' + group by o_custkey having count(o_custkey) > 5); + +eval +explain +select c_name, c_acctbal from customer where $c11; +eval +select c_name, c_acctbal from customer where $c11; + +eval +explain +update customer set c_acctbal = c_acctbal-1 where $c11; +eval +update customer set c_acctbal = c_acctbal-1 where $c11; +eval +select c_name, c_acctbal from customer where $c11; + +eval +update customer set c_acctbal = c_acctbal+1 where $c11; +eval +select c_name, c_acctbal from customer where $c11; + + +--echo # Pullout PS +--echo # ========== + +eval +prepare stmt from " +update orders set o_totalprice = o_totalprice+? where $c1; +"; + +eval +select o_orderkey, o_totalprice from orders where $c1; +set @a1=-20; +execute stmt using @a1; +eval +select o_orderkey, o_totalprice from orders where $c1; +set @a2=-10; +execute stmt using @a2; +eval +select o_orderkey, o_totalprice from orders where $c1; +execute stmt using -(@a1+@a2); +eval +select o_orderkey, o_totalprice from orders where $c1; + +deallocate prepare stmt; + + +--echo # FirstMatch PS +--echo # ============= + +set optimizer_switch='materialization=off'; + +eval +prepare stmt from " +update customer set c_acctbal = c_acctbal+? where $c5; +"; + +eval +select c_name, c_acctbal from customer where $c5; +set @a1=15; +execute stmt using @a1; +eval +select c_name, c_acctbal from customer where $c5; +set @a2=5; +execute stmt using @a2; +eval +select c_name, c_acctbal from customer where $c5; +execute stmt using -(@a1+@a2); +eval +select c_name, c_acctbal from customer where $c5; + +deallocate prepare stmt; + +set optimizer_switch='materialization=default'; + +--echo # Materialization PS +--echo # ================== + +eval +prepare stmt from " +update customer set c_acctbal = c_acctbal+? where $c8; +"; + +eval +select c_name, c_acctbal from customer where $c8; +set @a1=7; +execute stmt using @a1; +eval +select c_name, c_acctbal from customer where $c8; +set @a2=3; +execute stmt using @a2; +eval +select c_name, c_acctbal from customer where $c8; +execute stmt using -(@a1+@a2); +eval +select c_name, c_acctbal from customer where $c8; + +deallocate prepare stmt; + + +--echo # Materialization SJM PS +--echo # ====================== + +eval +prepare stmt from " +update customer set c_acctbal = c_acctbal+? where $c10; +"; + +eval +select c_name, c_acctbal from customer where $c10; +set @a1=-2; +execute stmt using @a1; +eval +select c_name, c_acctbal from customer where $c10; +set @a2=-1; +execute stmt using @a2; +eval +select c_name, c_acctbal from customer where $c10; +execute stmt using -(@a1+@a2); +eval +select c_name, c_acctbal from customer where $c10; + +deallocate prepare stmt; + + +--echo # Pullout SP +--echo # ========== + +eval +create procedure p(d int) +update orders set o_totalprice = o_totalprice+d where $c1; + +eval +select o_orderkey, o_totalprice from orders where $c1; +call p(-10); +eval +select o_orderkey, o_totalprice from orders where $c1; +call p(-20); +eval +select o_orderkey, o_totalprice from orders where $c1; +call p(10+20); +eval +select o_orderkey, o_totalprice from orders where $c1; + +drop procedure p; + + +--echo # FirstMatch SP +--echo # ============= + +set optimizer_switch='materialization=off'; + +eval +create procedure p(d int) +update customer set c_acctbal = c_acctbal+d where $c5; + +eval +select c_name, c_acctbal from customer where $c5; +call p(5); +eval +select c_name, c_acctbal from customer where $c5; +call p(15); +eval +select c_name, c_acctbal from customer where $c5; +call p(-(5+15)); +eval +select c_name, c_acctbal from customer where $c5; + +drop procedure p; + +set optimizer_switch='materialization=default'; + + +--echo # Materialization SP +--echo # ================== + +eval +create procedure p(d int) +update customer set c_acctbal = c_acctbal+d where $c8; + +eval +select c_name, c_acctbal from customer where $c8; +call p(3); +eval +select c_name, c_acctbal from customer where $c8; +call p(7); +eval +select c_name, c_acctbal from customer where $c8; +call p(-(3+7)); +eval +select c_name, c_acctbal from customer where $c8; + +drop procedure p; + + +--echo # Materialization SJM SP +--echo # ====================== + +eval +create procedure p(d int) +update customer set c_acctbal = c_acctbal+d where $c10; + +eval +select c_name, c_acctbal from customer where $c10; +call p(-1); +eval +select c_name, c_acctbal from customer where $c10; +call p(-2); +eval +select c_name, c_acctbal from customer where $c10; +call p(1+2); +eval +select c_name, c_acctbal from customer where $c10; + +drop procedure p; + +--echo # Checking limitations +--echo # ==================== + +let $c11= + o_orderDATE between '1992-01-01' and '1992-06-30' and + o_custkey in (select c_custkey from customer + where c_nationkey in (1,2)); + +eval +select o_orderkey, o_totalprice from orders where $c11; +--echo # Should not use semi-join conversion because has ORDER BY ... LIMIT +eval +explain +update orders set o_totalprice = o_totalprice-50 where $c11 +order by o_totalprice limit 500; +eval +update orders set o_totalprice = o_totalprice-50 where $c11 +order by o_totalprice limit 500; +eval +select o_orderkey, o_totalprice from orders where $c11; +eval +update orders set o_totalprice = o_totalprice+50 where $c11 +order by o_totalprice limit 500; +eval +select o_orderkey, o_totalprice from orders where $c11; + +--echo # Should use semi-join converion +eval +explain +update orders set o_totalprice = o_totalprice-50 where $c11; +eval +update orders set o_totalprice = o_totalprice-50 where $c11; +eval +select o_orderkey, o_totalprice from orders where $c11; +eval +update orders set o_totalprice = o_totalprice+50 where $c11; +eval +select o_orderkey, o_totalprice from orders where $c11; + +CREATE TABLE partsupp_small ( + ps_partkey int(11) NOT NULL DEFAULT '0', + ps_suppkey int(11) NOT NULL DEFAULT '0', + ps_availqty int(11) DEFAULT NULL, + ps_supplycost double DEFAULT NULL, + ps_comment varchar(199) DEFAULT NULL, + PRIMARY KEY (ps_partkey,ps_suppkey), + KEY i_ps_partkey (ps_partkey), + KEY i_ps_suppkey (ps_suppkey) +); + +create index i_ps_sup_part on partsupp_small(ps_suppkey, ps_partkey); +insert into partsupp_small select * from partsupp where ps_partkey <50; +analyze table partsupp_small persistent for all; + +--echo # LooseScan +--echo # ========= + +let $c12 = l_suppkey in + (select ps_suppkey from partsupp_small + where ps_partkey in (1,2,3)); + +eval +explain +select count(*) from lineitem where $c12; +eval +explain format=json +select count(*) from lineitem where $c12; +eval +select count(*) from lineitem where $c12; +let $l_count = + query_get_value('select count(*) as a from lineitem where $c12;', a, 1); +let $l_old_sum = + query_get_value('select ROUND(sum(l_extendedprice),2) as a + from lineitem where $c12;', a, 1 + ); +eval select $l_count as count, $l_old_sum as old_sum; + +eval +explain +update lineitem set l_extendedprice=l_extendedprice+10 where $c12; +eval +explain format=json +update lineitem set l_extendedprice=l_extendedprice+10 where $c12; +eval +update lineitem set l_extendedprice=l_extendedprice+10 where $c12; +eval +select ROUND(sum(l_extendedprice),2), $l_count as count, + ($l_old_sum+10*$l_count) as 'old_sum+10*count' + from lineitem where $c12; + +eval +update lineitem set l_extendedprice=l_extendedprice-10 where $c12; +eval +select ROUND(sum(l_extendedprice),2), $l_count as count, + $l_old_sum as old_sum from lineitem where $c12; + + +--echo # LooseScan PS +--echo # ============ + +eval +prepare stmt from " +update lineitem set l_extendedprice=l_extendedprice+? where $c12; +"; + +let $l_count = query_get_value('select count(*) as a + from lineitem where $c12;', a, 1 ); +let $l_old_sum = query_get_value('select ROUND(sum(l_extendedprice),2) as a + from lineitem where $c12;', a, 1 ); +eval select $l_count as count, $l_old_sum as old_sum; +eval +set @a1=20; +execute stmt using @a1; +eval +select ROUND(sum(l_extendedprice),2), $l_count as count, + ($l_old_sum+20*$l_count) as 'old_sum+20*count' + from lineitem where $c12; +set @a2=10; +execute stmt using @a2; +eval +select ROUND(sum(l_extendedprice),2), $l_count as count, + ($l_old_sum+30*$l_count) as 'old_sum+30*count' + from lineitem where $c12; +execute stmt using -(@a1+@a2); +eval +select ROUND(sum(l_extendedprice),2), $l_count as count, + $l_old_sum as old_sum from lineitem where $c12; + +deallocate prepare stmt; + +--echo # LooseScan SP +--echo # ============ + +eval +create procedure p(d int) +update lineitem set l_extendedprice=l_extendedprice+d where $c12; + +let $l_count = query_get_value('select count(*) as a + from lineitem where $c12;', a, 1 ); +let $l_old_sum = query_get_value('select ROUND(sum(l_extendedprice),2) as a + from lineitem where $c12;', a, 1 ); +eval select $l_count as count, $l_old_sum as old_sum; +eval +call p(10); +eval +select ROUND(sum(l_extendedprice),2), $l_count as count, + ($l_old_sum+10*$l_count) as 'old_sum+10*count' + from lineitem where $c12; +call p(20); +eval +select ROUND(sum(l_extendedprice),2), $l_count as count, + ($l_old_sum+30*$l_count) as 'old_sum+30*count' + from lineitem where $c12; +call p(-(10+20)); +eval +select ROUND(sum(l_extendedprice),2), $l_count as count, + $l_old_sum as old_sum from lineitem where $c12; + +drop procedure p; + +--echo # DuplicateWeedout +--echo # ================ + +set @tmp_optimizer_switch= @@optimizer_switch; +set optimizer_switch='materialization=off'; + +analyze table lineitem; +analyze table orders; + +let $c13 = l_partkey in ( + select ps_partkey + from partsupp_small join lineitem on ps_partkey=l_partkey + where ps_suppkey in ( + select s_suppkey from supplier where s_suppkey < 2 + ) +); + +eval +explain +select count(*) from lineitem where $c13; +eval +explain format=json +select count(*) from lineitem where $c13; +eval +select count(*) from lineitem where $c13; + +let $l_count = query_get_value('select count(*) as a + from lineitem where $c13;', a, 1 ); +let $l_old_sum = query_get_value('select ROUND(sum(l_extendedprice),2) as a + from lineitem where $c13;', a, 1 ); +eval select $l_count as count, $l_old_sum as old_sum; + +eval +explain +update lineitem set l_extendedprice=l_extendedprice+10 where $c13; +eval +explain format=json +update lineitem set l_extendedprice=l_extendedprice+10 where $c13; +eval +update lineitem set l_extendedprice=l_extendedprice+10 where $c13; +eval +select ROUND(sum(l_extendedprice),2), $l_count as count, + ($l_old_sum+10*$l_count) as 'old_sum+10*count' + from lineitem where $c13; + +eval +update lineitem set l_extendedprice=l_extendedprice-10 where $c13; +eval +select ROUND(sum(l_extendedprice),2), $l_count as count, + $l_old_sum as old_sum from lineitem where $c13; + + +--echo # DuplicateWeedout PS +--echo # =================== + +eval +prepare stmt from " +update lineitem set l_extendedprice=l_extendedprice+? where $c13; +"; + +let $l_count = + query_get_value('select count(*) as a + from lineitem where $c13;', a, 1 ); +let $l_old_sum = + query_get_value('select ROUND(sum(l_extendedprice),2) as a + from lineitem where $c13;', a, 1); +eval select $l_count as count, $l_old_sum as old_sum; +eval +set @a1=20; +execute stmt using @a1; +eval +select ROUND(sum(l_extendedprice),2), $l_count as count, + ($l_old_sum+20*$l_count) as 'old_sum+20*count' + from lineitem where $c13; +set @a2=10; +execute stmt using @a2; +eval +select ROUND(sum(l_extendedprice),2), $l_count as count, + ($l_old_sum+30*$l_count) as 'old_sum+30*count' + from lineitem where $c13; +execute stmt using -(@a1+@a2); +eval +select ROUND(sum(l_extendedprice),2), $l_count as count, + $l_old_sum as old_sum from lineitem where $c13; + +deallocate prepare stmt; + +--echo # DuplicateWeedout SP +--echo # =================== + +eval +create procedure p(d int) +update lineitem set l_extendedprice=l_extendedprice+d where $c13; + +let $l_count = query_get_value('select count(*) as a + from lineitem where $c13;', a, 1 ); +let $l_old_sum = query_get_value('select ROUND(sum(l_extendedprice),2) as a + from lineitem where $c13;', a, 1 ); +eval select $l_count as count, $l_old_sum as old_sum; +eval +call p(10); + +eval +select ROUND(sum(l_extendedprice),2), $l_count as count, + ($l_old_sum+10*$l_count) as 'old_sum+10*count' + from lineitem where $c13; +call p(20); +eval +select ROUND(sum(l_extendedprice),2), $l_count as count, + ($l_old_sum+30*$l_count) as 'old_sum+30*count' + from lineitem where $c13; +call p(-(10+20)); +eval +select ROUND(sum(l_extendedprice),2), $l_count as count, + $l_old_sum as old_sum from lineitem where $c13; + +drop procedure p; +set @@optimizer_switch=@tmp_optimizer_switch; + +drop table partsupp_small; + +DROP DATABASE dbt3_s001; diff --git a/mysql-test/main/update_use_source.result b/mysql-test/main/update_use_source.result index d61bff04e0d..d756775226c 100644 --- a/mysql-test/main/update_use_source.result +++ b/mysql-test/main/update_use_source.result @@ -1,4 +1,16 @@ -create table t1 (old_c1 integer, old_c2 integer,c1 integer, c2 integer, c3 integer) engine=InnoDB STATS_PERSISTENT=0; +set @save_default_engine=@@default_storage_engine; +####################################### +# # +# Engine InnoDB # +# # +####################################### +set global innodb_stats_persistent=1; +set default_storage_engine=InnoDB; +create table t1 (old_c1 integer, +old_c2 integer, +c1 integer, +c2 integer, +c3 integer); create view v1 as select * from t1 where c2=2; create trigger trg_t1 before update on t1 for each row begin @@ -6,37 +18,39 @@ set new.old_c1=old.c1; set new.old_c2=old.c2; end; / -insert into t1(c1,c2,c3) values (1,1,1); -insert into t1(c1,c2,c3) values (1,2,2); -insert into t1(c1,c2,c3) values (1,3,3); -insert into t1(c1,c2,c3) values (2,1,4); -insert into t1(c1,c2,c3) values (2,2,5); -insert into t1(c1,c2,c3) values (2,3,6); -insert into t1(c1,c2,c3) values (2,4,7); -insert into t1(c1,c2,c3) values (2,5,8); -commit; -select * from t1; -old_c1 old_c2 c1 c2 c3 -NULL NULL 1 1 1 -NULL NULL 1 2 2 -NULL NULL 1 3 3 -NULL NULL 2 1 4 -NULL NULL 2 2 5 -NULL NULL 2 3 6 -NULL NULL 2 4 7 -NULL NULL 2 5 8 -Test without any index -# -# Update a with value from subquery on the same table, no search clause. ALL access -# -start transaction; -update t1 -set c1=(select a.c3 -from t1 a -where a.c3 = t1.c3); -affected rows: 8 -info: Rows matched: 8 Changed: 8 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; +insert into t1(c1,c2,c3) +values (1,1,1), (1,2,2), (1,3,3), +(2,1,4), (2,2,5), (2,3,6), +(2,4,7), (2,5,8); +insert into t1 select NULL, NULL, c1+10,c2,c3+10 from t1; +insert into t1 select NULL, NULL, c1+20,c2+1,c3+20 from t1; +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 +create table tmp as select * from t1; +####################################### +# Test without any index # +####################################### +# +# Update with value from subquery on the same table +# +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 +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed 1->1 1 1->2 2 * @@ -46,20 +60,56 @@ concat(old_c1,'->',c1) c3 Changed 2->6 6 * 2->7 7 * 2->8 8 * -rollback; +11->11 11 +11->12 12 * +11->13 13 * +12->14 14 * +12->15 15 * +12->16 16 * +12->17 17 * +12->18 18 * +21->21 21 +21->22 22 * +21->23 23 * +22->24 24 * +22->25 25 * +22->26 26 * +22->27 27 * +22->28 28 * +31->31 31 +31->32 32 * +31->33 33 * +32->34 34 * +32->35 35 * +32->36 36 * +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; # -# Update with search clause on the same table +# Update with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition # -start transaction; -update t1 -set c1=10 -where c1 <2 -and exists (select 'X' - from t1 a -where a.c1 = t1.c1); +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 +explain select * from t1 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); affected rows: 3 info: Rows matched: 3 Changed: 3 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed 1->10 1 * 1->10 2 * @@ -69,19 +119,55 @@ NULL 5 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# Update via RANGE or INDEX access if an index or a primary key exists +# Update with EXISTS subquery over the updated table +# in WHERE + non-sargable condition # -explain update t1 set c1=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 > 3; +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where -1 PRIMARY a ALL NULL NULL NULL NULL 8 Using where; FirstMatch(t1) -start transaction; +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; -affected rows: 4 -info: Rows matched: 4 Changed: 4 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 NULL 2 @@ -91,13 +177,57 @@ NULL 5 2->12 6 * 2->12 7 * 2->12 8 * -rollback; +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; # # Update with order by # -start transaction; -update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3 order by c2; -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 NULL 2 @@ -107,18 +237,54 @@ NULL 5 2->12 6 * 2->12 7 * 2->12 8 * -rollback; +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; # -Update using a view in subquery +# Update with a reference to view in subquery +# in settable value # -start transaction; -update t1 -set c1=c1 +(select max(a.c2) -from v1 a -where a.c1 = t1.c1) ; -affected rows: 8 -info: Rows matched: 8 Changed: 8 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +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 +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed 1->3 1 * 1->3 2 * @@ -128,19 +294,53 @@ concat(old_c1,'->',c1) c3 Changed 2->4 6 * 2->4 7 * 2->4 8 * -rollback; +11->13 11 * +11->13 12 * +11->13 13 * +12->14 14 * +12->14 15 * +12->14 16 * +12->14 17 * +12->14 18 * +21->23 21 * +21->23 22 * +21->23 23 * +22->24 24 * +22->24 25 * +22->24 26 * +22->24 27 * +22->24 28 * +31->33 31 * +31->33 32 * +31->33 33 * +32->34 34 * +32->34 35 * +32->34 36 * +32->34 37 * +32->34 38 * +truncate table t1; +insert into t1 select * from tmp; # -# Update throw a view +# Update view # -start transaction; -update v1 -set c1=c1 + (select max(a.c2) -from t1 a -where a.c1 = v1.c1) +10 -where c3 > 3; -affected rows: 1 -info: Rows matched: 1 Changed: 1 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +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 +explain select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using where +explain update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +affected rows: 7 +info: Rows matched: 7 Changed: 7 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 NULL 2 @@ -150,20 +350,55 @@ NULL 4 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +11->24 12 * +NULL 13 +NULL 14 +12->27 15 * +NULL 16 +NULL 17 +NULL 18 +21->35 21 * +NULL 22 +NULL 23 +22->38 24 * +NULL 25 +NULL 26 +NULL 27 +NULL 28 +31->45 31 * +NULL 32 +NULL 33 +32->48 34 * +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# Update through a view and using the view in subquery +# Update view with reference to the same view in subquery # -start transaction; -update v1 -set c1=c1 + 1 -where c1 <2 -and exists (select 'X' - from v1 a -where a.c1 = v1.c1); +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 +explain select * from v1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); affected rows: 1 info: Rows matched: 1 Changed: 1 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 1->2 2 * @@ -173,22 +408,57 @@ NULL 5 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# Update through a view and using the view in subquery +# Update view with EXISTS and reference to the same view in subquery # -start transaction; +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 +explain select * from v1 where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where update v1 -set c1=(select max(a.c1)+10 -from v1 a -where a.c1 = v1.c1) -where c1 <10 -and exists (select 'X' - from v1 a -where a.c2 = v1.c2); +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); affected rows: 2 info: Rows matched: 2 Changed: 2 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 1->11 2 * @@ -198,41 +468,107 @@ NULL 4 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# Update of the index or primary key (c3) +# Update with IN predicand over the updated table in WHERE # -start transaction; -explain update t1 set c3=c3+10 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +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 +explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 8 -1 PRIMARY a ALL NULL NULL NULL NULL 8 Using where; FirstMatch(t1) -update t1 set c3=c3+10 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); -affected rows: 8 -info: Rows matched: 8 Changed: 8 Warnings: 0 +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 select c3 from t1; c3 -11 -12 -13 -14 -15 -16 -17 -18 -rollback; -# -# update with a limit -# -start transaction; +111 +112 +113 +114 +115 +116 +117 +118 +121 +122 +123 +124 +125 +126 +127 +128 +131 +132 +133 +134 +135 +136 +137 +138 +141 +142 +143 +144 +145 +146 +147 +148 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit +# +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 +explain select * from t1 limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where update t1 -set c1=(select a.c3 -from t1 a -where a.c3 = t1.c3) -limit 2; +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; affected rows: 2 info: Rows matched: 2 Changed: 2 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed 1->1 1 1->2 2 * @@ -242,19 +578,55 @@ NULL 5 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# update with a limit and an order by +# Update with a limit and an order by # -start transaction; +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 +explain select * from t1 order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using filesort +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where update t1 -set c1=(select a.c3 -from t1 a -where a.c3 = t1.c3) +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) order by c3 desc limit 2; affected rows: 2 info: Rows matched: 2 Changed: 2 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 NULL 2 @@ -262,22 +634,61 @@ NULL 3 NULL 4 NULL 5 NULL 6 -2->7 7 * -2->8 8 * -rollback; -Test with an index on updated columns +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +####################################### +# Test with an index # +####################################### create index t1_c2 on t1 (c2,c1); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK # -# Update a with value from subquery on the same table, no search clause. ALL access +# Update with value from subquery on the same table # -start transaction; -update t1 -set c1=(select a.c3 -from t1 a -where a.c3 = t1.c3); -affected rows: 8 -info: Rows matched: 8 Changed: 8 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; +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 +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed 1->1 1 1->2 2 * @@ -287,20 +698,56 @@ concat(old_c1,'->',c1) c3 Changed 2->6 6 * 2->7 7 * 2->8 8 * -rollback; +11->11 11 +11->12 12 * +11->13 13 * +12->14 14 * +12->15 15 * +12->16 16 * +12->17 17 * +12->18 18 * +21->21 21 +21->22 22 * +21->23 23 * +22->24 24 * +22->25 25 * +22->26 26 * +22->27 27 * +22->28 28 * +31->31 31 +31->32 32 * +31->33 33 * +32->34 34 * +32->35 35 * +32->36 36 * +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; # -# Update with search clause on the same table +# Update with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition # -start transaction; -update t1 -set c1=10 -where c1 <2 -and exists (select 'X' - from t1 a -where a.c1 = t1.c1); +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 +explain select * from t1 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a index NULL t1_c2 10 NULL 32 Using where; Using index; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a index NULL t1_c2 10 NULL 32 Using where; Using index; FirstMatch(t1) +update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); affected rows: 3 info: Rows matched: 3 Changed: 3 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed 1->10 1 * 1->10 2 * @@ -310,19 +757,53 @@ NULL 5 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# Update via RANGE or INDEX access if an index or a primary key exists +# Update with EXISTS subquery over the updated table +# in WHERE + non-sargable condition # -explain update t1 set c1=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 > 3; +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using where -1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c2 8 Using index; FirstMatch(t1) -start transaction; +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c2 5 Using index; FirstMatch(t1) +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c2 5 Using index; FirstMatch(t1) update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; -affected rows: 4 -info: Rows matched: 4 Changed: 4 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 NULL 2 @@ -332,13 +813,55 @@ NULL 5 2->12 6 * 2->12 7 * 2->12 8 * -rollback; +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; # # Update with order by # -start transaction; -update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3 order by c2; -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c2 5 Using index; FirstMatch(t1) +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c2 5 Using index; FirstMatch(t1) +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 NULL 2 @@ -348,18 +871,54 @@ NULL 5 2->12 6 * 2->12 7 * 2->12 8 * -rollback; +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; # -Update using a view in subquery +# Update with a reference to view in subquery +# in settable value # -start transaction; -update t1 -set c1=c1 +(select max(a.c2) -from v1 a -where a.c1 = t1.c1) ; -affected rows: 8 -info: Rows matched: 8 Changed: 8 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +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 +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 Using index +update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed 1->3 1 * 1->3 2 * @@ -369,19 +928,53 @@ concat(old_c1,'->',c1) c3 Changed 2->4 6 * 2->4 7 * 2->4 8 * -rollback; +11->13 11 * +11->13 12 * +11->13 13 * +12->14 14 * +12->14 15 * +12->14 16 * +12->14 17 * +12->14 18 * +21->23 21 * +21->23 22 * +21->23 23 * +22->24 24 * +22->24 25 * +22->24 26 * +22->24 27 * +22->24 28 * +31->33 31 * +31->33 32 * +31->33 33 * +32->34 34 * +32->34 35 * +32->34 36 * +32->34 37 * +32->34 38 * +truncate table t1; +insert into t1 select * from tmp; # -# Update throw a view +# Update view # -start transaction; -update v1 -set c1=c1 + (select max(a.c2) -from t1 a -where a.c1 = v1.c1) +10 -where c3 > 3; -affected rows: 1 -info: Rows matched: 1 Changed: 1 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +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 +explain select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref t1_c2 t1_c2 5 const 8 +explain update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 5 const 8 Using where +2 DEPENDENT SUBQUERY a index NULL t1_c2 10 NULL 32 Using where; Using index +update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +affected rows: 7 +info: Rows matched: 7 Changed: 7 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 NULL 2 @@ -391,20 +984,55 @@ NULL 4 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +11->24 12 * +NULL 13 +NULL 14 +12->27 15 * +NULL 16 +NULL 17 +NULL 18 +21->35 21 * +NULL 22 +NULL 23 +22->38 24 * +NULL 25 +NULL 26 +NULL 27 +NULL 28 +31->45 31 * +NULL 32 +NULL 33 +32->48 34 * +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# Update through a view and using the view in subquery +# Update view with reference to the same view in subquery # -start transaction; -update v1 -set c1=c1 + 1 -where c1 <2 -and exists (select 'X' - from v1 a -where a.c1 = v1.c1); +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 +explain select * from v1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 10 NULL 1 Using index condition +1 PRIMARY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 Using index; FirstMatch(t1) +explain update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 10 NULL 1 Using index condition; Using where +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,func 1 Using where; Using index +update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); affected rows: 1 info: Rows matched: 1 Changed: 1 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 1->2 2 * @@ -414,22 +1042,57 @@ NULL 5 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# Update through a view and using the view in subquery +# Update view with EXISTS and reference to the same view in subquery # -start transaction; +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 +explain select * from v1 where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 10 NULL 2 Using index condition +1 PRIMARY t1 ref t1_c2 t1_c2 5 const 8 Using index; FirstMatch(t1) +explain update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 10 NULL 2 Using index condition +3 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 5 const 8 Using where; Using index +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 Using index update v1 -set c1=(select max(a.c1)+10 -from v1 a -where a.c1 = v1.c1) -where c1 <10 -and exists (select 'X' - from v1 a -where a.c2 = v1.c2); +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); affected rows: 2 info: Rows matched: 2 Changed: 2 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 1->11 2 * @@ -439,41 +1102,107 @@ NULL 4 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# Update of the index or primary key (c3) +# Update with IN predicand over the updated table in WHERE # -start transaction; -explain update t1 set c3=c3+10 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +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 +explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 10 test.t1.c2,test.t1.c1 1 Using index; FirstMatch(t1) +explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 8 Using where +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where 1 PRIMARY a ref t1_c2 t1_c2 10 test.t1.c2,test.t1.c1 1 Using index; FirstMatch(t1) -update t1 set c3=c3+10 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); -affected rows: 8 -info: Rows matched: 8 Changed: 8 Warnings: 0 +update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 select c3 from t1; c3 -11 -12 -13 -14 -15 -16 -17 -18 -rollback; -# -# update with a limit -# -start transaction; +111 +112 +113 +114 +115 +116 +117 +118 +121 +122 +123 +124 +125 +126 +127 +128 +131 +132 +133 +134 +135 +136 +137 +138 +141 +142 +143 +144 +145 +146 +147 +148 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit +# +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 +explain select * from t1 limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where update t1 -set c1=(select a.c3 -from t1 a -where a.c3 = t1.c3) -limit 2; +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; affected rows: 2 info: Rows matched: 2 Changed: 2 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed 1->1 1 1->2 2 * @@ -483,19 +1212,55 @@ NULL 5 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# update with a limit and an order by +# Update with a limit and an order by # -start transaction; +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 +explain select * from t1 order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using filesort +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where update t1 -set c1=(select a.c3 -from t1 a -where a.c3 = t1.c3) +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) order by c3 desc limit 2; affected rows: 2 info: Rows matched: 2 Changed: 2 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 NULL 2 @@ -503,22 +1268,1336 @@ NULL 3 NULL 4 NULL 5 NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +####################################### +# Test with a primary key # +####################################### +drop index t1_c2 on t1; +alter table t1 add primary key (c3); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +# +# Update with value from subquery on the same table +# +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 +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 +update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->1 1 +1->2 2 * +1->3 3 * +2->4 4 * +2->5 5 * +2->6 6 * 2->7 7 * 2->8 8 * -rollback; -Test with an index on updated columns -create index t1_c3 on t1 (c3); +11->11 11 +11->12 12 * +11->13 13 * +12->14 14 * +12->15 15 * +12->16 16 * +12->17 17 * +12->18 18 * +21->21 21 +21->22 22 * +21->23 23 * +22->24 24 * +22->25 25 * +22->26 26 * +22->27 27 * +22->28 28 * +31->31 31 +31->32 32 * +31->33 33 * +32->34 34 * +32->35 35 * +32->36 36 * +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +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 +explain select * from t1 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +affected rows: 3 +info: Rows matched: 3 Changed: 3 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->10 1 * +1->10 2 * +1->10 3 * +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +1->11 3 * +NULL 4 +NULL 5 +2->12 6 * +2->12 7 * +2->12 8 * +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with order by +# +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +1->11 3 * +NULL 4 +NULL 5 +2->12 6 * +2->12 7 * +2->12 8 * +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a reference to view in subquery +# in settable value +# +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 +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->3 1 * +1->3 2 * +1->3 3 * +2->4 4 * +2->4 5 * +2->4 6 * +2->4 7 * +2->4 8 * +11->13 11 * +11->13 12 * +11->13 13 * +12->14 14 * +12->14 15 * +12->14 16 * +12->14 17 * +12->14 18 * +21->23 21 * +21->23 22 * +21->23 23 * +22->24 24 * +22->24 25 * +22->24 26 * +22->24 27 * +22->24 28 * +31->33 31 * +31->33 32 * +31->33 33 * +32->34 34 * +32->34 35 * +32->34 36 * +32->34 37 * +32->34 38 * +truncate table t1; +insert into t1 select * from tmp; # -# Update a with value from subquery on the same table, no search clause. ALL access +# Update view # -start transaction; +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 +explain select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using where +explain update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 29 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +affected rows: 7 +info: Rows matched: 7 Changed: 7 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +NULL 3 +NULL 4 +2->17 5 * +NULL 6 +NULL 7 +NULL 8 +NULL 11 +11->24 12 * +NULL 13 +NULL 14 +12->27 15 * +NULL 16 +NULL 17 +NULL 18 +21->35 21 * +NULL 22 +NULL 23 +22->38 24 * +NULL 25 +NULL 26 +NULL 27 +NULL 28 +31->45 31 * +NULL 32 +NULL 33 +32->48 34 * +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update view with reference to the same view in subquery +# +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 +explain select * from v1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +affected rows: 1 +info: Rows matched: 1 Changed: 1 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +1->2 2 * +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update view with EXISTS and reference to the same view in subquery +# +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 +explain select * from v1 where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +1->11 2 * +NULL 3 +NULL 4 +2->12 5 * +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with IN predicand over the updated table in WHERE +# +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 +explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select c3 from t1; +c3 +111 +112 +113 +114 +115 +116 +117 +118 +121 +122 +123 +124 +125 +126 +127 +128 +131 +132 +133 +134 +135 +136 +137 +138 +141 +142 +143 +144 +145 +146 +147 +148 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit +# +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 +explain select * from t1 limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 +update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->1 1 +1->2 2 * +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit and an order by +# +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 +explain select * from t1 order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 4 NULL 2 +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index NULL PRIMARY 4 NULL 2 Using buffer +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 update t1 -set c1=(select a.c3 -from t1 a -where a.c3 = t1.c3); -affected rows: 8 -info: Rows matched: 8 Changed: 8 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +# Update with error "Subquery returns more than 1 row" +update t1 set c2=(select c2 from t1); +ERROR 21000: Subquery returns more than 1 row +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +# Update with error "Subquery returns more than 1 row" +# and order by +update t1 set c2=(select c2 from t1) order by c3; +ERROR 21000: Subquery returns more than 1 row +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +# Duplicate value on update a primary key +update t1 set c3=0 +where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +ERROR 23000: Duplicate entry '0' for key 'PRIMARY' +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Duplicate value on update a primary key with ignore +update ignore t1 set c3=0 +where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 0 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Duplicate value on update a primary key and limit +update t1 set c3=0 +where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 limit 2; +ERROR 23000: Duplicate entry '0' for key 'PRIMARY' +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Duplicate value on update a primary key with ignore +# and limit +update ignore t1 set c3=0 +where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 0 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Update no rows found +update t1 set c1=10 +where c1 <2 and exists (select 'X' from t1 a where a.c1 = t1.c1 + 10); +affected rows: 3 +info: Rows matched: 3 Changed: 3 Warnings: 0 +select c1,c2,c3 from t1; +c1 c2 c3 +10 1 1 +10 2 2 +10 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Update no rows changed +drop trigger trg_t1; +update t1 set c1=c1 +where c1 <2 and exists (select 'X' from t1 a where a.c1 = t1.c1); +affected rows: 0 +info: Rows matched: 3 Changed: 0 Warnings: 0 +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Check call of after trigger +# +create or replace trigger trg_t2 after update on t1 for each row +begin +declare msg varchar(100); +if (new.c3 = 5) then +set msg=concat('in after update trigger on ',new.c3); +SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg; +end if; +end; +/ +update t1 set c1=2 +where c3 in (select distinct a.c3 from t1 a where a.c1=t1.c1); +ERROR 45000: in after update trigger on 5 +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Check update with order by and after trigger +# +update t1 set c1=2 +where c3 in (select distinct a.c3 from t1 a where a.c1=t1.c1) +order by t1.c2, t1.c1; +ERROR 45000: in after update trigger on 5 +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +drop view v1; +# +# Check update on view with check option +# +create view v1 as select * from t1 where c2=2 with check option; +update v1 set c2=3 where c1=1; +ERROR 44000: CHECK OPTION failed `test`.`v1` +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +update v1 set c2=(select max(c3) from v1) where c1=1; +ERROR 44000: CHECK OPTION failed `test`.`v1` +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +update v1 set c2=(select min(va.c3) from v1 va), c1=0 where c1=1; +select c1,c2,c3 from t1; +c1 c2 c3 +0 2 2 +1 1 1 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +drop table tmp; +drop view v1; +drop table t1; +# +# Test on dynamic columns (blob) +# +create table assets ( +item_name varchar(32) primary key, -- A common attribute for all items +dynamic_cols blob -- Dynamic columns will be stored here +); +INSERT INTO assets VALUES ('MariaDB T-shirt', +COLUMN_CREATE('color', 'blue', 'size', 'XL')); +INSERT INTO assets VALUES ('Thinkpad Laptop', +COLUMN_CREATE('color', 'black', 'price', 500)); +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color +FROM assets; +item_name color +MariaDB T-shirt blue +Thinkpad Laptop black +UPDATE assets +SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', '3 years') +WHERE item_name='Thinkpad Laptop'; +SELECT item_name, +COLUMN_GET(dynamic_cols, 'warranty' as char) AS color +FROM assets; +item_name color +MariaDB T-shirt NULL +Thinkpad Laptop 3 years +UPDATE assets +SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', '4 years') +WHERE item_name in +(select b.item_name from assets b +where COLUMN_GET(b.dynamic_cols, 'color' as char) ='black'); +SELECT item_name, +COLUMN_GET(dynamic_cols, 'warranty' as char) AS color +FROM assets; +item_name color +MariaDB T-shirt NULL +Thinkpad Laptop 4 years +UPDATE assets SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', +(select COLUMN_GET(b.dynamic_cols, 'color' as char) +from assets b +where assets.item_name = item_name)); +SELECT item_name, +COLUMN_GET(dynamic_cols, 'warranty' as char) AS color +FROM assets; +item_name color +MariaDB T-shirt blue +Thinkpad Laptop black +drop table assets; +# +# Test on fulltext columns +# +CREATE TABLE ft2(copy TEXT,FULLTEXT(copy)); +INSERT INTO ft2(copy) VALUES +('MySQL vs MariaDB database'), +('Oracle vs MariaDB database'), +('PostgreSQL vs MariaDB database'), +('MariaDB overview'), +('Foreign keys'), +('Primary keys'), +('Indexes'), +('Transactions'), +('Triggers'); +SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('database'); +copy +MySQL vs MariaDB database +Oracle vs MariaDB database +PostgreSQL vs MariaDB database +update ft2 set copy = (select max(concat('mykeyword ',substr(b.copy,1,5))) +from ft2 b WHERE MATCH(b.copy) AGAINST('database')) +where MATCH(copy) AGAINST('keys'); +SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('mykeyword'); +copy +mykeyword Postg +mykeyword Postg +drop table ft2; +####################################### +# # +# Engine Aria # +# # +####################################### +set default_storage_engine=Aria; +create table t1 (old_c1 integer, +old_c2 integer, +c1 integer, +c2 integer, +c3 integer); +create view v1 as select * from t1 where c2=2; +create trigger trg_t1 before update on t1 for each row +begin +set new.old_c1=old.c1; +set new.old_c2=old.c2; +end; +/ +insert into t1(c1,c2,c3) +values (1,1,1), (1,2,2), (1,3,3), +(2,1,4), (2,2,5), (2,3,6), +(2,4,7), (2,5,8); +insert into t1 select NULL, NULL, c1+10,c2,c3+10 from t1; +insert into t1 select NULL, NULL, c1+20,c2+1,c3+20 from t1; +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 +create table tmp as select * from t1; +####################################### +# Test without any index # +####################################### +# +# Update with value from subquery on the same table +# +analyze table t1 persistent for all; +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 t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed 1->1 1 1->2 2 * @@ -528,20 +2607,56 @@ concat(old_c1,'->',c1) c3 Changed 2->6 6 * 2->7 7 * 2->8 8 * -rollback; +11->11 11 +11->12 12 * +11->13 13 * +12->14 14 * +12->15 15 * +12->16 16 * +12->17 17 * +12->18 18 * +21->21 21 +21->22 22 * +21->23 23 * +22->24 24 * +22->25 25 * +22->26 26 * +22->27 27 * +22->28 28 * +31->31 31 +31->32 32 * +31->33 33 * +32->34 34 * +32->35 35 * +32->36 36 * +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; # -# Update with search clause on the same table +# Update with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition # -start transaction; -update t1 -set c1=10 -where c1 <2 -and exists (select 'X' - from t1 a -where a.c1 = t1.c1); +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 +explain select * from t1 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); affected rows: 3 info: Rows matched: 3 Changed: 3 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed 1->10 1 * 1->10 2 * @@ -551,19 +2666,55 @@ NULL 5 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# Update via RANGE or INDEX access if an index or a primary key exists +# Update with EXISTS subquery over the updated table +# in WHERE + non-sargable condition # -explain update t1 set c1=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 > 3; +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY a index t1_c2 t1_c2 10 NULL 8 Using where; Using index; LooseScan -1 PRIMARY t1 ref t1_c2 t1_c2 5 test.a.c2 1 -start transaction; +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; -affected rows: 4 -info: Rows matched: 4 Changed: 4 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 NULL 2 @@ -573,13 +2724,57 @@ NULL 5 2->12 6 * 2->12 7 * 2->12 8 * -rollback; +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; # # Update with order by # -start transaction; -update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3 order by c2; -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 NULL 2 @@ -589,18 +2784,54 @@ NULL 5 2->12 6 * 2->12 7 * 2->12 8 * -rollback; +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; # -Update using a view in subquery +# Update with a reference to view in subquery +# in settable value # -start transaction; -update t1 -set c1=c1 +(select max(a.c2) -from v1 a -where a.c1 = t1.c1) ; -affected rows: 8 -info: Rows matched: 8 Changed: 8 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +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 +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed 1->3 1 * 1->3 2 * @@ -610,19 +2841,687 @@ concat(old_c1,'->',c1) c3 Changed 2->4 6 * 2->4 7 * 2->4 8 * -rollback; +11->13 11 * +11->13 12 * +11->13 13 * +12->14 14 * +12->14 15 * +12->14 16 * +12->14 17 * +12->14 18 * +21->23 21 * +21->23 22 * +21->23 23 * +22->24 24 * +22->24 25 * +22->24 26 * +22->24 27 * +22->24 28 * +31->33 31 * +31->33 32 * +31->33 33 * +32->34 34 * +32->34 35 * +32->34 36 * +32->34 37 * +32->34 38 * +truncate table t1; +insert into t1 select * from tmp; # -# Update throw a view +# Update view # -start transaction; -update v1 -set c1=c1 + (select max(a.c2) -from t1 a -where a.c1 = v1.c1) +10 -where c3 > 3; +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 +explain select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using where +explain update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +affected rows: 7 +info: Rows matched: 7 Changed: 7 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +NULL 3 +NULL 4 +2->17 5 * +NULL 6 +NULL 7 +NULL 8 +NULL 11 +11->24 12 * +NULL 13 +NULL 14 +12->27 15 * +NULL 16 +NULL 17 +NULL 18 +21->35 21 * +NULL 22 +NULL 23 +22->38 24 * +NULL 25 +NULL 26 +NULL 27 +NULL 28 +31->45 31 * +NULL 32 +NULL 33 +32->48 34 * +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update view with reference to the same view in subquery +# +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 +explain select * from v1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); affected rows: 1 info: Rows matched: 1 Changed: 1 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +1->2 2 * +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update view with EXISTS and reference to the same view in subquery +# +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 +explain select * from v1 where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +1->11 2 * +NULL 3 +NULL 4 +2->12 5 * +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with IN predicand over the updated table in WHERE +# +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 +explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select c3 from t1; +c3 +111 +112 +113 +114 +115 +116 +117 +118 +121 +122 +123 +124 +125 +126 +127 +128 +131 +132 +133 +134 +135 +136 +137 +138 +141 +142 +143 +144 +145 +146 +147 +148 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit +# +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 +explain select * from t1 limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->1 1 +1->2 2 * +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit and an order by +# +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 +explain select * from t1 order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using filesort +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +####################################### +# Test with an index # +####################################### +create index t1_c2 on t1 (c2,c1); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +# +# Update with value from subquery on the same table +# +analyze table t1 persistent for all; +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 t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->1 1 +1->2 2 * +1->3 3 * +2->4 4 * +2->5 5 * +2->6 6 * +2->7 7 * +2->8 8 * +11->11 11 +11->12 12 * +11->13 13 * +12->14 14 * +12->15 15 * +12->16 16 * +12->17 17 * +12->18 18 * +21->21 21 +21->22 22 * +21->23 23 * +22->24 24 * +22->25 25 * +22->26 26 * +22->27 27 * +22->28 28 * +31->31 31 +31->32 32 * +31->33 33 * +32->34 34 * +32->35 35 * +32->36 36 * +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +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 +explain select * from t1 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a index NULL t1_c2 10 NULL 32 Using where; Using index; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a index NULL t1_c2 10 NULL 32 Using where; Using index; FirstMatch(t1) +update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +affected rows: 3 +info: Rows matched: 3 Changed: 3 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->10 1 * +1->10 2 * +1->10 3 * +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 21 Using index condition +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c2 5 Using index; FirstMatch(t1) +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 21 Using index condition +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c2 5 Using index; FirstMatch(t1) +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +1->11 3 * +NULL 4 +NULL 5 +2->12 6 * +2->12 7 * +2->12 8 * +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with order by +# +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 21 Using index condition +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c2 5 Using index; FirstMatch(t1) +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 21 Using index condition +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c2 5 Using index; FirstMatch(t1) +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +1->11 3 * +NULL 4 +NULL 5 +2->12 6 * +2->12 7 * +2->12 8 * +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a reference to view in subquery +# in settable value +# +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 +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 Using index +update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->3 1 * +1->3 2 * +1->3 3 * +2->4 4 * +2->4 5 * +2->4 6 * +2->4 7 * +2->4 8 * +11->13 11 * +11->13 12 * +11->13 13 * +12->14 14 * +12->14 15 * +12->14 16 * +12->14 17 * +12->14 18 * +21->23 21 * +21->23 22 * +21->23 23 * +22->24 24 * +22->24 25 * +22->24 26 * +22->24 27 * +22->24 28 * +31->33 31 * +31->33 32 * +31->33 33 * +32->34 34 * +32->34 35 * +32->34 36 * +32->34 37 * +32->34 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update view +# +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 +explain select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref t1_c2 t1_c2 5 const 8 +explain update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 5 const 8 Using where +2 DEPENDENT SUBQUERY a index NULL t1_c2 10 NULL 32 Using where; Using index +update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +affected rows: 7 +info: Rows matched: 7 Changed: 7 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 NULL 2 @@ -632,20 +3531,55 @@ NULL 4 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +11->24 12 * +NULL 13 +NULL 14 +12->27 15 * +NULL 16 +NULL 17 +NULL 18 +21->35 21 * +NULL 22 +NULL 23 +22->38 24 * +NULL 25 +NULL 26 +NULL 27 +NULL 28 +31->45 31 * +NULL 32 +NULL 33 +32->48 34 * +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# Update through a view and using the view in subquery +# Update view with reference to the same view in subquery # -start transaction; -update v1 -set c1=c1 + 1 -where c1 <2 -and exists (select 'X' - from v1 a -where a.c1 = v1.c1); +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 +explain select * from v1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 10 NULL 1 Using index condition +1 PRIMARY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 Using index; FirstMatch(t1) +explain update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 10 NULL 1 Using index condition; Using where +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,func 1 Using where; Using index +update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); affected rows: 1 info: Rows matched: 1 Changed: 1 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 1->2 2 * @@ -655,22 +3589,57 @@ NULL 5 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# Update through a view and using the view in subquery +# Update view with EXISTS and reference to the same view in subquery # -start transaction; +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 +explain select * from v1 where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 10 NULL 2 Using index condition +1 PRIMARY t1 ref t1_c2 t1_c2 5 const 8 Using index; FirstMatch(t1) +explain update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 10 NULL 2 Using index condition +3 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 5 const 8 Using where; Using index +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 Using index update v1 -set c1=(select max(a.c1)+10 -from v1 a -where a.c1 = v1.c1) -where c1 <10 -and exists (select 'X' - from v1 a -where a.c2 = v1.c2); +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); affected rows: 2 info: Rows matched: 2 Changed: 2 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 1->11 2 * @@ -680,41 +3649,107 @@ NULL 4 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# Update of the index or primary key (c3) +# Update with IN predicand over the updated table in WHERE # -start transaction; -explain update t1 set c3=c3+10 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +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 +explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 10 test.t1.c2,test.t1.c1 1 Using index; FirstMatch(t1) +explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 8 Using where +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where 1 PRIMARY a ref t1_c2 t1_c2 10 test.t1.c2,test.t1.c1 1 Using index; FirstMatch(t1) -update t1 set c3=c3+10 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); -affected rows: 8 -info: Rows matched: 8 Changed: 8 Warnings: 0 +update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 select c3 from t1; c3 -11 -12 -13 -14 -15 -16 -17 -18 -rollback; -# -# update with a limit -# -start transaction; +111 +112 +113 +114 +115 +116 +117 +118 +121 +122 +123 +124 +125 +126 +127 +128 +131 +132 +133 +134 +135 +136 +137 +138 +141 +142 +143 +144 +145 +146 +147 +148 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit +# +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 +explain select * from t1 limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where update t1 -set c1=(select a.c3 -from t1 a -where a.c3 = t1.c3) -limit 2; +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; affected rows: 2 info: Rows matched: 2 Changed: 2 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed 1->1 1 1->2 2 * @@ -724,19 +3759,55 @@ NULL 5 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# update with a limit and an order by +# Update with a limit and an order by # -start transaction; +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 +explain select * from t1 order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using filesort +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where update t1 -set c1=(select a.c3 -from t1 a -where a.c3 = t1.c3) +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) order by c3 desc limit 2; affected rows: 2 info: Rows matched: 2 Changed: 2 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 NULL 2 @@ -744,23 +3815,1336 @@ NULL 3 NULL 4 NULL 5 NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +####################################### +# Test with a primary key # +####################################### +drop index t1_c2 on t1; +alter table t1 add primary key (c3); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +# +# Update with value from subquery on the same table +# +analyze table t1 persistent for all; +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 t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using index +update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->1 1 +1->2 2 * +1->3 3 * +2->4 4 * +2->5 5 * +2->6 6 * 2->7 7 * 2->8 8 * -rollback; -Test with a primary key on updated columns -drop index t1_c3 on t1; -alter table t1 add primary key (c3); +11->11 11 +11->12 12 * +11->13 13 * +12->14 14 * +12->15 15 * +12->16 16 * +12->17 17 * +12->18 18 * +21->21 21 +21->22 22 * +21->23 23 * +22->24 24 * +22->25 25 * +22->26 26 * +22->27 27 * +22->28 28 * +31->31 31 +31->32 32 * +31->33 33 * +32->34 34 * +32->35 35 * +32->36 36 * +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +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 +explain select * from t1 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +affected rows: 3 +info: Rows matched: 3 Changed: 3 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->10 1 * +1->10 2 * +1->10 3 * +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +1->11 3 * +NULL 4 +NULL 5 +2->12 6 * +2->12 7 * +2->12 8 * +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; # -# Update a with value from subquery on the same table, no search clause. ALL access +# Update with order by # -start transaction; +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +1->11 3 * +NULL 4 +NULL 5 +2->12 6 * +2->12 7 * +2->12 8 * +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a reference to view in subquery +# in settable value +# +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 +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->3 1 * +1->3 2 * +1->3 3 * +2->4 4 * +2->4 5 * +2->4 6 * +2->4 7 * +2->4 8 * +11->13 11 * +11->13 12 * +11->13 13 * +12->14 14 * +12->14 15 * +12->14 16 * +12->14 17 * +12->14 18 * +21->23 21 * +21->23 22 * +21->23 23 * +22->24 24 * +22->24 25 * +22->24 26 * +22->24 27 * +22->24 28 * +31->33 31 * +31->33 32 * +31->33 33 * +32->34 34 * +32->34 35 * +32->34 36 * +32->34 37 * +32->34 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update view +# +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 +explain select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using where +explain update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 30 Using index condition; Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +affected rows: 7 +info: Rows matched: 7 Changed: 7 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +NULL 3 +NULL 4 +2->17 5 * +NULL 6 +NULL 7 +NULL 8 +NULL 11 +11->24 12 * +NULL 13 +NULL 14 +12->27 15 * +NULL 16 +NULL 17 +NULL 18 +21->35 21 * +NULL 22 +NULL 23 +22->38 24 * +NULL 25 +NULL 26 +NULL 27 +NULL 28 +31->45 31 * +NULL 32 +NULL 33 +32->48 34 * +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update view with reference to the same view in subquery +# +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 +explain select * from v1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +affected rows: 1 +info: Rows matched: 1 Changed: 1 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +1->2 2 * +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update view with EXISTS and reference to the same view in subquery +# +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 +explain select * from v1 where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +1->11 2 * +NULL 3 +NULL 4 +2->12 5 * +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with IN predicand over the updated table in WHERE +# +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 +explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select c3 from t1; +c3 +111 +112 +113 +114 +115 +116 +117 +118 +121 +122 +123 +124 +125 +126 +127 +128 +131 +132 +133 +134 +135 +136 +137 +138 +141 +142 +143 +144 +145 +146 +147 +148 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit +# +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 +explain select * from t1 limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using index update t1 -set c1=(select a.c3 -from t1 a -where a.c3 = t1.c3); -affected rows: 8 -info: Rows matched: 8 Changed: 8 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->1 1 +1->2 2 * +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit and an order by +# +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 +explain select * from t1 order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 4 NULL 2 +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index NULL PRIMARY 4 NULL 2 Using buffer +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using index +update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +# Update with error "Subquery returns more than 1 row" +update t1 set c2=(select c2 from t1); +ERROR 21000: Subquery returns more than 1 row +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +# Update with error "Subquery returns more than 1 row" +# and order by +update t1 set c2=(select c2 from t1) order by c3; +ERROR 21000: Subquery returns more than 1 row +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +# Duplicate value on update a primary key +update t1 set c3=0 +where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +ERROR 23000: Duplicate entry '0' for key 'PRIMARY' +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 0 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Duplicate value on update a primary key with ignore +update ignore t1 set c3=0 +where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 0 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Duplicate value on update a primary key and limit +update t1 set c3=0 +where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 limit 2; +ERROR 23000: Duplicate entry '0' for key 'PRIMARY' +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 0 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Duplicate value on update a primary key with ignore +# and limit +update ignore t1 set c3=0 +where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 0 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Update no rows found +update t1 set c1=10 +where c1 <2 and exists (select 'X' from t1 a where a.c1 = t1.c1 + 10); +affected rows: 3 +info: Rows matched: 3 Changed: 3 Warnings: 0 +select c1,c2,c3 from t1; +c1 c2 c3 +10 1 1 +10 2 2 +10 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Update no rows changed +drop trigger trg_t1; +update t1 set c1=c1 +where c1 <2 and exists (select 'X' from t1 a where a.c1 = t1.c1); +affected rows: 0 +info: Rows matched: 3 Changed: 0 Warnings: 0 +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Check call of after trigger +# +create or replace trigger trg_t2 after update on t1 for each row +begin +declare msg varchar(100); +if (new.c3 = 5) then +set msg=concat('in after update trigger on ',new.c3); +SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg; +end if; +end; +/ +update t1 set c1=2 +where c3 in (select distinct a.c3 from t1 a where a.c1=t1.c1); +ERROR 45000: in after update trigger on 5 +select c1,c2,c3 from t1; +c1 c2 c3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 1 +2 1 4 +2 2 2 +2 2 5 +2 3 3 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Check update with order by and after trigger +# +update t1 set c1=2 +where c3 in (select distinct a.c3 from t1 a where a.c1=t1.c1) +order by t1.c2, t1.c1; +ERROR 45000: in after update trigger on 5 +select c1,c2,c3 from t1; +c1 c2 c3 +1 3 3 +11 2 12 +11 3 13 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 1 +2 1 11 +2 1 14 +2 1 4 +2 2 2 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +drop view v1; +# +# Check update on view with check option +# +create view v1 as select * from t1 where c2=2 with check option; +update v1 set c2=3 where c1=1; +ERROR 44000: CHECK OPTION failed `test`.`v1` +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +update v1 set c2=(select max(c3) from v1) where c1=1; +ERROR 44000: CHECK OPTION failed `test`.`v1` +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +update v1 set c2=(select min(va.c3) from v1 va), c1=0 where c1=1; +select c1,c2,c3 from t1; +c1 c2 c3 +0 2 2 +1 1 1 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +drop table tmp; +drop view v1; +drop table t1; +# +# Test on dynamic columns (blob) +# +create table assets ( +item_name varchar(32) primary key, -- A common attribute for all items +dynamic_cols blob -- Dynamic columns will be stored here +); +INSERT INTO assets VALUES ('MariaDB T-shirt', +COLUMN_CREATE('color', 'blue', 'size', 'XL')); +INSERT INTO assets VALUES ('Thinkpad Laptop', +COLUMN_CREATE('color', 'black', 'price', 500)); +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color +FROM assets; +item_name color +MariaDB T-shirt blue +Thinkpad Laptop black +UPDATE assets +SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', '3 years') +WHERE item_name='Thinkpad Laptop'; +SELECT item_name, +COLUMN_GET(dynamic_cols, 'warranty' as char) AS color +FROM assets; +item_name color +MariaDB T-shirt NULL +Thinkpad Laptop 3 years +UPDATE assets +SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', '4 years') +WHERE item_name in +(select b.item_name from assets b +where COLUMN_GET(b.dynamic_cols, 'color' as char) ='black'); +SELECT item_name, +COLUMN_GET(dynamic_cols, 'warranty' as char) AS color +FROM assets; +item_name color +MariaDB T-shirt NULL +Thinkpad Laptop 4 years +UPDATE assets SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', +(select COLUMN_GET(b.dynamic_cols, 'color' as char) +from assets b +where assets.item_name = item_name)); +SELECT item_name, +COLUMN_GET(dynamic_cols, 'warranty' as char) AS color +FROM assets; +item_name color +MariaDB T-shirt blue +Thinkpad Laptop black +drop table assets; +# +# Test on fulltext columns +# +CREATE TABLE ft2(copy TEXT,FULLTEXT(copy)); +INSERT INTO ft2(copy) VALUES +('MySQL vs MariaDB database'), +('Oracle vs MariaDB database'), +('PostgreSQL vs MariaDB database'), +('MariaDB overview'), +('Foreign keys'), +('Primary keys'), +('Indexes'), +('Transactions'), +('Triggers'); +SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('database'); +copy +MySQL vs MariaDB database +Oracle vs MariaDB database +PostgreSQL vs MariaDB database +update ft2 set copy = (select max(concat('mykeyword ',substr(b.copy,1,5))) +from ft2 b WHERE MATCH(b.copy) AGAINST('database')) +where MATCH(copy) AGAINST('keys'); +SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('mykeyword'); +copy +mykeyword Postg +mykeyword Postg +drop table ft2; +####################################### +# # +# Engine MyISAM # +# # +####################################### +set default_storage_engine=MyISAM; +create table t1 (old_c1 integer, +old_c2 integer, +c1 integer, +c2 integer, +c3 integer); +create view v1 as select * from t1 where c2=2; +create trigger trg_t1 before update on t1 for each row +begin +set new.old_c1=old.c1; +set new.old_c2=old.c2; +end; +/ +insert into t1(c1,c2,c3) +values (1,1,1), (1,2,2), (1,3,3), +(2,1,4), (2,2,5), (2,3,6), +(2,4,7), (2,5,8); +insert into t1 select NULL, NULL, c1+10,c2,c3+10 from t1; +insert into t1 select NULL, NULL, c1+20,c2+1,c3+20 from t1; +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 +create table tmp as select * from t1; +####################################### +# Test without any index # +####################################### +# +# Update with value from subquery on the same table +# +analyze table t1 persistent for all; +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 t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed 1->1 1 1->2 2 * @@ -770,20 +5154,56 @@ concat(old_c1,'->',c1) c3 Changed 2->6 6 * 2->7 7 * 2->8 8 * -rollback; +11->11 11 +11->12 12 * +11->13 13 * +12->14 14 * +12->15 15 * +12->16 16 * +12->17 17 * +12->18 18 * +21->21 21 +21->22 22 * +21->23 23 * +22->24 24 * +22->25 25 * +22->26 26 * +22->27 27 * +22->28 28 * +31->31 31 +31->32 32 * +31->33 33 * +32->34 34 * +32->35 35 * +32->36 36 * +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; # -# Update with search clause on the same table +# Update with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition # -start transaction; -update t1 -set c1=10 -where c1 <2 -and exists (select 'X' - from t1 a -where a.c1 = t1.c1); +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 +explain select * from t1 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); affected rows: 3 info: Rows matched: 3 Changed: 3 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed 1->10 1 * 1->10 2 * @@ -793,19 +5213,55 @@ NULL 5 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# Update via RANGE or INDEX access if an index or a primary key exists +# Update with EXISTS subquery over the updated table +# in WHERE + non-sargable condition # -explain update t1 set c1=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 > 3; +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY a index t1_c2 t1_c2 10 NULL 8 Using where; Using index; LooseScan -1 PRIMARY t1 ref t1_c2 t1_c2 5 test.a.c2 1 -start transaction; +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; -affected rows: 4 -info: Rows matched: 4 Changed: 4 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 NULL 2 @@ -815,13 +5271,57 @@ NULL 5 2->12 6 * 2->12 7 * 2->12 8 * -rollback; +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; # # Update with order by # -start transaction; -update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3 order by c2; -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 NULL 2 @@ -831,18 +5331,54 @@ NULL 5 2->12 6 * 2->12 7 * 2->12 8 * -rollback; +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; # -Update using a view in subquery +# Update with a reference to view in subquery +# in settable value # -start transaction; -update t1 -set c1=c1 +(select max(a.c2) -from v1 a -where a.c1 = t1.c1) ; -affected rows: 8 -info: Rows matched: 8 Changed: 8 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +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 +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed 1->3 1 * 1->3 2 * @@ -852,19 +5388,687 @@ concat(old_c1,'->',c1) c3 Changed 2->4 6 * 2->4 7 * 2->4 8 * -rollback; +11->13 11 * +11->13 12 * +11->13 13 * +12->14 14 * +12->14 15 * +12->14 16 * +12->14 17 * +12->14 18 * +21->23 21 * +21->23 22 * +21->23 23 * +22->24 24 * +22->24 25 * +22->24 26 * +22->24 27 * +22->24 28 * +31->33 31 * +31->33 32 * +31->33 33 * +32->34 34 * +32->34 35 * +32->34 36 * +32->34 37 * +32->34 38 * +truncate table t1; +insert into t1 select * from tmp; # -# Update throw a view +# Update view # -start transaction; -update v1 -set c1=c1 + (select max(a.c2) -from t1 a -where a.c1 = v1.c1) +10 -where c3 > 3; +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 +explain select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using where +explain update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +affected rows: 7 +info: Rows matched: 7 Changed: 7 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +NULL 3 +NULL 4 +2->17 5 * +NULL 6 +NULL 7 +NULL 8 +NULL 11 +11->24 12 * +NULL 13 +NULL 14 +12->27 15 * +NULL 16 +NULL 17 +NULL 18 +21->35 21 * +NULL 22 +NULL 23 +22->38 24 * +NULL 25 +NULL 26 +NULL 27 +NULL 28 +31->45 31 * +NULL 32 +NULL 33 +32->48 34 * +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update view with reference to the same view in subquery +# +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 +explain select * from v1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); affected rows: 1 info: Rows matched: 1 Changed: 1 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +1->2 2 * +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update view with EXISTS and reference to the same view in subquery +# +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 +explain select * from v1 where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +1->11 2 * +NULL 3 +NULL 4 +2->12 5 * +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with IN predicand over the updated table in WHERE +# +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 +explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select c3 from t1; +c3 +111 +112 +113 +114 +115 +116 +117 +118 +121 +122 +123 +124 +125 +126 +127 +128 +131 +132 +133 +134 +135 +136 +137 +138 +141 +142 +143 +144 +145 +146 +147 +148 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit +# +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 +explain select * from t1 limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->1 1 +1->2 2 * +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit and an order by +# +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 +explain select * from t1 order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using filesort +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +####################################### +# Test with an index # +####################################### +create index t1_c2 on t1 (c2,c1); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +# +# Update with value from subquery on the same table +# +analyze table t1 persistent for all; +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 t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->1 1 +1->2 2 * +1->3 3 * +2->4 4 * +2->5 5 * +2->6 6 * +2->7 7 * +2->8 8 * +11->11 11 +11->12 12 * +11->13 13 * +12->14 14 * +12->15 15 * +12->16 16 * +12->17 17 * +12->18 18 * +21->21 21 +21->22 22 * +21->23 23 * +22->24 24 * +22->25 25 * +22->26 26 * +22->27 27 * +22->28 28 * +31->31 31 +31->32 32 * +31->33 33 * +32->34 34 * +32->35 35 * +32->36 36 * +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +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 +explain select * from t1 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a index NULL t1_c2 10 NULL 32 Using where; Using index; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a index NULL t1_c2 10 NULL 32 Using where; Using index; FirstMatch(t1) +update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +affected rows: 3 +info: Rows matched: 3 Changed: 3 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->10 1 * +1->10 2 * +1->10 3 * +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c2 5 Using index; FirstMatch(t1) +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c2 5 Using index; FirstMatch(t1) +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +1->11 3 * +NULL 4 +NULL 5 +2->12 6 * +2->12 7 * +2->12 8 * +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with order by +# +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c2 5 Using index; FirstMatch(t1) +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY a ref t1_c2 t1_c2 5 test.t1.c2 5 Using index; FirstMatch(t1) +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +1->11 3 * +NULL 4 +NULL 5 +2->12 6 * +2->12 7 * +2->12 8 * +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a reference to view in subquery +# in settable value +# +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 +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 Using index +update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->3 1 * +1->3 2 * +1->3 3 * +2->4 4 * +2->4 5 * +2->4 6 * +2->4 7 * +2->4 8 * +11->13 11 * +11->13 12 * +11->13 13 * +12->14 14 * +12->14 15 * +12->14 16 * +12->14 17 * +12->14 18 * +21->23 21 * +21->23 22 * +21->23 23 * +22->24 24 * +22->24 25 * +22->24 26 * +22->24 27 * +22->24 28 * +31->33 31 * +31->33 32 * +31->33 33 * +32->34 34 * +32->34 35 * +32->34 36 * +32->34 37 * +32->34 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update view +# +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 +explain select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref t1_c2 t1_c2 5 const 8 +explain update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref t1_c2 t1_c2 5 const 8 Using where +2 DEPENDENT SUBQUERY a index NULL t1_c2 10 NULL 32 Using where; Using index +update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +affected rows: 7 +info: Rows matched: 7 Changed: 7 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 NULL 2 @@ -874,20 +6078,55 @@ NULL 4 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +11->24 12 * +NULL 13 +NULL 14 +12->27 15 * +NULL 16 +NULL 17 +NULL 18 +21->35 21 * +NULL 22 +NULL 23 +22->38 24 * +NULL 25 +NULL 26 +NULL 27 +NULL 28 +31->45 31 * +NULL 32 +NULL 33 +32->48 34 * +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# Update through a view and using the view in subquery +# Update view with reference to the same view in subquery # -start transaction; -update v1 -set c1=c1 + 1 -where c1 <2 -and exists (select 'X' - from v1 a -where a.c1 = v1.c1); +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 +explain select * from v1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 10 NULL 1 Using index condition +1 PRIMARY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 Using index; FirstMatch(t1) +explain update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 10 NULL 1 Using index condition; Using where +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,func 1 Using where; Using index +update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); affected rows: 1 info: Rows matched: 1 Changed: 1 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 1->2 2 * @@ -897,22 +6136,57 @@ NULL 5 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# Update through a view and using the view in subquery +# Update view with EXISTS and reference to the same view in subquery # -start transaction; +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 +explain select * from v1 where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 10 NULL 2 Using index condition +1 PRIMARY t1 ref t1_c2 t1_c2 5 const 8 Using index; FirstMatch(t1) +explain update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range t1_c2 t1_c2 10 NULL 2 Using index condition +3 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 5 const 8 Using where; Using index +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 1 Using index update v1 -set c1=(select max(a.c1)+10 -from v1 a -where a.c1 = v1.c1) -where c1 <10 -and exists (select 'X' - from v1 a -where a.c2 = v1.c2); +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); affected rows: 2 info: Rows matched: 2 Changed: 2 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 1->11 2 * @@ -922,41 +6196,107 @@ NULL 4 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# Update of the index or primary key (c3) +# Update with IN predicand over the updated table in WHERE # -start transaction; -explain update t1 set c3=c3+10 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +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 +explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 10 test.t1.c2,test.t1.c1 1 Using index; FirstMatch(t1) +explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 8 Using where +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where 1 PRIMARY a ref t1_c2 t1_c2 10 test.t1.c2,test.t1.c1 1 Using index; FirstMatch(t1) -update t1 set c3=c3+10 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); -affected rows: 8 -info: Rows matched: 8 Changed: 8 Warnings: 0 +update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 select c3 from t1; c3 -11 -14 -12 -15 -13 -16 -17 -18 -rollback; -# -# update with a limit -# -start transaction; +111 +112 +113 +114 +115 +116 +117 +118 +121 +122 +123 +124 +125 +126 +127 +128 +131 +132 +133 +134 +135 +136 +137 +138 +141 +142 +143 +144 +145 +146 +147 +148 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit +# +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 +explain select * from t1 limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where update t1 -set c1=(select a.c3 -from t1 a -where a.c3 = t1.c3) -limit 2; +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; affected rows: 2 info: Rows matched: 2 Changed: 2 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed 1->1 1 1->2 2 * @@ -966,19 +6306,55 @@ NULL 5 NULL 6 NULL 7 NULL 8 -rollback; +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; # -# update with a limit and an order by +# Update with a limit and an order by # -start transaction; +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 +explain select * from t1 order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using filesort +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where update t1 -set c1=(select a.c3 -from t1 a -where a.c3 = t1.c3) +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) order by c3 desc limit 2; affected rows: 2 info: Rows matched: 2 Changed: 2 Warnings: 0 -select concat(old_c1,'->',c1),c3, case when c1 != old_c1 then '*' else ' ' end "Changed" from t1 ; +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; concat(old_c1,'->',c1) c3 Changed NULL 1 NULL 2 @@ -986,58 +6362,996 @@ NULL 3 NULL 4 NULL 5 NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +####################################### +# Test with a primary key # +####################################### +drop index t1_c2 on t1; +alter table t1 add primary key (c3); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +# +# Update with value from subquery on the same table +# +analyze table t1 persistent for all; +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 t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using index +update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->1 1 +1->2 2 * +1->3 3 * +2->4 4 * +2->5 5 * +2->6 6 * 2->7 7 * 2->8 8 * -rollback; +11->11 11 +11->12 12 * +11->13 13 * +12->14 14 * +12->15 15 * +12->16 16 * +12->17 17 * +12->18 18 * +21->21 21 +21->22 22 * +21->23 23 * +22->24 24 * +22->25 25 * +22->26 26 * +22->27 27 * +22->28 28 * +31->31 31 +31->32 32 * +31->33 33 * +32->34 34 * +32->35 35 * +32->36 36 * +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +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 +explain select * from t1 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +affected rows: 3 +info: Rows matched: 3 Changed: 3 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->10 1 * +1->10 2 * +1->10 3 * +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +1->11 3 * +NULL 4 +NULL 5 +2->12 6 * +2->12 7 * +2->12 8 * +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with order by +# +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 +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +1->11 3 * +NULL 4 +NULL 5 +2->12 6 * +2->12 7 * +2->12 8 * +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a reference to view in subquery +# in settable value +# +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 +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->3 1 * +1->3 2 * +1->3 3 * +2->4 4 * +2->4 5 * +2->4 6 * +2->4 7 * +2->4 8 * +11->13 11 * +11->13 12 * +11->13 13 * +12->14 14 * +12->14 15 * +12->14 16 * +12->14 17 * +12->14 18 * +21->23 21 * +21->23 22 * +21->23 23 * +22->24 24 * +22->24 25 * +22->24 26 * +22->24 27 * +22->24 28 * +31->33 31 * +31->33 32 * +31->33 33 * +32->34 34 * +32->34 35 * +32->34 36 * +32->34 37 * +32->34 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update view +# +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 +explain select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using where +explain update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +affected rows: 7 +info: Rows matched: 7 Changed: 7 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +NULL 3 +NULL 4 +2->17 5 * +NULL 6 +NULL 7 +NULL 8 +NULL 11 +11->24 12 * +NULL 13 +NULL 14 +12->27 15 * +NULL 16 +NULL 17 +NULL 18 +21->35 21 * +NULL 22 +NULL 23 +22->38 24 * +NULL 25 +NULL 26 +NULL 27 +NULL 28 +31->45 31 * +NULL 32 +NULL 33 +32->48 34 * +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update view with reference to the same view in subquery +# +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 +explain select * from v1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +affected rows: 1 +info: Rows matched: 1 Changed: 1 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +1->2 2 * +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update view with EXISTS and reference to the same view in subquery +# +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 +explain select * from v1 where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +1->11 2 * +NULL 3 +NULL 4 +2->12 5 * +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with IN predicand over the updated table in WHERE +# +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 +explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select c3 from t1; +c3 +111 +112 +113 +114 +115 +116 +117 +118 +121 +122 +123 +124 +125 +126 +127 +128 +131 +132 +133 +134 +135 +136 +137 +138 +141 +142 +143 +144 +145 +146 +147 +148 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit +# +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 +explain select * from t1 limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using index +update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->1 1 +1->2 2 * +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit and an order by +# +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 +explain select * from t1 order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 4 NULL 2 +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index NULL PRIMARY 4 NULL 2 Using buffer +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 Using index +update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; # Update with error "Subquery returns more than 1 row" update t1 set c2=(select c2 from t1); ERROR 21000: Subquery returns more than 1 row -# Update with error "Subquery returns more than 1 row" and order by +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +# Update with error "Subquery returns more than 1 row" +# and order by update t1 set c2=(select c2 from t1) order by c3; ERROR 21000: Subquery returns more than 1 row -Duplicate value on update a primary key -start transaction; -update t1 set c3=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +# Duplicate value on update a primary key +update t1 set c3=0 +where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; ERROR 23000: Duplicate entry '0' for key 'PRIMARY' -rollback; -Duplicate value on update a primary key with ignore -start transaction; -update ignore t1 set c3=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; -affected rows: 4 -info: Rows matched: 4 Changed: 4 Warnings: 0 -rollback; -Duplicate value on update a primary key and limit -start transaction; -update t1 set c3=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3 limit 2; +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 0 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Duplicate value on update a primary key with ignore +update ignore t1 set c3=0 +where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 0 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Duplicate value on update a primary key and limit +update t1 set c3=0 +where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 limit 2; ERROR 23000: Duplicate entry '0' for key 'PRIMARY' -rollback; -Duplicate value on update a primary key with ignore and limit -start transaction; -update ignore t1 set c3=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3 limit 2; +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 0 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Duplicate value on update a primary key with ignore +# and limit +update ignore t1 set c3=0 +where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 limit 2; affected rows: 2 info: Rows matched: 2 Changed: 2 Warnings: 0 -rollback; +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 0 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; # Update no rows found -update t1 -set c1=10 -where c1 <2 -and exists (select 'X' - from t1 a -where a.c1 = t1.c1 + 10); -affected rows: 0 -info: Rows matched: 0 Changed: 0 Warnings: 0 +update t1 set c1=10 +where c1 <2 and exists (select 'X' from t1 a where a.c1 = t1.c1 + 10); +affected rows: 3 +info: Rows matched: 3 Changed: 3 Warnings: 0 +select c1,c2,c3 from t1; +c1 c2 c3 +10 1 1 +10 2 2 +10 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; # Update no rows changed drop trigger trg_t1; -start transaction; -update t1 -set c1=c1 -where c1 <2 -and exists (select 'X' - from t1 a -where a.c1 = t1.c1); +update t1 set c1=c1 +where c1 <2 and exists (select 'X' from t1 a where a.c1 = t1.c1); affected rows: 0 info: Rows matched: 3 Changed: 0 Warnings: 0 -rollback; +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; # # Check call of after trigger # @@ -1050,61 +7364,208 @@ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg; end if; end; / -update t1 set c1=2 where c3 in (select distinct a.c3 from t1 a where a.c1=t1.c1); +update t1 set c1=2 +where c3 in (select distinct a.c3 from t1 a where a.c1=t1.c1); ERROR 45000: in after update trigger on 5 +select c1,c2,c3 from t1; +c1 c2 c3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 1 +2 1 4 +2 2 2 +2 2 5 +2 3 3 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; # # Check update with order by and after trigger # -update t1 set c1=2 where c3 in (select distinct a.c3 from t1 a where a.c1=t1.c1) order by t1.c2; +update t1 set c1=2 +where c3 in (select distinct a.c3 from t1 a where a.c1=t1.c1) +order by t1.c2, t1.c1; ERROR 45000: in after update trigger on 5 +select c1,c2,c3 from t1; +c1 c2 c3 +1 3 3 +11 2 12 +11 3 13 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 1 +2 1 11 +2 1 14 +2 1 4 +2 2 2 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; drop view v1; # # Check update on view with check option # create view v1 as select * from t1 where c2=2 with check option; -start transaction; update v1 set c2=3 where c1=1; ERROR 44000: CHECK OPTION failed `test`.`v1` -rollback; -start transaction; +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; update v1 set c2=(select max(c3) from v1) where c1=1; ERROR 44000: CHECK OPTION failed `test`.`v1` -rollback; -start transaction; +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; update v1 set c2=(select min(va.c3) from v1 va), c1=0 where c1=1; -rollback; -drop view v1; -drop table t1; -# -# Test with a temporary table -# -create temporary table t1 (c1 integer, c2 integer, c3 integer) engine=InnoDb; -insert into t1(c1,c2,c3) values (1,1,1); -insert into t1(c1,c2,c3) values (1,2,2); -insert into t1(c1,c2,c3) values (1,3,3); -insert into t1(c1,c2,c3) values (2,1,4); -insert into t1(c1,c2,c3) values (2,2,5); -insert into t1(c1,c2,c3) values (2,3,6); -insert into t1(c1,c2,c3) values (2,4,7); -insert into t1(c1,c2,c3) values (2,5,8); -start transaction; -update t1 -set c1=(select a.c2 -from t1 a -where a.c3 = t1.c3) limit 3; -affected rows: 2 -info: Rows matched: 3 Changed: 2 Warnings: 0 -select * from t1 ; +select c1,c2,c3 from t1; c1 c2 c3 +0 2 2 1 1 1 -2 2 2 -3 3 3 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 2 1 4 2 2 5 2 3 6 2 4 7 2 5 8 -rollback; +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +drop table tmp; +drop view v1; drop table t1; # # Test on dynamic columns (blob) @@ -1113,37 +7574,50 @@ create table assets ( item_name varchar(32) primary key, -- A common attribute for all items dynamic_cols blob -- Dynamic columns will be stored here ); -INSERT INTO assets VALUES ('MariaDB T-shirt', COLUMN_CREATE('color', 'blue', 'size', 'XL')); -INSERT INTO assets VALUES ('Thinkpad Laptop', COLUMN_CREATE('color', 'black', 'price', 500)); -SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color FROM assets; +INSERT INTO assets VALUES ('MariaDB T-shirt', +COLUMN_CREATE('color', 'blue', 'size', 'XL')); +INSERT INTO assets VALUES ('Thinkpad Laptop', +COLUMN_CREATE('color', 'black', 'price', 500)); +SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color +FROM assets; item_name color MariaDB T-shirt blue Thinkpad Laptop black -UPDATE assets SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', '3 years') WHERE item_name='Thinkpad Laptop'; -SELECT item_name, COLUMN_GET(dynamic_cols, 'warranty' as char) AS color FROM assets; +UPDATE assets +SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', '3 years') +WHERE item_name='Thinkpad Laptop'; +SELECT item_name, +COLUMN_GET(dynamic_cols, 'warranty' as char) AS color +FROM assets; item_name color MariaDB T-shirt NULL Thinkpad Laptop 3 years -UPDATE assets SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', '4 years') -WHERE item_name in (select b.item_name -from assets b +UPDATE assets +SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', '4 years') +WHERE item_name in +(select b.item_name from assets b where COLUMN_GET(b.dynamic_cols, 'color' as char) ='black'); -SELECT item_name, COLUMN_GET(dynamic_cols, 'warranty' as char) AS color FROM assets; +SELECT item_name, +COLUMN_GET(dynamic_cols, 'warranty' as char) AS color +FROM assets; item_name color MariaDB T-shirt NULL Thinkpad Laptop 4 years -UPDATE assets SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', (select COLUMN_GET(b.dynamic_cols, 'color' as char) +UPDATE assets SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', +(select COLUMN_GET(b.dynamic_cols, 'color' as char) from assets b where assets.item_name = item_name)); -SELECT item_name, COLUMN_GET(dynamic_cols, 'warranty' as char) AS color FROM assets; +SELECT item_name, +COLUMN_GET(dynamic_cols, 'warranty' as char) AS color +FROM assets; item_name color MariaDB T-shirt blue Thinkpad Laptop black -drop table assets ; +drop table assets; # # Test on fulltext columns # -CREATE TABLE ft2(copy TEXT,FULLTEXT(copy)) ENGINE=MyISAM; +CREATE TABLE ft2(copy TEXT,FULLTEXT(copy)); INSERT INTO ft2(copy) VALUES ('MySQL vs MariaDB database'), ('Oracle vs MariaDB database'), @@ -1159,17 +7633,2488 @@ copy MySQL vs MariaDB database Oracle vs MariaDB database PostgreSQL vs MariaDB database -update ft2 set copy = (select max(concat('mykeyword ',substr(b.copy,1,5))) from ft2 b WHERE MATCH(b.copy) AGAINST('database')) +update ft2 set copy = (select max(concat('mykeyword ',substr(b.copy,1,5))) +from ft2 b WHERE MATCH(b.copy) AGAINST('database')) where MATCH(copy) AGAINST('keys'); SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('mykeyword'); copy mykeyword Postg mykeyword Postg drop table ft2; +####################################### +# # +# Engine MEMORY # +# # +####################################### +set default_storage_engine=MEMORY; +create table t1 (old_c1 integer, +old_c2 integer, +c1 integer, +c2 integer, +c3 integer); +create view v1 as select * from t1 where c2=2; +create trigger trg_t1 before update on t1 for each row +begin +set new.old_c1=old.c1; +set new.old_c2=old.c2; +end; +/ +insert into t1(c1,c2,c3) +values (1,1,1), (1,2,2), (1,3,3), +(2,1,4), (2,2,5), (2,3,6), +(2,4,7), (2,5,8); +insert into t1 select NULL, NULL, c1+10,c2,c3+10 from t1; +insert into t1 select NULL, NULL, c1+20,c2+1,c3+20 from t1; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +create table tmp as select * from t1; +####################################### +# Test without any index # +####################################### +# +# Update with value from subquery on the same table +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->1 1 +1->2 2 * +1->3 3 * +2->4 4 * +2->5 5 * +2->6 6 * +2->7 7 * +2->8 8 * +11->11 11 +11->12 12 * +11->13 13 * +12->14 14 * +12->15 15 * +12->16 16 * +12->17 17 * +12->18 18 * +21->21 21 +21->22 22 * +21->23 23 * +22->24 24 * +22->25 25 * +22->26 26 * +22->27 27 * +22->28 28 * +31->31 31 +31->32 32 * +31->33 33 * +32->34 34 * +32->35 35 * +32->36 36 * +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from t1 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +affected rows: 3 +info: Rows matched: 3 Changed: 3 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->10 1 * +1->10 2 * +1->10 3 * +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +1->11 3 * +NULL 4 +NULL 5 +2->12 6 * +2->12 7 * +2->12 8 * +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with order by +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +1->11 3 * +NULL 4 +NULL 5 +2->12 6 * +2->12 7 * +2->12 8 * +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a reference to view in subquery +# in settable value +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->3 1 * +1->3 2 * +1->3 3 * +2->4 4 * +2->4 5 * +2->4 6 * +2->4 7 * +2->4 8 * +11->13 11 * +11->13 12 * +11->13 13 * +12->14 14 * +12->14 15 * +12->14 16 * +12->14 17 * +12->14 18 * +21->23 21 * +21->23 22 * +21->23 23 * +22->24 24 * +22->24 25 * +22->24 26 * +22->24 27 * +22->24 28 * +31->33 31 * +31->33 32 * +31->33 33 * +32->34 34 * +32->34 35 * +32->34 36 * +32->34 37 * +32->34 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update view +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using where +explain update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +affected rows: 7 +info: Rows matched: 7 Changed: 7 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +NULL 3 +NULL 4 +2->17 5 * +NULL 6 +NULL 7 +NULL 8 +NULL 11 +11->24 12 * +NULL 13 +NULL 14 +12->27 15 * +NULL 16 +NULL 17 +NULL 18 +21->35 21 * +NULL 22 +NULL 23 +22->38 24 * +NULL 25 +NULL 26 +NULL 27 +NULL 28 +31->45 31 * +NULL 32 +NULL 33 +32->48 34 * +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update view with reference to the same view in subquery +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from v1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +affected rows: 1 +info: Rows matched: 1 Changed: 1 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +1->2 2 * +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update view with EXISTS and reference to the same view in subquery +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from v1 where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +1->11 2 * +NULL 3 +NULL 4 +2->12 5 * +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with IN predicand over the updated table in WHERE +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select c3 from t1; +c3 +111 +112 +113 +114 +115 +116 +117 +118 +121 +122 +123 +124 +125 +126 +127 +128 +131 +132 +133 +134 +135 +136 +137 +138 +141 +142 +143 +144 +145 +146 +147 +148 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from t1 limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->1 1 +1->2 2 * +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit and an order by +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from t1 order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using filesort +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +####################################### +# Test with an index # +####################################### +create index t1_c2 on t1 (c2,c1); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +# +# Update with value from subquery on the same table +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->1 1 +1->2 2 * +1->3 3 * +2->4 4 * +2->5 5 * +2->6 6 * +2->7 7 * +2->8 8 * +11->11 11 +11->12 12 * +11->13 13 * +12->14 14 * +12->15 15 * +12->16 16 * +12->17 17 * +12->18 18 * +21->21 21 +21->22 22 * +21->23 23 * +22->24 24 * +22->25 25 * +22->26 26 * +22->27 27 * +22->28 28 * +31->31 31 +31->32 32 * +31->33 33 * +32->34 34 * +32->35 35 * +32->36 36 * +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +explain select * from t1 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +affected rows: 3 +info: Rows matched: 3 Changed: 3 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->10 1 * +1->10 2 * +1->10 3 * +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL t1_c2 NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL t1_c2 NULL NULL NULL 32 +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +1->11 3 * +NULL 4 +NULL 5 +2->12 6 * +2->12 7 * +2->12 8 * +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with order by +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL t1_c2 NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL t1_c2 NULL NULL NULL 32 +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +1->11 3 * +NULL 4 +NULL 5 +2->12 6 * +2->12 7 * +2->12 8 * +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a reference to view in subquery +# in settable value +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 2 +update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->3 1 * +1->3 2 * +1->3 3 * +2->4 4 * +2->4 5 * +2->4 6 * +2->4 7 * +2->4 8 * +11->13 11 * +11->13 12 * +11->13 13 * +12->14 14 * +12->14 15 * +12->14 16 * +12->14 17 * +12->14 18 * +21->23 21 * +21->23 22 * +21->23 23 * +22->24 24 * +22->24 25 * +22->24 26 * +22->24 27 * +22->24 28 * +31->33 31 * +31->33 32 * +31->33 33 * +32->34 34 * +32->34 35 * +32->34 36 * +32->34 37 * +32->34 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update view +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +explain select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL t1_c2 NULL NULL NULL 32 Using where +explain update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +affected rows: 7 +info: Rows matched: 7 Changed: 7 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +NULL 3 +NULL 4 +2->17 5 * +NULL 6 +NULL 7 +NULL 8 +NULL 11 +11->24 12 * +NULL 13 +NULL 14 +12->27 15 * +NULL 16 +NULL 17 +NULL 18 +21->35 21 * +NULL 22 +NULL 23 +22->38 24 * +NULL 25 +NULL 26 +NULL 27 +NULL 28 +31->45 31 * +NULL 32 +NULL 33 +32->48 34 * +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update view with reference to the same view in subquery +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +explain select * from v1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 2 FirstMatch(t1) +explain update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,func 2 Using where +update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +affected rows: 1 +info: Rows matched: 1 Changed: 1 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +1->2 2 * +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update view with EXISTS and reference to the same view in subquery +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +explain select * from v1 where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +3 DEPENDENT SUBQUERY t1 ALL t1_c2 NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ref t1_c2 t1_c2 10 const,test.t1.c1 2 +update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +1->11 2 * +NULL 3 +NULL 4 +2->12 5 * +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with IN predicand over the updated table in WHERE +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 10 test.t1.c2,test.t1.c1 2 FirstMatch(t1) +explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL t1_c2 NULL NULL NULL 32 Using where +1 PRIMARY a ref t1_c2 t1_c2 10 test.t1.c2,test.t1.c1 2 FirstMatch(t1) +update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select c3 from t1; +c3 +111 +112 +113 +114 +115 +116 +117 +118 +121 +122 +123 +124 +125 +126 +127 +128 +131 +132 +133 +134 +135 +136 +137 +138 +141 +142 +143 +144 +145 +146 +147 +148 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +explain select * from t1 limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->1 1 +1->2 2 * +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit and an order by +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Operation failed +explain select * from t1 order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using filesort +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +####################################### +# Test with a primary key # +####################################### +drop index t1_c2 on t1; +alter table t1 add primary key (c3); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +# +# Update with value from subquery on the same table +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 +update t1 set c1=(select a.c3 from t1 a where a.c3 = t1.c3); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->1 1 +1->2 2 * +1->3 3 * +2->4 4 * +2->5 5 * +2->6 6 * +2->7 7 * +2->8 8 * +11->11 11 +11->12 12 * +11->13 13 * +12->14 14 * +12->15 15 * +12->16 16 * +12->17 17 * +12->18 18 * +21->21 21 +21->22 22 * +21->23 23 * +22->24 24 * +22->25 25 * +22->26 26 * +22->27 27 * +22->28 28 * +31->31 31 +31->32 32 * +31->33 33 * +32->34 34 * +32->35 35 * +32->36 36 * +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with EXISTS subquery over the updated table +# in WHERE + possibly sargable condition +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from t1 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c1=10 where c1 <2 +and exists (select 'X' from t1 a where a.c1 = t1.c1); +affected rows: 3 +info: Rows matched: 3 Changed: 3 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->10 1 * +1->10 2 * +1->10 3 * +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with EXISTS subquery over the updated table +# in WHERE + non-sargable condition +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +1->11 3 * +NULL 4 +NULL 5 +2->12 6 * +2->12 7 * +2->12 8 * +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with order by +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from t1 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED a ALL NULL NULL NULL NULL 32 +update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 order by c2; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +1->11 3 * +NULL 4 +NULL 5 +2->12 6 * +2->12 7 * +2->12 8 * +NULL 11 +NULL 12 +11->21 13 * +NULL 14 +NULL 15 +12->22 16 * +12->22 17 * +12->22 18 * +NULL 21 +21->31 22 * +21->31 23 * +NULL 24 +22->32 25 * +22->32 26 * +22->32 27 * +22->32 28 * +NULL 31 +31->41 32 * +31->41 33 * +NULL 34 +32->42 35 * +32->42 36 * +32->42 37 * +32->42 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a reference to view in subquery +# in settable value +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update t1 set c1=c1 +(select max(a.c2) from v1 a +where a.c1 = t1.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->3 1 * +1->3 2 * +1->3 3 * +2->4 4 * +2->4 5 * +2->4 6 * +2->4 7 * +2->4 8 * +11->13 11 * +11->13 12 * +11->13 13 * +12->14 14 * +12->14 15 * +12->14 16 * +12->14 17 * +12->14 18 * +21->23 21 * +21->23 22 * +21->23 23 * +22->24 24 * +22->24 25 * +22->24 26 * +22->24 27 * +22->24 28 * +31->33 31 * +31->33 32 * +31->33 33 * +32->34 34 * +32->34 35 * +32->34 36 * +32->34 37 * +32->34 38 * +truncate table t1; +insert into t1 select * from tmp; +# +# Update view +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using where +explain update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY a ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + (select max(a.c2) from t1 a +where a.c1 = v1.c1) +10 where c3 > 3; +affected rows: 7 +info: Rows matched: 7 Changed: 7 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +NULL 3 +NULL 4 +2->17 5 * +NULL 6 +NULL 7 +NULL 8 +NULL 11 +11->24 12 * +NULL 13 +NULL 14 +12->27 15 * +NULL 16 +NULL 17 +NULL 18 +21->35 21 * +NULL 22 +NULL 23 +22->38 24 * +NULL 25 +NULL 26 +NULL 27 +NULL 28 +31->45 31 * +NULL 32 +NULL 33 +32->48 34 * +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update view with reference to the same view in subquery +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from v1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update v1 set c1=c1 + 1 where c1 <2 +and exists (select 'X' from v1 a where a.c1 = v1.c1); +affected rows: 1 +info: Rows matched: 1 Changed: 1 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +1->2 2 * +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update view with EXISTS and reference to the same view in subquery +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from v1 where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using where +3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 32 Using where +update v1 +set c1=(select max(a.c1)+10 from v1 a where a.c1 = v1.c1) +where c1 <10 and exists (select 'X' from v1 a where a.c2 = v1.c2); +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +1->11 2 * +NULL 3 +NULL 4 +2->12 5 * +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with IN predicand over the updated table in WHERE +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from t1 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +explain update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +1 PRIMARY a ALL NULL NULL NULL NULL 32 Using where; FirstMatch(t1) +update t1 set c3=c3+110 where c2 in (select distinct a.c2 from t1 a where t1.c1=a.c1); +affected rows: 32 +info: Rows matched: 32 Changed: 32 Warnings: 0 +select c3 from t1; +c3 +111 +112 +113 +114 +115 +116 +117 +118 +121 +122 +123 +124 +125 +126 +127 +128 +131 +132 +133 +134 +135 +136 +137 +138 +141 +142 +143 +144 +145 +146 +147 +148 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from t1 limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 +update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +1->1 1 +1->2 2 * +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +NULL 37 +NULL 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Update with a limit and an order by +# +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze note The storage engine for the table doesn't support analyze +explain select * from t1 order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 32 Using filesort +explain update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 32 Using filesort +2 DEPENDENT SUBQUERY a eq_ref PRIMARY PRIMARY 4 test.t1.c3 1 +update t1 +set c1=(select a.c3 from t1 a where a.c3 = t1.c3) +order by c3 desc limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select concat(old_c1,'->',c1),c3, +case when c1 != old_c1 then '*' else ' ' end "Changed" from t1; +concat(old_c1,'->',c1) c3 Changed +NULL 1 +NULL 2 +NULL 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +NULL 15 +NULL 16 +NULL 17 +NULL 18 +NULL 21 +NULL 22 +NULL 23 +NULL 24 +NULL 25 +NULL 26 +NULL 27 +NULL 28 +NULL 31 +NULL 32 +NULL 33 +NULL 34 +NULL 35 +NULL 36 +32->37 37 * +32->38 38 * +truncate table t1; +insert into t1 select * from tmp; +# Update with error "Subquery returns more than 1 row" +update t1 set c2=(select c2 from t1); +ERROR 21000: Subquery returns more than 1 row +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +# Update with error "Subquery returns more than 1 row" +# and order by +update t1 set c2=(select c2 from t1) order by c3; +ERROR 21000: Subquery returns more than 1 row +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +# Duplicate value on update a primary key +update t1 set c3=0 +where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +ERROR 23000: Duplicate entry '0' for key 'PRIMARY' +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 0 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Duplicate value on update a primary key with ignore +update ignore t1 set c3=0 +where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; +affected rows: 20 +info: Rows matched: 20 Changed: 20 Warnings: 0 +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 0 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Duplicate value on update a primary key and limit +update t1 set c3=0 +where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 limit 2; +ERROR 23000: Duplicate entry '0' for key 'PRIMARY' +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 0 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Duplicate value on update a primary key with ignore +# and limit +update ignore t1 set c3=0 +where exists (select 'X' from t1 a where a.c2 = t1.c2) +and c2 >= 3 limit 2; +affected rows: 2 +info: Rows matched: 2 Changed: 2 Warnings: 0 +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 0 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Update no rows found +update t1 set c1=10 +where c1 <2 and exists (select 'X' from t1 a where a.c1 = t1.c1 + 10); +affected rows: 3 +info: Rows matched: 3 Changed: 3 Warnings: 0 +select c1,c2,c3 from t1; +c1 c2 c3 +10 1 1 +10 2 2 +10 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# Update no rows changed +drop trigger trg_t1; +update t1 set c1=c1 +where c1 <2 and exists (select 'X' from t1 a where a.c1 = t1.c1); +affected rows: 0 +info: Rows matched: 3 Changed: 0 Warnings: 0 +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Check call of after trigger +# +create or replace trigger trg_t2 after update on t1 for each row +begin +declare msg varchar(100); +if (new.c3 = 5) then +set msg=concat('in after update trigger on ',new.c3); +SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg; +end if; +end; +/ +update t1 set c1=2 +where c3 in (select distinct a.c3 from t1 a where a.c1=t1.c1); +ERROR 45000: in after update trigger on 5 +select c1,c2,c3 from t1; +c1 c2 c3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 1 +2 1 4 +2 2 2 +2 2 5 +2 3 3 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +# +# Check update with order by and after trigger +# +update t1 set c1=2 +where c3 in (select distinct a.c3 from t1 a where a.c1=t1.c1) +order by t1.c2, t1.c1; +ERROR 45000: in after update trigger on 5 +select c1,c2,c3 from t1; +c1 c2 c3 +1 3 3 +11 2 12 +11 3 13 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 1 +2 1 11 +2 1 14 +2 1 4 +2 2 2 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +drop view v1; +# +# Check update on view with check option +# +create view v1 as select * from t1 where c2=2 with check option; +update v1 set c2=3 where c1=1; +ERROR 44000: CHECK OPTION failed `test`.`v1` +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +update v1 set c2=(select max(c3) from v1) where c1=1; +ERROR 44000: CHECK OPTION failed `test`.`v1` +select c1,c2,c3 from t1; +c1 c2 c3 +1 1 1 +1 2 2 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +update v1 set c2=(select min(va.c3) from v1 va), c1=0 where c1=1; +select c1,c2,c3 from t1; +c1 c2 c3 +0 2 2 +1 1 1 +1 3 3 +11 1 11 +11 2 12 +11 3 13 +12 1 14 +12 2 15 +12 3 16 +12 4 17 +12 5 18 +2 1 4 +2 2 5 +2 3 6 +2 4 7 +2 5 8 +21 2 21 +21 3 22 +21 4 23 +22 2 24 +22 3 25 +22 4 26 +22 5 27 +22 6 28 +31 2 31 +31 3 32 +31 4 33 +32 2 34 +32 3 35 +32 4 36 +32 5 37 +32 6 38 +truncate table t1; +insert into t1 select * from tmp; +drop table tmp; +drop view v1; +drop table t1; +set @@default_storage_engine=@save_default_engine; # # Test with MyISAM # -create table t1 (old_c1 integer, old_c2 integer,c1 integer, c2 integer, c3 integer) engine=MyISAM; +create table t1 (old_c1 integer, +old_c2 integer, +c1 integer, +c2 integer, +c3 integer) engine=MyISAM; insert t1 (c1,c2,c3) select 0,seq,seq%10 from seq_1_to_500; insert t1 (c1,c2,c3) select 1,seq,seq%10 from seq_1_to_400; insert t1 (c1,c2,c3) select 2,seq,seq%10 from seq_1_to_300; @@ -1189,13 +10134,14 @@ count(*) 140 drop table t1; # -# Test error on multi_update conversion on view with order by or limit +# Test error on multi_update conversion on view +# with order by or limit # create table t1 (c1 integer) engine=InnoDb; create table t2 (c1 integer) engine=InnoDb; -create view v1 as select t1.c1 as "t1c1" ,t2.c1 as "t2c1" from t1,t2 where t1.c1=t2.c1; +create view v1 as select t1.c1 as "t1c1" ,t2.c1 as "t2c1" + from t1,t2 where t1.c1=t2.c1; update v1 set t1c1=2 order by 1; -ERROR 42S22: Unknown column '1' in 'order clause' update v1 set t1c1=2 limit 1; drop table t1; drop table t2; diff --git a/mysql-test/main/update_use_source.test b/mysql-test/main/update_use_source.test index 1b765138a18..ec27fa4d03c 100644 --- a/mysql-test/main/update_use_source.test +++ b/mysql-test/main/update_use_source.test @@ -2,221 +2,55 @@ --source include/have_innodb.inc --source include/no_valgrind_without_big.inc -create table t1 (old_c1 integer, old_c2 integer,c1 integer, c2 integer, c3 integer) engine=InnoDB STATS_PERSISTENT=0; -create view v1 as select * from t1 where c2=2; -delimiter /; -create trigger trg_t1 before update on t1 for each row -begin - set new.old_c1=old.c1; - set new.old_c2=old.c2; -end; -/ -delimiter ;/ - -insert into t1(c1,c2,c3) values (1,1,1); -insert into t1(c1,c2,c3) values (1,2,2); -insert into t1(c1,c2,c3) values (1,3,3); -insert into t1(c1,c2,c3) values (2,1,4); -insert into t1(c1,c2,c3) values (2,2,5); -insert into t1(c1,c2,c3) values (2,3,6); -insert into t1(c1,c2,c3) values (2,4,7); -insert into t1(c1,c2,c3) values (2,5,8); - -commit; -select * from t1; - ---echo Test without any index +set @save_default_engine=@@default_storage_engine; + +--echo ####################################### +--echo # # +--echo # Engine InnoDB # +--echo # # +--echo ####################################### +set global innodb_stats_persistent=1; +set default_storage_engine=InnoDB; --source include/update_use_source.inc - ---echo Test with an index on updated columns -create index t1_c2 on t1 (c2,c1); +--source include/update_use_source_ext.inc + +--echo ####################################### +--echo # # +--echo # Engine Aria # +--echo # # +--echo ####################################### +set default_storage_engine=Aria; --source include/update_use_source.inc - ---echo Test with an index on updated columns -create index t1_c3 on t1 (c3); +--source include/update_use_source_ext.inc + +--echo ####################################### +--echo # # +--echo # Engine MyISAM # +--echo # # +--echo ####################################### +set default_storage_engine=MyISAM; --source include/update_use_source.inc - ---echo Test with a primary key on updated columns -drop index t1_c3 on t1; -alter table t1 add primary key (c3); +--source include/update_use_source_ext.inc + +--echo ####################################### +--echo # # +--echo # Engine MEMORY # +--echo # # +--echo ####################################### +set default_storage_engine=MEMORY; --source include/update_use_source.inc ---echo # Update with error "Subquery returns more than 1 row" ---error ER_SUBQUERY_NO_1_ROW -update t1 set c2=(select c2 from t1); - ---echo # Update with error "Subquery returns more than 1 row" and order by ---error ER_SUBQUERY_NO_1_ROW -update t1 set c2=(select c2 from t1) order by c3; - --- echo Duplicate value on update a primary key -start transaction; ---error ER_DUP_ENTRY -update t1 set c3=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; -rollback; - --- echo Duplicate value on update a primary key with ignore -start transaction; ---enable_info ONCE -update ignore t1 set c3=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; -rollback; - --- echo Duplicate value on update a primary key and limit -start transaction; ---error ER_DUP_ENTRY -update t1 set c3=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3 limit 2; -rollback; - --- echo Duplicate value on update a primary key with ignore and limit -start transaction; ---enable_info ONCE -update ignore t1 set c3=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3 limit 2; -rollback; - ---echo # Update no rows found ---enable_info ONCE -update t1 - set c1=10 - where c1 <2 - and exists (select 'X' - from t1 a - where a.c1 = t1.c1 + 10); - ---echo # Update no rows changed -drop trigger trg_t1; -start transaction; ---enable_info ONCE -update t1 - set c1=c1 - where c1 <2 - and exists (select 'X' - from t1 a - where a.c1 = t1.c1); -rollback; - ---echo # ---echo # Check call of after trigger ---echo # - -delimiter /; -create or replace trigger trg_t2 after update on t1 for each row -begin - declare msg varchar(100); - if (new.c3 = 5) then - set msg=concat('in after update trigger on ',new.c3); - SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg; - end if; -end; -/ -delimiter ;/ ---error 1644 -update t1 set c1=2 where c3 in (select distinct a.c3 from t1 a where a.c1=t1.c1); - ---echo # ---echo # Check update with order by and after trigger ---echo # - ---error 1644 -update t1 set c1=2 where c3 in (select distinct a.c3 from t1 a where a.c1=t1.c1) order by t1.c2; - -drop view v1; ---echo # ---echo # Check update on view with check option ---echo # - -create view v1 as select * from t1 where c2=2 with check option; - -start transaction; --- error 1369 -update v1 set c2=3 where c1=1; -rollback; - -start transaction; --- error 1369 -update v1 set c2=(select max(c3) from v1) where c1=1; -rollback; - -start transaction; -update v1 set c2=(select min(va.c3) from v1 va), c1=0 where c1=1; -rollback; - -drop view v1; -drop table t1; - ---echo # ---echo # Test with a temporary table ---echo # - -create temporary table t1 (c1 integer, c2 integer, c3 integer) engine=InnoDb; -insert into t1(c1,c2,c3) values (1,1,1); -insert into t1(c1,c2,c3) values (1,2,2); -insert into t1(c1,c2,c3) values (1,3,3); -insert into t1(c1,c2,c3) values (2,1,4); -insert into t1(c1,c2,c3) values (2,2,5); -insert into t1(c1,c2,c3) values (2,3,6); -insert into t1(c1,c2,c3) values (2,4,7); -insert into t1(c1,c2,c3) values (2,5,8); - -start transaction; ---enable_info ONCE -update t1 - set c1=(select a.c2 - from t1 a - where a.c3 = t1.c3) limit 3; -select * from t1 ; -rollback; -drop table t1; - ---echo # ---echo # Test on dynamic columns (blob) ---echo # - -create table assets ( - item_name varchar(32) primary key, -- A common attribute for all items - dynamic_cols blob -- Dynamic columns will be stored here -); -INSERT INTO assets VALUES ('MariaDB T-shirt', COLUMN_CREATE('color', 'blue', 'size', 'XL')); -INSERT INTO assets VALUES ('Thinkpad Laptop', COLUMN_CREATE('color', 'black', 'price', 500)); -SELECT item_name, COLUMN_GET(dynamic_cols, 'color' as char) AS color FROM assets; -UPDATE assets SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', '3 years') WHERE item_name='Thinkpad Laptop'; -SELECT item_name, COLUMN_GET(dynamic_cols, 'warranty' as char) AS color FROM assets; -UPDATE assets SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', '4 years') - WHERE item_name in (select b.item_name - from assets b - where COLUMN_GET(b.dynamic_cols, 'color' as char) ='black'); -SELECT item_name, COLUMN_GET(dynamic_cols, 'warranty' as char) AS color FROM assets; - -UPDATE assets SET dynamic_cols=COLUMN_ADD(dynamic_cols, 'warranty', (select COLUMN_GET(b.dynamic_cols, 'color' as char) - from assets b - where assets.item_name = item_name)); -SELECT item_name, COLUMN_GET(dynamic_cols, 'warranty' as char) AS color FROM assets; -drop table assets ; - ---echo # ---echo # Test on fulltext columns ---echo # -CREATE TABLE ft2(copy TEXT,FULLTEXT(copy)) ENGINE=MyISAM; -INSERT INTO ft2(copy) VALUES - ('MySQL vs MariaDB database'), - ('Oracle vs MariaDB database'), - ('PostgreSQL vs MariaDB database'), - ('MariaDB overview'), - ('Foreign keys'), - ('Primary keys'), - ('Indexes'), - ('Transactions'), - ('Triggers'); -SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('database'); -update ft2 set copy = (select max(concat('mykeyword ',substr(b.copy,1,5))) from ft2 b WHERE MATCH(b.copy) AGAINST('database')) - where MATCH(copy) AGAINST('keys'); -SELECT * FROM ft2 WHERE MATCH(copy) AGAINST('mykeyword'); -drop table ft2; +set @@default_storage_engine=@save_default_engine; --echo # --echo # Test with MyISAM --echo # -create table t1 (old_c1 integer, old_c2 integer,c1 integer, c2 integer, c3 integer) engine=MyISAM; +create table t1 (old_c1 integer, + old_c2 integer, + c1 integer, + c2 integer, + c3 integer) engine=MyISAM; insert t1 (c1,c2,c3) select 0,seq,seq%10 from seq_1_to_500; insert t1 (c1,c2,c3) select 1,seq,seq%10 from seq_1_to_400; insert t1 (c1,c2,c3) select 2,seq,seq%10 from seq_1_to_300; @@ -232,13 +66,15 @@ drop table t1; --echo # ---echo # Test error on multi_update conversion on view with order by or limit +--echo # Test error on multi_update conversion on view +--echo # with order by or limit --echo # create table t1 (c1 integer) engine=InnoDb; create table t2 (c1 integer) engine=InnoDb; -create view v1 as select t1.c1 as "t1c1" ,t2.c1 as "t2c1" from t1,t2 where t1.c1=t2.c1; ---error ER_BAD_FIELD_ERROR +create view v1 as select t1.c1 as "t1c1" ,t2.c1 as "t2c1" + from t1,t2 where t1.c1=t2.c1; +# 'order by 1' should be considered as in 'select * from v1 order 1' update v1 set t1c1=2 order by 1; update v1 set t1c1=2 limit 1; drop table t1; diff --git a/mysql-test/main/variables.result b/mysql-test/main/variables.result index 9b54a24be71..4359a8eef01 100644 --- a/mysql-test/main/variables.result +++ b/mysql-test/main/variables.result @@ -548,7 +548,7 @@ set default_storage_engine=myisam; set global thread_cache_size=100; set timestamp=1, timestamp=default; set tmp_table_size=1024; -set tx_isolation="READ-COMMITTED"; +set transaction_isolation="READ-COMMITTED"; set wait_timeout=100; set log_warnings=1; set global log_warnings=1; diff --git a/mysql-test/main/variables.test b/mysql-test/main/variables.test index 89267560ca6..77c6a153304 100644 --- a/mysql-test/main/variables.test +++ b/mysql-test/main/variables.test @@ -336,7 +336,7 @@ set default_storage_engine=myisam; set global thread_cache_size=100; set timestamp=1, timestamp=default; set tmp_table_size=1024; -set tx_isolation="READ-COMMITTED"; +set transaction_isolation="READ-COMMITTED"; set wait_timeout=100; set log_warnings=1; set global log_warnings=1; diff --git a/mysql-test/main/view_grant.result b/mysql-test/main/view_grant.result index 1c720f215f8..cfb8f7df60e 100644 --- a/mysql-test/main/view_grant.result +++ b/mysql-test/main/view_grant.result @@ -676,6 +676,7 @@ ERROR 42000: UPDATE command denied to user 'readonly'@'localhost' for table `mys UPDATE mysqltest1.v_ts SET x= 200; ERROR 42000: UPDATE command denied to user 'readonly'@'localhost' for table `mysqltest1`.`v_ts` UPDATE mysqltest1.v_tu SET x= 200 WHERE x = 100; +ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for column 'x' in table 'v_tu' UPDATE mysqltest1.v_tus SET x= 200 WHERE x = 100; UPDATE mysqltest1.v_tu SET x= 200; DELETE FROM mysqltest1.v_ts WHERE x= 200; diff --git a/mysql-test/main/view_grant.test b/mysql-test/main/view_grant.test index 9094c616a1f..a7990b44636 100644 --- a/mysql-test/main/view_grant.test +++ b/mysql-test/main/view_grant.test @@ -809,6 +809,7 @@ INSERT INTO mysqltest1.v_ti VALUES (100); UPDATE mysqltest1.v_ts SET x= 200 WHERE x = 100; --error ER_TABLEACCESS_DENIED_ERROR UPDATE mysqltest1.v_ts SET x= 200; +--error ER_COLUMNACCESS_DENIED_ERROR UPDATE mysqltest1.v_tu SET x= 200 WHERE x = 100; UPDATE mysqltest1.v_tus SET x= 200 WHERE x = 100; UPDATE mysqltest1.v_tu SET x= 200; diff --git a/mysql-test/mariadb-test-run.pl b/mysql-test/mariadb-test-run.pl index 07d55afe959..245e5d42ed2 100755 --- a/mysql-test/mariadb-test-run.pl +++ b/mysql-test/mariadb-test-run.pl @@ -1261,14 +1261,14 @@ sub command_line_setup { # In the RPM case, binaries and libraries are installed in the # default system locations, instead of having our own private base - # directory. And we install "/usr/share/mysql-test". Moving up one - # more directory relative to "mysql-test" gives us a usable base + # directory. And we install "/usr/share/mariadb-test". Moving up one + # more directory relative to "mariadb-test" gives us a usable base # directory for RPM installs. if ( ! $source_dist and ! -d "$basedir/bin" ) { $basedir= dirname($basedir); } - # For .deb, it's like RPM, but installed in /usr/share/mysql/mysql-test. + # For .deb, it's like RPM, but installed in /usr/share/mariadb/mariadb-test. # So move up one more directory level yet. if ( ! $source_dist and ! -d "$basedir/bin" ) { @@ -1867,7 +1867,8 @@ sub executable_setup () { $exe_mysql_plugin= mtr_exe_exists("$path_client_bindir/mariadb-plugin"); $exe_mariadb_conv= mtr_exe_exists("$path_client_bindir/mariadb-conv"); - $exe_mysql_embedded= mtr_exe_maybe_exists("$bindir/libmysqld/examples/mysql_embedded"); + $exe_mysql_embedded= mtr_exe_maybe_exists("$bindir/libmysqld/examples/mariadb-embedded", + "$bindir/libmysqld/examples/mysql_embedded"); # Look for mysqltest executable if ( $opt_embedded_server ) @@ -1977,11 +1978,15 @@ sub mysql_client_test_arguments(){ # mysql_client_test executable may _not_ exist if ( $opt_embedded_server ) { $exe= mtr_exe_maybe_exists( + "$bindir/libmysqld/examples$multiconfig/mariadb-client-test-embedded", + "$bindir/bin/mariadb-client-test-embedded", "$bindir/libmysqld/examples$multiconfig/mysql_client_test_embedded", - "$bindir/bin/mysql_client_test_embedded"); + "$bindir/bin/mysql_client_test_embedded"); } else { - $exe= mtr_exe_maybe_exists("$bindir/tests$multiconfig/mysql_client_test", - "$bindir/bin/mysql_client_test"); + $exe= mtr_exe_maybe_exists("$bindir/tests$multiconfig/mariadb-client-test", + "$bindir/bin/mariadb-client-test", + "$bindir/tests$multiconfig/mysql_client_test", + "$bindir/bin/mysql_client_test"); } my $args; @@ -2186,10 +2191,10 @@ sub environment_setup { # mysql_fix_privilege_tables.sql # ---------------------------------------------------- my $file_mysql_fix_privilege_tables= - mtr_file_exists("$bindir/scripts/mysql_fix_privilege_tables.sql", - "$bindir/share/mysql_fix_privilege_tables.sql", - "$bindir/share/mariadb/mysql_fix_privilege_tables.sql", - "$bindir/share/mysql/mysql_fix_privilege_tables.sql"); + mtr_file_exists("$bindir/scripts/mariadb_fix_privilege_tables.sql", + "$bindir/share/mariadb_fix_privilege_tables.sql", + "$bindir/share/mariadb/mariadb_fix_privilege_tables.sql", + "$bindir/share/mysql/mariadb_fix_privilege_tables.sql"); $ENV{'MYSQL_FIX_PRIVILEGE_TABLES'}= $file_mysql_fix_privilege_tables; # ---------------------------------------------------- @@ -2264,6 +2269,8 @@ sub environment_setup { # mariabackup # ---------------------------------------------------- my $exe_mariabackup= mtr_exe_maybe_exists( + "$bindir/extra/mariabackup$multiconfig/mariadb-backup", + "$path_client_bindir/mariadb-backup", "$bindir/extra/mariabackup$multiconfig/mariabackup", "$path_client_bindir/mariabackup"); @@ -3098,7 +3105,7 @@ sub mysql_install_db { my $path_sql= my_find_file($install_basedir, ["mysql", "sql/share", "share/mariadb", "share/mysql", "share", "scripts"], - "mysql_system_tables.sql", + "mariadb_system_tables.sql", NOT_REQUIRED); if (-f $path_sql ) @@ -3109,7 +3116,7 @@ sub mysql_install_db { # Add the offical mysql system tables # for a production system - mtr_appendfile_to_file("$sql_dir/mysql_system_tables.sql", + mtr_appendfile_to_file("$sql_dir/mariadb_system_tables.sql", $bootstrap_sql_file); my $gis_sp_path = $source_dist ? "$bindir/scripts" : $sql_dir; @@ -3118,18 +3125,18 @@ sub mysql_install_db { # Add the performance tables # for a production system - mtr_appendfile_to_file("$sql_dir/mysql_performance_tables.sql", + mtr_appendfile_to_file("$sql_dir/mariadb_performance_tables.sql", $bootstrap_sql_file); # Add the mysql system tables initial data # for a production system - mtr_appendfile_to_file("$sql_dir/mysql_system_tables_data.sql", + mtr_appendfile_to_file("$sql_dir/mariadb_system_tables_data.sql", $bootstrap_sql_file); # Add test data for timezone - this is just a subset, on a real # system these tables will be populated either by mysql_tzinfo_to_sql # or by downloading the timezone table package from our website - mtr_appendfile_to_file("$sql_dir/mysql_test_data_timezone.sql", + mtr_appendfile_to_file("$sql_dir/mariadb_test_data_timezone.sql", $bootstrap_sql_file); # Fill help tables, just an empty file when running from bk repo @@ -3139,7 +3146,7 @@ sub mysql_install_db { $bootstrap_sql_file); # Append sys schema - mtr_appendfile_to_file("$gis_sp_path/mysql_sys_schema.sql", + mtr_appendfile_to_file("$gis_sp_path/mariadb_sys_schema.sql", $bootstrap_sql_file); mtr_tofile($bootstrap_sql_file, "CREATE DATABASE IF NOT EXISTS test CHARACTER SET latin1 COLLATE latin1_swedish_ci;\n"); diff --git a/mysql-test/suite/binlog/r/binlog_stm_do_db.result b/mysql-test/suite/binlog/r/binlog_stm_do_db.result index c39404aef55..391158b1723 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_do_db.result +++ b/mysql-test/suite/binlog/r/binlog_stm_do_db.result @@ -1,6 +1,6 @@ RESET MASTER; -SET @old_isolation_level= @@session.tx_isolation; -SET @@session.tx_isolation= 'READ-COMMITTED'; +SET @old_isolation_level= @@session.transaction_isolation; +SET @@session.transaction_isolation= 'READ-COMMITTED'; CREATE DATABASE b42829; use b42829; CREATE TABLE t1 (x int, y int) engine=InnoDB; @@ -43,4 +43,4 @@ master-bin.000001 # Gtid # # GTID #-#-# master-bin.000001 # Query # # use `b42829`; CREATE TABLE t2 (x int, y int) engine=InnoDB DROP DATABASE b42829; DROP DATABASE b42829_filtered; -SET @@session.tx_isolation= @old_isolation_level; +SET @@session.transaction_isolation= @old_isolation_level; diff --git a/mysql-test/suite/binlog/t/binlog_stm_do_db.test b/mysql-test/suite/binlog/t/binlog_stm_do_db.test index 3ed1734f18d..c83753eb68d 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_do_db.test +++ b/mysql-test/suite/binlog/t/binlog_stm_do_db.test @@ -19,7 +19,7 @@ # # The test is implemented as follows: # -# i) set tx_isolation to read-committed. +# i) set transaction_isolation to read-committed. # # ii) create two databases (one filtered other not - using # binlog-do-db) @@ -38,8 +38,8 @@ -- source include/have_innodb.inc -- source include/have_binlog_format_statement.inc RESET MASTER; # clear up binlogs -SET @old_isolation_level= @@session.tx_isolation; -SET @@session.tx_isolation= 'READ-COMMITTED'; +SET @old_isolation_level= @@session.transaction_isolation; +SET @@session.transaction_isolation= 'READ-COMMITTED'; -- let $engine= InnoDB -- let $filtered= b42829_filtered @@ -87,4 +87,4 @@ source include/show_binlog_events.inc; -- eval DROP DATABASE $not_filtered -- eval DROP DATABASE $filtered -SET @@session.tx_isolation= @old_isolation_level; +SET @@session.transaction_isolation= @old_isolation_level; diff --git a/mysql-test/suite/encryption/r/innodb-bad-key-change.result b/mysql-test/suite/encryption/r/innodb-bad-key-change.result index eb114fcf6fc..a034e68e251 100644 --- a/mysql-test/suite/encryption/r/innodb-bad-key-change.result +++ b/mysql-test/suite/encryption/r/innodb-bad-key-change.result @@ -6,6 +6,7 @@ call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page n call mtr.add_suppression("failed to read \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]"); call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=[1-9][0-9]*, page number=3\\] in file .*test.t1.ibd looks corrupted; key_version=1"); call mtr.add_suppression("File '.*mysql-test.std_data.keysbad3\\.txt' not found"); +call mtr.add_suppression("File '.*mariadb-test.std_data.keysbad3\\.txt' not found"); call mtr.add_suppression("\\[ERROR\\] InnoDB: Cannot decrypt \\[page id: space="); # Start server with keys2.txt # restart: --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys2.txt diff --git a/mysql-test/suite/encryption/r/innodb-bad-key-change4.result b/mysql-test/suite/encryption/r/innodb-bad-key-change4.result deleted file mode 100644 index 9983c26c9d7..00000000000 --- a/mysql-test/suite/encryption/r/innodb-bad-key-change4.result +++ /dev/null @@ -1,25 +0,0 @@ -call mtr.add_suppression("InnoDB: Table `test`\\.`t1` (has an unreadable root page)"); -call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t1\\.ibd' cannot be decrypted; key_version=1"); -call mtr.add_suppression("InnoDB: Recovery failed to read page"); -call mtr.add_suppression("Couldn't load plugins from 'file_key_management"); -call mtr.add_suppression("Table .*t1.* is corrupted"); -call mtr.add_suppression("\\[ERROR\\] InnoDB: Cannot decrypt \\[page id: space="); -# restart: --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys2.txt -CREATE TABLE t1 (pk INT PRIMARY KEY, f VARCHAR(8)) ENGINE=InnoDB -ENCRYPTED=YES ENCRYPTION_KEY_ID=4; -INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); -# restart: --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys3.txt -OPTIMIZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 optimize Error Table 'test.t1' doesn't exist in engine -test.t1 optimize status Operation failed -SHOW WARNINGS; -Level Code Message -CHECK TABLE t1; -Table Op Msg_type Msg_text -test.t1 check Error Table test/t1 is corrupted. Please drop the table and recreate. -test.t1 check error Corrupt -SHOW WARNINGS; -Level Code Message -# restart: --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys2.txt -DROP TABLE t1; diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change.test b/mysql-test/suite/encryption/t/innodb-bad-key-change.test index 5eefded9ae1..27483ae35d0 100644 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change.test +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change.test @@ -16,6 +16,7 @@ call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page n call mtr.add_suppression("failed to read \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]"); call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=[1-9][0-9]*, page number=3\\] in file .*test.t1.ibd looks corrupted; key_version=1"); call mtr.add_suppression("File '.*mysql-test.std_data.keysbad3\\.txt' not found"); +call mtr.add_suppression("File '.*mariadb-test.std_data.keysbad3\\.txt' not found"); # for innodb_checksum_algorithm=full_crc32 only call mtr.add_suppression("\\[ERROR\\] InnoDB: Cannot decrypt \\[page id: space="); diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change4.combinations b/mysql-test/suite/encryption/t/innodb-bad-key-change4.combinations deleted file mode 100644 index 729380593f3..00000000000 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change4.combinations +++ /dev/null @@ -1,5 +0,0 @@ -[strict_crc32] ---innodb-checksum-algorithm=strict_crc32 - -[strict_full_crc32] ---innodb-checksum-algorithm=strict_full_crc32 diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change4.opt b/mysql-test/suite/encryption/t/innodb-bad-key-change4.opt deleted file mode 100644 index d20d3b60913..00000000000 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change4.opt +++ /dev/null @@ -1,6 +0,0 @@ ---loose-innodb-buffer-pool-stats ---loose-innodb-buffer-page ---loose-innodb-buffer-page-lru ---innodb-defragment=1 ---innodb-purge-rseg-truncate-frequency=1 ---skip-innodb-fast-shutdown diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change4.test b/mysql-test/suite/encryption/t/innodb-bad-key-change4.test deleted file mode 100644 index b041c988851..00000000000 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change4.test +++ /dev/null @@ -1,42 +0,0 @@ ---source include/have_innodb.inc -# embedded does not support restart --- source include/not_embedded.inc --- source filekeys_plugin_exists.inc -# -# MDEV-8769: Server crash at file btr0btr.ic line 122 when defragmenting encrypted table using incorrect keys -# MDEV-8768: Server crash at file btr0btr.ic line 122 when checking encrypted table using incorrect keys -# - -call mtr.add_suppression("InnoDB: Table `test`\\.`t1` (has an unreadable root page)"); -call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t1\\.ibd' cannot be decrypted; key_version=1"); -call mtr.add_suppression("InnoDB: Recovery failed to read page"); -# Suppression for builds where file_key_management plugin is linked statically -call mtr.add_suppression("Couldn't load plugins from 'file_key_management"); -call mtr.add_suppression("Table .*t1.* is corrupted"); -# for innodb_checksum_algorithm=full_crc32 only -call mtr.add_suppression("\\[ERROR\\] InnoDB: Cannot decrypt \\[page id: space="); - ---let $restart_parameters=--plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt ---source include/restart_mysqld.inc - -CREATE TABLE t1 (pk INT PRIMARY KEY, f VARCHAR(8)) ENGINE=InnoDB -ENCRYPTED=YES ENCRYPTION_KEY_ID=4; -INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); - ---let $restart_parameters=--plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys3.txt ---source include/restart_mysqld.inc - ---replace_regex /key_id [1-9][0-9]*/\1 / -OPTIMIZE TABLE t1; ---replace_regex /key_id [1-9][0-9]*/\1 / -SHOW WARNINGS; - ---replace_regex /key_id [1-9][0-9]*/\1 / -CHECK TABLE t1; ---replace_regex /key_id [1-9][0-9]*/\1 / -SHOW WARNINGS; - ---let $restart_parameters=--plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt ---source include/restart_mysqld.inc - -DROP TABLE t1; diff --git a/mysql-test/suite/engines/iuds/r/update_delete_number.result b/mysql-test/suite/engines/iuds/r/update_delete_number.result index 1cd2a62cb56..1534f93b436 100644 --- a/mysql-test/suite/engines/iuds/r/update_delete_number.result +++ b/mysql-test/suite/engines/iuds/r/update_delete_number.result @@ -739,8 +739,21 @@ c1 c2 c3 c1 c2 c3 DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 WHERE a2.c1=a1.c2; SELECT * FROM t1,t2 WHERE t2.c1=t1.c2; c1 c2 c3 c1 c2 c3 -DELETE FROM t1,t2 using t1,t2 where t1.c1=(select c1 from t1); -ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +INSERT INTO t1 VALUES(254,127,1),(0,-128,2),(1,127,3),(3,NULL,5); +INSERT INTO t2 VALUES(127,255,1),(127,1,2),(-128,0,3),(-1,NULL,5); +DELETE FROM t1,t2 using t1,t2 +where t1.c1=(select c1 from t1 where c2 < 10) and t2.c2 < 10; +SELECT * FROM t1; +c1 c2 c3 +1 127 3 +254 127 1 +3 NULL 5 +SELECT * FROM t2; +c1 c2 c3 +-1 NULL 5 +127 255 1 CREATE TABLE t3(c1 INT UNSIGNED NOT NULL PRIMARY KEY, c2 INT SIGNED NULL, c3 INT); CREATE TABLE t4(c1 INT UNSIGNED, c2 INT); INSERT INTO t3 VALUES(200,126,1),(250,-127,2); @@ -981,7 +994,6 @@ create table mt1 (col1 int); create table mt2 (col1 int); update mt1,mt2 set mt1.col1 = (select max(col1) from mt1) where mt1.col1 = mt2.col1; delete mt1 from mt1,mt2 where mt1.col1 < (select max(col1) from mt1) and mt1.col1 = mt2.col1; -ERROR HY000: Table 'mt1' is specified twice, both as a target for 'DELETE' and as a separate source for data drop table mt1,mt2; CREATE TABLE IF NOT EXISTS `mt1` (`id` int(11) NOT NULL auto_increment, `tst` text, `tsmt1` text, PRIMARY KEY (`id`)); CREATE TABLE IF NOT EXISTS `mt2` (`ID` int(11) NOT NULL auto_increment, `ParId` int(11) default NULL, `tst` text, `tsmt1` text, PRIMARY KEY (`ID`), KEY `IX_ParId_mt2` (`ParId`), FOREIGN KEY (`ParId`) REFERENCES `mt1` (`id`)); @@ -1852,7 +1864,6 @@ DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 WHERE a2.c1=a1.c2; SELECT * FROM t1,t2 WHERE t2.c1=t1.c2; c1 c2 c3 c1 c2 c3 DELETE FROM t1,t2 using t1,t2 where t1.c1=(select c1 from t1); -ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data CREATE TABLE t3(c1 TINYINT UNSIGNED NOT NULL PRIMARY KEY, c2 TINYINT SIGNED NULL, c3 INT); CREATE TABLE t4(c1 TINYINT UNSIGNED, c2 INT); INSERT INTO t3 VALUES(200,126,1),(250,-127,2); @@ -2599,7 +2610,6 @@ DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 WHERE a2.c1=a1.c2; SELECT * FROM t1,t2 WHERE t2.c1=t1.c2; c1 c2 c3 c1 c2 c3 DELETE FROM t1,t2 using t1,t2 where t1.c1=(select c1 from t1); -ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data CREATE TABLE t3(c1 SMALLINT UNSIGNED NOT NULL PRIMARY KEY, c2 SMALLINT SIGNED NULL, c3 INT); CREATE TABLE t4(c1 SMALLINT UNSIGNED, c2 INT); INSERT INTO t3 VALUES(200,126,1),(250,-127,2); @@ -3346,7 +3356,6 @@ DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 WHERE a2.c1=a1.c2; SELECT * FROM t1,t2 WHERE t2.c1=t1.c2; c1 c2 c3 c1 c2 c3 DELETE FROM t1,t2 using t1,t2 where t1.c1=(select c1 from t1); -ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data CREATE TABLE t3(c1 MEDIUMINT UNSIGNED NOT NULL PRIMARY KEY, c2 MEDIUMINT SIGNED NULL, c3 INT); CREATE TABLE t4(c1 MEDIUMINT UNSIGNED, c2 INT); INSERT INTO t3 VALUES(200,126,1),(250,-127,2); @@ -4093,7 +4102,6 @@ DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 WHERE a2.c1=a1.c2; SELECT * FROM t1,t2 WHERE t2.c1=t1.c2; c1 c2 c3 c1 c2 c3 DELETE FROM t1,t2 using t1,t2 where t1.c1=(select c1 from t1); -ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data CREATE TABLE t3(c1 BIGINT UNSIGNED NOT NULL PRIMARY KEY, c2 BIGINT SIGNED NULL, c3 INT); CREATE TABLE t4(c1 BIGINT UNSIGNED, c2 INT); INSERT INTO t3 VALUES(200,126,1),(250,-127,2); diff --git a/mysql-test/suite/engines/iuds/t/update_delete_number.test b/mysql-test/suite/engines/iuds/t/update_delete_number.test index ce3f90140b2..4347d0606ae 100644 --- a/mysql-test/suite/engines/iuds/t/update_delete_number.test +++ b/mysql-test/suite/engines/iuds/t/update_delete_number.test @@ -285,8 +285,18 @@ SELECT * FROM t1,t2 WHERE t2.c1=t1.c2; DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 WHERE a2.c1=a1.c2; --sorted_result SELECT * FROM t1,t2 WHERE t2.c1=t1.c2; ---error ER_UPDATE_TABLE_USED -DELETE FROM t1,t2 using t1,t2 where t1.c1=(select c1 from t1); +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +INSERT INTO t1 VALUES(254,127,1),(0,-128,2),(1,127,3),(3,NULL,5); +INSERT INTO t2 VALUES(127,255,1),(127,1,2),(-128,0,3),(-1,NULL,5); +# After the patch for MDEV-28883 this should not report +# ER_UPDATE_TABLE_USED anymore +DELETE FROM t1,t2 using t1,t2 + where t1.c1=(select c1 from t1 where c2 < 10) and t2.c2 < 10; +--sorted_result +SELECT * FROM t1; +--sorted_result +SELECT * FROM t2; # eq-ref join CREATE TABLE t3(c1 INT UNSIGNED NOT NULL PRIMARY KEY, c2 INT SIGNED NULL, c3 INT); @@ -496,7 +506,7 @@ drop table mt1, mt2, mt3; create table mt1 (col1 int); create table mt2 (col1 int); update mt1,mt2 set mt1.col1 = (select max(col1) from mt1) where mt1.col1 = mt2.col1; --- error ER_UPDATE_TABLE_USED +# -- error ER_UPDATE_TABLE_USED delete mt1 from mt1,mt2 where mt1.col1 < (select max(col1) from mt1) and mt1.col1 = mt2.col1; drop table mt1,mt2; @@ -865,7 +875,6 @@ SELECT * FROM t1,t2 WHERE t2.c1=t1.c2; DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 WHERE a2.c1=a1.c2; --sorted_result SELECT * FROM t1,t2 WHERE t2.c1=t1.c2; ---error ER_UPDATE_TABLE_USED DELETE FROM t1,t2 using t1,t2 where t1.c1=(select c1 from t1); # eq-ref join @@ -1166,7 +1175,6 @@ SELECT * FROM t1,t2 WHERE t2.c1=t1.c2; DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 WHERE a2.c1=a1.c2; --sorted_result SELECT * FROM t1,t2 WHERE t2.c1=t1.c2; ---error ER_UPDATE_TABLE_USED DELETE FROM t1,t2 using t1,t2 where t1.c1=(select c1 from t1); # eq-ref join @@ -1467,7 +1475,6 @@ SELECT * FROM t1,t2 WHERE t2.c1=t1.c2; DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 WHERE a2.c1=a1.c2; --sorted_result SELECT * FROM t1,t2 WHERE t2.c1=t1.c2; ---error ER_UPDATE_TABLE_USED DELETE FROM t1,t2 using t1,t2 where t1.c1=(select c1 from t1); # eq-ref join @@ -1768,7 +1775,6 @@ SELECT * FROM t1,t2 WHERE t2.c1=t1.c2; DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 WHERE a2.c1=a1.c2; --sorted_result SELECT * FROM t1,t2 WHERE t2.c1=t1.c2; ---error ER_UPDATE_TABLE_USED DELETE FROM t1,t2 using t1,t2 where t1.c1=(select c1 from t1); # eq-ref join diff --git a/mysql-test/suite/engines/rr_trx/include/rr_init.test b/mysql-test/suite/engines/rr_trx/include/rr_init.test index 7d08c4565e2..579df37dc06 100644 --- a/mysql-test/suite/engines/rr_trx/include/rr_init.test +++ b/mysql-test/suite/engines/rr_trx/include/rr_init.test @@ -17,7 +17,7 @@ if (`SELECT @@default_storage_engine LIKE 'InnoDB' AND @@version LIKE '%6.%'`) SHOW VARIABLES LIKE 'default_storage_engine'; # Verify default isolation level -SHOW VARIABLES LIKE 'tx_isolation'; +SHOW VARIABLES LIKE 'transaction_isolation'; # # Create table for keeping track of test metadata/statistics (counters etc.). diff --git a/mysql-test/suite/engines/rr_trx/r/init_innodb.result b/mysql-test/suite/engines/rr_trx/r/init_innodb.result index 292575a6610..cecaeab4902 100644 --- a/mysql-test/suite/engines/rr_trx/r/init_innodb.result +++ b/mysql-test/suite/engines/rr_trx/r/init_innodb.result @@ -2,9 +2,9 @@ SET @@default_storage_engine = 'InnoDB'; SHOW VARIABLES LIKE 'default_storage_engine'; Variable_name Value storage_engine InnoDB -SHOW VARIABLES LIKE 'tx_isolation'; +SHOW VARIABLES LIKE 'transaction_isolation'; Variable_name Value -tx_isolation REPEATABLE-READ +transaction_isolation REPEATABLE-READ CREATE TABLE statistics ( tx_errors INTEGER NOT NULL ); diff --git a/mysql-test/suite/events/events_embedded.test b/mysql-test/suite/events/events_embedded.test index f6921f302bf..c607573b2dc 100644 --- a/mysql-test/suite/events/events_embedded.test +++ b/mysql-test/suite/events/events_embedded.test @@ -1,4 +1,4 @@ --source include/is_embedded.inc ---error 1193 +--error ER_UNKNOWN_SYSTEM_VARIABLE set global event_scheduler=ON; diff --git a/mysql-test/suite/funcs_1/r/is_collations.result b/mysql-test/suite/funcs_1/r/is_collations.result index 979b477b8bc..6007742a2a1 100644 --- a/mysql-test/suite/funcs_1/r/is_collations.result +++ b/mysql-test/suite/funcs_1/r/is_collations.result @@ -66,7 +66,7 @@ INSERT INTO information_schema.collations (collation_name,character_set_name,id,is_default,is_compiled,sortlen) VALUES ( 'cp1251_bin', 'cp1251',50, '', '',0); ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' -UPDATE information_schema.collations SET description = 'just updated'; +UPDATE information_schema.collations SET collation_name = 'just updated'; Got one of the listed errors DELETE FROM information_schema.collations WHERE table_name = 't1'; ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' diff --git a/mysql-test/suite/funcs_1/t/is_collations.test b/mysql-test/suite/funcs_1/t/is_collations.test index db34a7b77b1..aa199b512bc 100644 --- a/mysql-test/suite/funcs_1/t/is_collations.test +++ b/mysql-test/suite/funcs_1/t/is_collations.test @@ -83,7 +83,7 @@ INSERT INTO information_schema.collations VALUES ( 'cp1251_bin', 'cp1251',50, '', '',0); --error ER_DBACCESS_DENIED_ERROR,ER_NON_UPDATABLE_TABLE -UPDATE information_schema.collations SET description = 'just updated'; +UPDATE information_schema.collations SET collation_name = 'just updated'; --error ER_DBACCESS_DENIED_ERROR DELETE FROM information_schema.collations WHERE table_name = 't1'; diff --git a/mysql-test/suite/galera/r/MDEV-29142.result b/mysql-test/suite/galera/r/MDEV-29142.result index 2528520e236..2e567666c47 100644 --- a/mysql-test/suite/galera/r/MDEV-29142.result +++ b/mysql-test/suite/galera/r/MDEV-29142.result @@ -11,7 +11,7 @@ call mtr.add_suppression("WSREP: Failed to open table mysql.wsrep_streaming_log call mtr.add_suppression("WSREP: Failed to open SR table for write"); call mtr.add_suppression("WSREP: Failed to recover SR transactions from schema: wsrep_on : 0"); call mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on.*"); -SET @@global.tx_read_only = ON; +SET @@global.transaction_read_only = ON; SET default_storage_engine = SEQUENCE; create table t1 (c1 int); ERROR HY000: Can't create table `test`.`t1` (errno: 131 "Command not supported by the engine") diff --git a/mysql-test/suite/galera/t/MDEV-29142.test b/mysql-test/suite/galera/t/MDEV-29142.test index 7e9776b005b..316b7f26000 100644 --- a/mysql-test/suite/galera/t/MDEV-29142.test +++ b/mysql-test/suite/galera/t/MDEV-29142.test @@ -18,7 +18,7 @@ call mtr.add_suppression("WSREP: Failed to open SR table for write"); call mtr.add_suppression("WSREP: Failed to recover SR transactions from schema: wsrep_on : 0"); call mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on.*"); -SET @@global.tx_read_only = ON; +SET @@global.transaction_read_only = ON; --error 0,1286 SET default_storage_engine = SEQUENCE; --error 1005 diff --git a/mysql-test/suite/innodb/r/defrag_mdl-9155.result b/mysql-test/suite/innodb/r/defrag_mdl-9155.result deleted file mode 100644 index b1b70de3373..00000000000 --- a/mysql-test/suite/innodb/r/defrag_mdl-9155.result +++ /dev/null @@ -1,22 +0,0 @@ -set global innodb_defragment=1; -Warnings: -Warning 1287 '@@innodb_defragment' is deprecated and will be removed in a future release -create table t1 (a int not null primary key auto_increment, b varchar(256), key second(a, b)) engine=innodb; -insert t1 select null, repeat('a', 256) from seq_1_to_100; -select count(*) from t1; -count(*) -100 -connect con1,localhost,root; -start transaction; -select count(*) from t1; -count(*) -100 -connection default; -optimize table t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -connection con1; -drop table t1; -set global innodb_defragment=default; -Warnings: -Warning 1287 '@@innodb_defragment' is deprecated and will be removed in a future release diff --git a/mysql-test/suite/innodb/r/innodb-blob.result b/mysql-test/suite/innodb/r/innodb-blob.result index 8173d30e92c..63c52f2e6e5 100644 --- a/mysql-test/suite/innodb/r/innodb-blob.result +++ b/mysql-test/suite/innodb/r/innodb-blob.result @@ -29,8 +29,8 @@ INSERT INTO t1 VALUES (3,REPEAT('c',50000)); connection con1; SET DEBUG_SYNC='now WAIT_FOR rec_not_blob'; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation READ-UNCOMMITTED SELECT a, RIGHT(b,20) FROM t1; a RIGHT(b,20) @@ -60,8 +60,8 @@ UPDATE t3 SET c=REPEAT('f',3000) WHERE a=1; connect con1,localhost,root,,; SET DEBUG_SYNC='now WAIT_FOR go_sel'; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation READ-UNCOMMITTED SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3; a RIGHT(b,20) RIGHT(c,20) diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result index a4c1115bfd4..b3e1eec3382 100644 --- a/mysql-test/suite/innodb/r/innodb.result +++ b/mysql-test/suite/innodb/r/innodb.result @@ -1017,8 +1017,8 @@ SET sql_mode = default; create table t1 (id int unsigned not null auto_increment, code tinyint unsigned not null, name char(20) not null, primary key (id), key (code), unique (name)) engine=innodb; BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; -SELECT @@tx_isolation,@@global.tx_isolation; -@@tx_isolation @@global.tx_isolation +SELECT @@transaction_isolation, @@global.transaction_isolation; +@@transaction_isolation @@global.transaction_isolation SERIALIZABLE REPEATABLE-READ insert into t1 (code, name) values (1, 'Tim'), (1, 'Monty'), (2, 'David'); select id, code, name from t1 order by id; @@ -3141,7 +3141,7 @@ CONNECT c1,localhost,root,,; CONNECT c2,localhost,root,,; connection c1; SET binlog_format='MIXED'; -SET TX_ISOLATION='read-committed'; +SET TRANSACTION_ISOLATION='read-committed'; SET AUTOCOMMIT=0; DROP TABLE IF EXISTS t1, t2; Warnings: @@ -3152,7 +3152,7 @@ SELECT * FROM t2; a connection c2; SET binlog_format='MIXED'; -SET TX_ISOLATION='read-committed'; +SET TRANSACTION_ISOLATION='read-committed'; SET AUTOCOMMIT=0; INSERT INTO t1 VALUES (1); COMMIT; @@ -3166,13 +3166,13 @@ CONNECT c1,localhost,root,,; CONNECT c2,localhost,root,,; connection c1; SET binlog_format='MIXED'; -SET TX_ISOLATION='read-committed'; +SET TRANSACTION_ISOLATION='read-committed'; SET AUTOCOMMIT=0; SELECT * FROM t2; a connection c2; SET binlog_format='MIXED'; -SET TX_ISOLATION='read-committed'; +SET TRANSACTION_ISOLATION='read-committed'; SET AUTOCOMMIT=0; INSERT INTO t1 VALUES (2); COMMIT; diff --git a/mysql-test/suite/innodb/r/innodb_bug40360.result b/mysql-test/suite/innodb/r/innodb_bug40360.result index ef4cf463903..46456bde3c8 100644 --- a/mysql-test/suite/innodb/r/innodb_bug40360.result +++ b/mysql-test/suite/innodb/r/innodb_bug40360.result @@ -1,4 +1,4 @@ -SET TX_ISOLATION='READ-COMMITTED'; +SET TRANSACTION_ISOLATION='READ-COMMITTED'; CREATE TABLE bug40360 (a INT) engine=innodb; INSERT INTO bug40360 VALUES (1); DROP TABLE bug40360; diff --git a/mysql-test/suite/innodb/r/innodb_bug49164.result b/mysql-test/suite/innodb/r/innodb_bug49164.result index 857cd2851f2..8cac84b4eda 100644 --- a/mysql-test/suite/innodb/r/innodb_bug49164.result +++ b/mysql-test/suite/innodb/r/innodb_bug49164.result @@ -1,7 +1,7 @@ connect con1,localhost,root,,; connect con2,localhost,root,,; connection con1; -SET tx_isolation = 'READ-COMMITTED'; +SET transaction_isolation = 'READ-COMMITTED'; CREATE TABLE bug49164 (a INT, b BIGINT, c TINYINT, PRIMARY KEY (a, b)) ENGINE=InnoDB; insert into bug49164 values (1,1,1), (2,2,2), (3,3,3); @@ -21,7 +21,7 @@ a b c begin; update bug49164 set c=7; connection con2; -SET tx_isolation = 'READ-COMMITTED'; +SET transaction_isolation = 'READ-COMMITTED'; begin; select * from bug49164; a b c diff --git a/mysql-test/suite/innodb/r/innodb_bug53756.result b/mysql-test/suite/innodb/r/innodb_bug53756.result index daa6113f8d4..100d37154ce 100644 --- a/mysql-test/suite/innodb/r/innodb_bug53756.result +++ b/mysql-test/suite/innodb/r/innodb_bug53756.result @@ -9,8 +9,8 @@ COMMIT; # Start a transaction in the default connection for isolation. START TRANSACTION; -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation READ-COMMITTED SELECT * FROM bug_53756; pk c1 @@ -20,38 +20,38 @@ pk c1 4 44 connect con1,localhost,root,,; START TRANSACTION; -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation READ-COMMITTED DELETE FROM bug_53756 WHERE pk=1; connect con2,localhost,root,,; START TRANSACTION; -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation READ-COMMITTED DELETE FROM bug_53756 WHERE pk=2; connect con3,localhost,root,,; START TRANSACTION; -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation READ-COMMITTED UPDATE bug_53756 SET c1=77 WHERE pk=3; connect con4,localhost,root,,; START TRANSACTION; -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation READ-COMMITTED UPDATE bug_53756 SET c1=88 WHERE pk=4; connect con5,localhost,root,,; START TRANSACTION; -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation READ-COMMITTED INSERT INTO bug_53756 VALUES(5, 55); connect con6,localhost,root,,; START TRANSACTION; -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation READ-COMMITTED INSERT INTO bug_53756 VALUES(6, 66); connection con1; diff --git a/mysql-test/suite/innodb/r/innodb_defrag_binlog.result b/mysql-test/suite/innodb/r/innodb_defrag_binlog.result deleted file mode 100644 index b97061cc9db..00000000000 --- a/mysql-test/suite/innodb/r/innodb_defrag_binlog.result +++ /dev/null @@ -1,31 +0,0 @@ -include/master-slave.inc -[connection master] -drop table if exists t1; -create table t1(a int not null primary key auto_increment, b varchar(256), key second(b)) engine=innodb; -insert into t1 values (1, REPEAT("a", 256)); -insert into t1 values (2, REPEAT("a", 256)); -optimize table t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -drop table t1; -include/show_binlog_events.inc -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `t1` /* generated by server */ -master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test`; create table t1(a int not null primary key auto_increment, b varchar(256), key second(b)) engine=innodb -master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Annotate_rows # # insert into t1 values (1, REPEAT("a", 256)) -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Annotate_rows # # insert into t1 values (2, REPEAT("a", 256)) -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test`; optimize table t1 -master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */ -include/rpl_end.inc diff --git a/mysql-test/suite/innodb/r/innodb_defrag_concurrent.result b/mysql-test/suite/innodb/r/innodb_defrag_concurrent.result deleted file mode 100644 index 72d520a61b4..00000000000 --- a/mysql-test/suite/innodb/r/innodb_defrag_concurrent.result +++ /dev/null @@ -1,110 +0,0 @@ -SET @n_pages= @@GLOBAL.innodb_defragment_n_pages; -SET @accuracy= @@GLOBAL.innodb_defragment_stats_accuracy; -SET @sp= @@GLOBAL.innodb_stats_persistent; -SET GLOBAL innodb_stats_persistent = 0; -set global innodb_defragment_stats_accuracy = 80; -Warnings: -Warning 1287 '@@innodb_defragment_stats_accuracy' is deprecated and will be removed in a future release -CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, -b VARCHAR(256), -c INT, -g GEOMETRY NOT NULL, -t VARCHAR(256), -KEY second(a, b), -KEY third(c), -SPATIAL gk(g), -FULLTEXT INDEX fti(t)) ENGINE=INNODB; -connect con1,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK; -connect con2,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK; -connect con3,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK; -connect con4,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK; -connection default; -SET @@global.innodb_defragment_n_pages = 20; -Warnings: -Warning 1287 '@@innodb_defragment_n_pages' is deprecated and will be removed in a future release -CREATE TEMPORARY TABLE tt (a INT, KEY(a)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; -INSERT INTO tt SELECT 0 FROM seq_1_to_180; -INSERT INTO tt SELECT 5 FROM seq_1_to_160; -INSERT INTO tt SELECT 1 FROM seq_1_to_1000; -OPTIMIZE TABLE tt; -Table Op Msg_type Msg_text -test.tt optimize note Table does not support optimize, doing recreate + analyze instead -test.tt optimize status OK -select count(*) from t1; -count(*) -20000 -select count(*) from t1 force index (second); -count(*) -20000 -select count(*) from t1 force index (third); -count(*) -20000 -select count(*) from t1; -count(*) -15800 -select count(*) from t1 force index (second); -count(*) -15800 -select count(*) from t1 force index (third); -count(*) -15800 -select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed'); -count(stat_value) > 0 -0 -select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split'); -count(stat_value) > 0 -1 -select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag'); -count(stat_value) > 0 -1 -connection con1; -optimize table t1;; -connection default; -INSERT INTO t1 VALUES (400000, REPEAT('A', 256),300000, Point(1,1),'More like a test but different.');; -connection con2; -INSERT INTO t1 VALUES (500000, REPEAT('A', 256),400000, Point(1,1),'Totally different text book.');; -connection con3; -DELETE FROM t1 where a between 1 and 100;; -connection con4; -UPDATE t1 SET c = c + 1 where c between 2000 and 8000;; -connection con1; -connection con2; -connection con3; -connection con4; -connection default; -disconnect con1; -disconnect con2; -disconnect con3; -disconnect con4; -optimize table t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -check table t1 extended; -Table Op Msg_type Msg_text -test.t1 check status OK -select count(*) from t1; -count(*) -15723 -select count(*) from t1 force index (second); -count(*) -15723 -select count(*) from t1 force index (third); -count(*) -15723 -select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed'); -count(stat_value) > 0 -1 -select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split'); -count(stat_value) > 0 -1 -select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag'); -count(stat_value) > 0 -1 -drop table t1; -SET GLOBAL innodb_defragment_n_pages = @n_pages; -Warnings: -Warning 1287 '@@innodb_defragment_n_pages' is deprecated and will be removed in a future release -SET GLOBAL innodb_defragment_stats_accuracy = @accuracy; -Warnings: -Warning 1287 '@@innodb_defragment_stats_accuracy' is deprecated and will be removed in a future release -SET GLOBAL innodb_stats_persistent = @sp; diff --git a/mysql-test/suite/innodb/r/innodb_defrag_stats.result b/mysql-test/suite/innodb/r/innodb_defrag_stats.result deleted file mode 100644 index 1753ce36bed..00000000000 --- a/mysql-test/suite/innodb/r/innodb_defrag_stats.result +++ /dev/null @@ -1,139 +0,0 @@ -SET GLOBAL innodb_defragment_stats_accuracy = 20; -Warnings: -Warning 1287 '@@innodb_defragment_stats_accuracy' is deprecated and will be removed in a future release -DELETE FROM mysql.innodb_index_stats; -# Create table. -CREATE TABLE t1 (a INT PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), -KEY SECOND(a, b)) ENGINE=INNODB STATS_PERSISTENT=0; -INSERT INTO t1 SELECT 100*FLOOR(seq/70)+seq%70, REPEAT('A', 256) -FROM seq_1_to_1024; -# Not enough page splits to trigger persistent stats write yet. -SELECT * FROM mysql.innodb_index_stats; -database_name table_name index_name last_update stat_name stat_value sample_size stat_description -INSERT INTO t1 SELECT 100*FLOOR(seq/70)+seq%70, REPEAT('A', 256) -FROM seq_1025_to_1433; -BEGIN; -INSERT INTO t1 SELECT 100*20+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*19+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*18+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*17+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*16+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*15+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*14+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*13+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*12+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*11+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*10+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*9+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*8+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*7+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*6+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*5+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*4+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*3+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*2+seq, REPEAT('A', 256) -FROM seq_70_to_99; -INSERT INTO t1 SELECT 100*1+seq, REPEAT('A', 256) -FROM seq_70_to_99; -ROLLBACK; -SELECT @@GLOBAL.innodb_force_recovery<2 "have background defragmentation"; -have background defragmentation -1 -SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats; -table_name index_name stat_name -t1 PRIMARY n_leaf_pages_defrag -t1 PRIMARY n_leaf_pages_reserved -t1 PRIMARY n_page_split -t1 SECOND n_leaf_pages_defrag -t1 SECOND n_leaf_pages_reserved -t1 SECOND n_page_split -optimize table t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats; -table_name index_name stat_name -t1 PRIMARY n_leaf_pages_defrag -t1 PRIMARY n_leaf_pages_reserved -t1 PRIMARY n_page_split -t1 PRIMARY n_pages_freed -t1 SECOND n_leaf_pages_defrag -t1 SECOND n_leaf_pages_reserved -t1 SECOND n_page_split -t1 SECOND n_pages_freed -set global innodb_defragment_stats_accuracy = 40; -Warnings: -Warning 1287 '@@innodb_defragment_stats_accuracy' is deprecated and will be removed in a future release -INSERT INTO t1 (b) SELECT b from t1; -SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats; -table_name index_name stat_name -t1 PRIMARY n_leaf_pages_defrag -t1 PRIMARY n_leaf_pages_reserved -t1 PRIMARY n_page_split -t1 PRIMARY n_pages_freed -t1 SECOND n_leaf_pages_defrag -t1 SECOND n_leaf_pages_reserved -t1 SECOND n_page_split -t1 SECOND n_pages_freed -INSERT INTO t1 (b) SELECT b from t1; -SELECT stat_name FROM mysql.innodb_index_stats WHERE table_name='t1'; -stat_name -n_leaf_pages_defrag -n_leaf_pages_defrag -n_leaf_pages_reserved -n_leaf_pages_reserved -n_page_split -n_page_split -n_pages_freed -n_pages_freed -# Table rename should cause stats rename. -rename table t1 to t2; -SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats; -table_name index_name stat_name -t2 PRIMARY n_leaf_pages_defrag -t2 PRIMARY n_leaf_pages_reserved -t2 PRIMARY n_page_split -t2 PRIMARY n_pages_freed -t2 SECOND n_leaf_pages_defrag -t2 SECOND n_leaf_pages_reserved -t2 SECOND n_page_split -t2 SECOND n_pages_freed -drop index SECOND on t2; -# -# MDEV-26636: Statistics must not be written for temporary tables -# -SET GLOBAL innodb_defragment_stats_accuracy = 1; -Warnings: -Warning 1287 '@@innodb_defragment_stats_accuracy' is deprecated and will be removed in a future release -CREATE TEMPORARY TABLE t (a INT PRIMARY KEY, c CHAR(255) NOT NULL) -ENGINE=InnoDB; -INSERT INTO t SELECT seq, '' FROM seq_1_to_100; -# restart -SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats; -table_name index_name stat_name -t2 PRIMARY n_leaf_pages_defrag -t2 PRIMARY n_leaf_pages_reserved -t2 PRIMARY n_page_split -t2 PRIMARY n_pages_freed -# Clean up -ALTER TABLE t2 STATS_PERSISTENT=1; -DROP TABLE t2; -SELECT * FROM mysql.innodb_index_stats; -database_name table_name index_name last_update stat_name stat_value sample_size stat_description diff --git a/mysql-test/suite/innodb/r/innodb_defrag_stats_many_tables.result b/mysql-test/suite/innodb/r/innodb_defrag_stats_many_tables.result deleted file mode 100644 index 37049b6386e..00000000000 --- a/mysql-test/suite/innodb/r/innodb_defrag_stats_many_tables.result +++ /dev/null @@ -1,42 +0,0 @@ -DROP TABLE if exists t1; -SET @start_table_definition_cache = @@global.table_definition_cache; -SET @@global.table_definition_cache = 400; -SET @start_flush_log_at_trx_commit = @@global.innodb_flush_log_at_trx_commit; -SET @@global.innodb_flush_log_at_trx_commit=2; -SET @start_innodb_defragment_stats_accuracy = @@global.innodb_defragment_stats_accuracy; -SET @@global.innodb_defragment_stats_accuracy = 80; -Warnings: -Warning 1287 '@@innodb_defragment_stats_accuracy' is deprecated and will be removed in a future release -CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), KEY SECOND(a, b)) ENGINE=INNODB; -INSERT INTO t1 VALUES(1, REPEAT('A', 256)); -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -select stat_value > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name = 'n_page_split'; -stat_value > 0 -Create 505 table to overflow the table cache. -Sleep for a while to make sure t1 is evicted. -select sleep(15); -sleep(15) -0 -Reload t1 to get defrag stats from persistent storage -INSERT INTO t1 (b) SELECT b from t1; -make sure the stats thread will wake up and do the write even if there's a race condition between set and reset. -select sleep(15); -sleep(15) -0 -select stat_value > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name = 'n_page_split'; -stat_value > 0 -SET @@global.innodb_defragment_stats_accuracy = @start_innodb_defragment_stats_accuracy; -Warnings: -Warning 1287 '@@innodb_defragment_stats_accuracy' is deprecated and will be removed in a future release -SET @@global.table_definition_cache = @start_table_definition_cache; -DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb_defragment.result b/mysql-test/suite/innodb/r/innodb_defragment.result deleted file mode 100644 index 72471060668..00000000000 --- a/mysql-test/suite/innodb/r/innodb_defragment.result +++ /dev/null @@ -1,139 +0,0 @@ -set global innodb_defragment_stats_accuracy = 80; -Warnings: -Warning 1287 '@@innodb_defragment_stats_accuracy' is deprecated and will be removed in a future release -CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), KEY SECOND(a, b)) ENGINE=INNODB; -optimize table t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -INSERT INTO t1 VALUES (100000, REPEAT('A', 256)); -INSERT INTO t1 VALUES (200000, REPEAT('A', 256)); -INSERT INTO t1 VALUES (300000, REPEAT('A', 256)); -INSERT INTO t1 VALUES (400000, REPEAT('A', 256)); -optimize table t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -create procedure defragment() -begin -set @i = 0; -repeat -set @i = @i + 1; -optimize table t1; -until @i = 3 end repeat; -end // -select count(stat_value) from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed'); -count(stat_value) -0 -select count(stat_value) from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split'); -count(stat_value) -2 -select count(stat_value) from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag'); -count(stat_value) -2 -select count(*) from t1; -count(*) -10004 -connect con1,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK; -connection con1; -call defragment(); -connection default; -connection con1; -connection default; -disconnect con1; -optimize table t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -# restart -select count(*) from t1; -count(*) -7904 -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed'); -count(stat_value) = 0 -0 -select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split'); -count(stat_value) > 0 -1 -select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag'); -count(stat_value) > 0 -1 -select count(*) from t1 force index (second); -count(*) -7904 -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_pages_freed'); -count(stat_value) = 0 -1 -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_page_split'); -count(stat_value) = 0 -1 -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_leaf_pages_defrag'); -count(stat_value) = 0 -1 -SET @@global.innodb_defragment_n_pages = 3; -Warnings: -Warning 1287 '@@innodb_defragment_n_pages' is deprecated and will be removed in a future release -optimize table t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -# restart -select count(stat_value) < 3 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed'); -count(stat_value) < 3 -1 -select count(stat_value) < 3 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split'); -count(stat_value) < 3 -1 -select count(stat_value) < 3 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag'); -count(stat_value) < 3 -1 -select count(*) from t1; -count(*) -6904 -select count(stat_value) < 3 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed'); -count(stat_value) < 3 -1 -select count(stat_value) < 3 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split'); -count(stat_value) < 3 -1 -select count(stat_value) < 3 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag'); -count(stat_value) < 3 -1 -select count(*) from t1 force index (second); -count(*) -6904 -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_pages_freed'); -count(stat_value) = 0 -1 -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_page_split'); -count(stat_value) = 0 -1 -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_leaf_pages_defrag'); -count(stat_value) = 0 -1 -SET @@global.innodb_defragment_n_pages = 10; -Warnings: -Warning 1287 '@@innodb_defragment_n_pages' is deprecated and will be removed in a future release -optimize table t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -# restart -select count(stat_value) > 1 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed'); -count(stat_value) > 1 -1 -select count(stat_value) > 1 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split'); -count(stat_value) > 1 -1 -select count(stat_value) > 1 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag'); -count(stat_value) > 1 -1 -select count(*) from t1 force index (second); -count(*) -6904 -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_pages_freed'); -count(stat_value) = 0 -1 -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_page_split'); -count(stat_value) = 0 -1 -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_leaf_pages_defrag'); -count(stat_value) = 0 -1 -DROP PROCEDURE defragment; -DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb_defragment_fill_factor.result b/mysql-test/suite/innodb/r/innodb_defragment_fill_factor.result deleted file mode 100644 index 8453050a92a..00000000000 --- a/mysql-test/suite/innodb/r/innodb_defragment_fill_factor.result +++ /dev/null @@ -1,118 +0,0 @@ -Testing tables with large records -CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), c VARCHAR(256), KEY SECOND(a, b,c)) ENGINE=INNODB; -INSERT INTO t1 VALUES (1, REPEAT('A', 256), REPEAT('B', 256)); -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -SET GLOBAL innodb_fast_shutdown = 0; -# restart -optimize table t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -select count(*) from t1; -count(*) -927 -select count(*) from t1 force index (second); -count(*) -927 -# A few more insertions on the page should not cause a page split. -insert into t1 values (81, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (83, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (87, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (82, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (86, REPEAT('A', 256), REPEAT('B', 256)); -# Insert more rows to cause a page split -insert into t1 values (180, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (181, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (182, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (183, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (184, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (185, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (186, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (187, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (188, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (189, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (190, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (191, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (192, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (193, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (194, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (195, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (196, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (197, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (198, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (199, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (200, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (201, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (202, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (203, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (204, REPEAT('A', 256), REPEAT('B', 256)); -DROP TABLE t1; -Testing table with small records -CREATE TABLE t2 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(16), c VARCHAR(32), KEY SECOND(a,b,c)) ENGINE=INNODB; -SET GLOBAL innodb_fast_shutdown = 0; -# restart -optimize table t2; -Table Op Msg_type Msg_text -test.t2 optimize status OK -select count(*) from t2; -count(*) -3701 -select count(*) from t2 force index(second); -count(*) -3701 -The page should have room for about 20 insertions -insert into t2 values(1181, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1191, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1182, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1192, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1183, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1193, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1184, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1194, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1185, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1195, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1186, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1196, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1187, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1197, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1188, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1198, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1189, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1199, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1190, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1180, REPEAT('A', 16), REPEAT('B',32)); -# Insert more rows to cause a page split -insert into t2 values (180, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (181, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (182, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (183, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (184, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (185, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (186, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (187, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (188, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (189, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (190, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (191, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (192, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (193, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (194, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (195, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (196, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (197, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (198, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (199, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (200, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (201, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (202, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (203, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (204, REPEAT('A', 16), REPEAT('B', 32)); -DROP TABLE t2; diff --git a/mysql-test/suite/innodb/r/innodb_defragment_small.result b/mysql-test/suite/innodb/r/innodb_defragment_small.result deleted file mode 100644 index 6b80637f3f8..00000000000 --- a/mysql-test/suite/innodb/r/innodb_defragment_small.result +++ /dev/null @@ -1,46 +0,0 @@ -SET @innodb_defragment_orig=@@GLOBAL.innodb_defragment; -SET @innodb_optimize_fulltext_orig=@@GLOBAL.innodb_optimize_fulltext_only; -SET GLOBAL innodb_defragment = 1; -Warnings: -Warning 1287 '@@innodb_defragment' is deprecated and will be removed in a future release -SET GLOBAL innodb_optimize_fulltext_only = 0; -# -# MDEV-12198 innodb_defragment=1 crashes server on -# OPTIMIZE TABLE when FULLTEXT index exists -# -CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(256), -KEY(a, b), FULLTEXT KEY(b)) ENGINE=INNODB; -OPTIMIZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -INSERT INTO t1 VALUES (100000, REPEAT('A', 256)); -INSERT INTO t1 VALUES (200000, REPEAT('A', 256)); -INSERT INTO t1 VALUES (300000, REPEAT('A', 256)); -INSERT INTO t1 VALUES (400000, REPEAT('A', 256)); -OPTIMIZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -# -# MDEV-15824 innodb_defragment=ON trumps -# innodb_optimize_fulltext_only=ON in OPTIMIZE TABLE -# -SET GLOBAL innodb_optimize_fulltext_only = 1; -OPTIMIZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -SET GLOBAL innodb_defragment = 0; -Warnings: -Warning 1287 '@@innodb_defragment' is deprecated and will be removed in a future release -OPTIMIZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -DROP TABLE t1; -CREATE TABLE t1 (c POINT PRIMARY KEY, SPATIAL INDEX(c)) ENGINE=InnoDB; -OPTIMIZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -DROP TABLE t1; -SET GLOBAL innodb_defragment = @innodb_defragment_orig; -Warnings: -Warning 1287 '@@innodb_defragment' is deprecated and will be removed in a future release -SET GLOBAL innodb_optimize_fulltext_only = @innodb_optimize_fulltext_orig; diff --git a/mysql-test/suite/innodb/r/innodb_lock_wait_timeout_1.result b/mysql-test/suite/innodb/r/innodb_lock_wait_timeout_1.result index 797c30d700f..52b85cf64e2 100644 --- a/mysql-test/suite/innodb/r/innodb_lock_wait_timeout_1.result +++ b/mysql-test/suite/innodb/r/innodb_lock_wait_timeout_1.result @@ -87,9 +87,9 @@ drop table t1, t2; # handler::unlock_row() in InnoDB does nothing. # Thus in order to reproduce the condition that led to the # warning, one needs to relax isolation by either -# setting a weaker tx_isolation value, or by turning on +# setting a weaker transaction_isolation value, or by turning on # the unsafe replication switch. -set @@session.tx_isolation="read-committed"; +set @@session.transaction_isolation="read-committed"; # Prepare data. We need a table with a unique index, # for join_read_key to be used. The other column # allows to control what passes WHERE clause filter. @@ -354,7 +354,7 @@ ERROR HY000: Lock wait timeout exceeded; try restarting transaction connection default; commit; disconnect con1; -set @@session.tx_isolation=default; +set @@session.transaction_isolation=default; drop table t1; # # End of 5.1 tests diff --git a/mysql-test/suite/innodb/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result index 7d5dc38f52c..18814e26c82 100644 --- a/mysql-test/suite/innodb/r/innodb_mysql.result +++ b/mysql-test/suite/innodb/r/innodb_mysql.result @@ -2301,10 +2301,10 @@ drop table t1, t2; # SET SESSION BINLOG_FORMAT=STATEMENT; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; -select @@session.sql_log_bin, @@session.binlog_format, @@session.tx_isolation; +select @@session.sql_log_bin, @@session.binlog_format, @@session.transaction_isolation; @@session.sql_log_bin 1 @@session.binlog_format STATEMENT -@@session.tx_isolation READ-COMMITTED +@@session.transaction_isolation READ-COMMITTED CREATE TABLE t1 ( a INT ) ENGINE=InnoDB; INSERT INTO t1 VALUES(1); DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb_status_variables.result b/mysql-test/suite/innodb/r/innodb_status_variables.result index a42f18ddd5b..2eeed4f169a 100644 --- a/mysql-test/suite/innodb/r/innodb_status_variables.result +++ b/mysql-test/suite/innodb/r/innodb_status_variables.result @@ -82,9 +82,6 @@ INNODB_HAVE_LZMA INNODB_HAVE_BZIP2 INNODB_HAVE_SNAPPY INNODB_HAVE_PUNCH_HOLE -INNODB_DEFRAGMENT_COMPRESSION_FAILURES -INNODB_DEFRAGMENT_FAILURES -INNODB_DEFRAGMENT_COUNT INNODB_INSTANT_ALTER_COLUMN INNODB_ONLINEDDL_ROWLOG_ROWS INNODB_ONLINEDDL_ROWLOG_PCT_USED diff --git a/mysql-test/suite/innodb/r/insert_into_empty.result b/mysql-test/suite/innodb/r/insert_into_empty.result index 45f3dd7654c..7bbbc2c5d43 100644 --- a/mysql-test/suite/innodb/r/insert_into_empty.result +++ b/mysql-test/suite/innodb/r/insert_into_empty.result @@ -41,7 +41,7 @@ SET GLOBAL innodb_adaptive_hash_index = @save_ahi; # CREATE TEMPORARY TABLE t (c INT) ENGINE=InnoDB; CREATE TEMPORARY TABLE t2 (c INT) ENGINE=InnoDB; -SET tx_read_only=1; +SET transaction_read_only=1; BEGIN; INSERT INTO t2 VALUES(0); INSERT INTO t VALUES(0); @@ -53,7 +53,7 @@ COMMIT; INSERT INTO t VALUES(0); DROP TEMPORARY TABLE t,t2; ERROR 25006: Cannot execute statement in a READ ONLY transaction -SET tx_read_only=0; +SET transaction_read_only=0; DROP TEMPORARY TABLE t,t2; # # MDEV-24818 Optimize multiple INSERT into empty table diff --git a/mysql-test/suite/innodb/r/instant_alter_debug.result b/mysql-test/suite/innodb/r/instant_alter_debug.result index 6efe5d7c734..5e1ec3aec60 100644 --- a/mysql-test/suite/innodb/r/instant_alter_debug.result +++ b/mysql-test/suite/innodb/r/instant_alter_debug.result @@ -277,16 +277,6 @@ SET GLOBAL innodb_limit_optimistic_insert_debug = 2; INSERT INTO t1 VALUES (1),(5),(4),(3),(2); SET GLOBAL innodb_limit_optimistic_insert_debug = @old_limit; ALTER TABLE t1 ADD COLUMN b INT, ALGORITHM=INSTANT; -SET @old_defragment = @@innodb_defragment; -SET GLOBAL innodb_defragment = 1; -Warnings: -Warning 1287 '@@innodb_defragment' is deprecated and will be removed in a future release -OPTIMIZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -SET GLOBAL innodb_defragment = @old_defragment; -Warnings: -Warning 1287 '@@innodb_defragment' is deprecated and will be removed in a future release ALTER TABLE t1 ADD vb INT AS (b) VIRTUAL; CHECK TABLE t1; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/innodb/r/temporary_table.result b/mysql-test/suite/innodb/r/temporary_table.result index ffcee726f0d..e90302daba4 100644 --- a/mysql-test/suite/innodb/r/temporary_table.result +++ b/mysql-test/suite/innodb/r/temporary_table.result @@ -709,12 +709,12 @@ UPDATE t1 SET a= 2; COMMIT; DROP TABLE t1; CREATE TEMPORARY TABLE t(c INT) ENGINE=InnoDB; -SET SESSION tx_read_only=TRUE; +SET SESSION TRANSACTION_READ_ONLY=TRUE; LOCK TABLE test.t READ; SELECT * FROM t; c INSERT INTO t VALUES(0xADC3); -SET SESSION tx_read_only=FALSE; +SET SESSION TRANSACTION_READ_ONLY=FALSE; DROP TABLE t; CREATE TEMPORARY TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); @@ -748,27 +748,27 @@ COMMIT; DROP TABLE t1; CREATE TEMPORARY TABLE tmp (a INT) ENGINE=InnoDB; INSERT INTO tmp () VALUES (),(); -SET TX_READ_ONLY= 1; +SET TRANSACTION_READ_ONLY= 1; INSERT INTO tmp SELECT * FROM tmp; -SET TX_READ_ONLY= 0; +SET TRANSACTION_READ_ONLY= 0; DROP TABLE tmp; SET sql_mode=''; -SET GLOBAL tx_read_only=TRUE; +SET GLOBAL TRANSACTION_READ_ONLY=TRUE; CREATE TEMPORARY TABLE t (c INT); -SET SESSION tx_read_only=DEFAULT; +SET SESSION TRANSACTION_READ_ONLY=DEFAULT; INSERT INTO t VALUES(1); INSERT INTO t SELECT * FROM t; -SET SESSION tx_read_only=FALSE; -SET GLOBAL tx_read_only=OFF; +SET SESSION TRANSACTION_READ_ONLY=FALSE; +SET GLOBAL TRANSACTION_READ_ONLY=OFF; DROP TABLE t; CREATE TEMPORARY TABLE t(a INT); -SET SESSION tx_read_only=ON; +SET SESSION TRANSACTION_READ_ONLY=ON; LOCK TABLE t READ; SELECT COUNT(*)FROM t; COUNT(*) 0 INSERT INTO t VALUES (0); -SET SESSION tx_read_only=OFF; +SET SESSION TRANSACTION_READ_ONLY=OFF; DROP TABLE t; CREATE TEMPORARY TABLE t (a INT) ENGINE=InnoDB; INSERT INTO t VALUES (1); diff --git a/mysql-test/suite/innodb/t/defrag_mdl-9155.test b/mysql-test/suite/innodb/t/defrag_mdl-9155.test deleted file mode 100644 index 1e1efb9c4c6..00000000000 --- a/mysql-test/suite/innodb/t/defrag_mdl-9155.test +++ /dev/null @@ -1,22 +0,0 @@ -# -# MDEV-9155 Enabling Defragmenting in 10.1.8 still causes OPTIMIZE TABLE to take metadatalocks -# -source include/have_innodb.inc; -source include/have_sequence.inc; - -set global innodb_defragment=1; -create table t1 (a int not null primary key auto_increment, b varchar(256), key second(a, b)) engine=innodb; -insert t1 select null, repeat('a', 256) from seq_1_to_100; -select count(*) from t1; - -connect (con1,localhost,root); -start transaction; -select count(*) from t1; - -connection default; -optimize table t1; - -connection con1; -drop table t1; - -set global innodb_defragment=default; diff --git a/mysql-test/suite/innodb/t/innodb-blob.test b/mysql-test/suite/innodb/t/innodb-blob.test index 301966fb41d..9ae13ca2fec 100644 --- a/mysql-test/suite/innodb/t/innodb-blob.test +++ b/mysql-test/suite/innodb/t/innodb-blob.test @@ -60,7 +60,7 @@ INSERT INTO t1 VALUES (3,REPEAT('c',50000)); connection con1; SET DEBUG_SYNC='now WAIT_FOR rec_not_blob'; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -SELECT @@tx_isolation; +SELECT @@transaction_isolation; # this one should see (3,NULL_BLOB) SELECT a, RIGHT(b,20) FROM t1; @@ -98,7 +98,7 @@ UPDATE t3 SET c=REPEAT('f',3000) WHERE a=1; connect (con1,localhost,root,,); SET DEBUG_SYNC='now WAIT_FOR go_sel'; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -SELECT @@tx_isolation; +SELECT @@transaction_isolation; SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3; set debug_sync='now SIGNAL go_upd'; diff --git a/mysql-test/suite/innodb/t/innodb.test b/mysql-test/suite/innodb/t/innodb.test index 9211a51dcfc..bb2eef7ba0c 100644 --- a/mysql-test/suite/innodb/t/innodb.test +++ b/mysql-test/suite/innodb/t/innodb.test @@ -724,7 +724,7 @@ create table t1 (id int unsigned not null auto_increment, code tinyint unsigned BEGIN; SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; -SELECT @@tx_isolation,@@global.tx_isolation; +SELECT @@transaction_isolation, @@global.transaction_isolation; insert into t1 (code, name) values (1, 'Tim'), (1, 'Monty'), (2, 'David'); select id, code, name from t1 order by id; COMMIT; @@ -2381,7 +2381,7 @@ CONNECT (c1,localhost,root,,); CONNECT (c2,localhost,root,,); CONNECTION c1; SET binlog_format='MIXED'; -SET TX_ISOLATION='read-committed'; +SET TRANSACTION_ISOLATION='read-committed'; SET AUTOCOMMIT=0; DROP TABLE IF EXISTS t1, t2; CREATE TABLE t1 ( a int ) ENGINE=InnoDB; @@ -2389,7 +2389,7 @@ CREATE TABLE t2 LIKE t1; SELECT * FROM t2; CONNECTION c2; SET binlog_format='MIXED'; -SET TX_ISOLATION='read-committed'; +SET TRANSACTION_ISOLATION='read-committed'; SET AUTOCOMMIT=0; INSERT INTO t1 VALUES (1); COMMIT; @@ -2401,12 +2401,12 @@ CONNECT (c1,localhost,root,,); CONNECT (c2,localhost,root,,); CONNECTION c1; SET binlog_format='MIXED'; -SET TX_ISOLATION='read-committed'; +SET TRANSACTION_ISOLATION='read-committed'; SET AUTOCOMMIT=0; SELECT * FROM t2; CONNECTION c2; SET binlog_format='MIXED'; -SET TX_ISOLATION='read-committed'; +SET TRANSACTION_ISOLATION='read-committed'; SET AUTOCOMMIT=0; INSERT INTO t1 VALUES (2); COMMIT; diff --git a/mysql-test/suite/innodb/t/innodb_bug40360.test b/mysql-test/suite/innodb/t/innodb_bug40360.test index f5187d55092..8e7b309e621 100644 --- a/mysql-test/suite/innodb/t/innodb_bug40360.test +++ b/mysql-test/suite/innodb/t/innodb_bug40360.test @@ -5,7 +5,7 @@ -- source include/not_embedded.inc -SET TX_ISOLATION='READ-COMMITTED'; +SET TRANSACTION_ISOLATION='READ-COMMITTED'; # This is the default since MySQL 5.1.29 SET BINLOG_FORMAT='STATEMENT'; diff --git a/mysql-test/suite/innodb/t/innodb_bug49164.test b/mysql-test/suite/innodb/t/innodb_bug49164.test index 159475ba10f..f19fb519168 100644 --- a/mysql-test/suite/innodb/t/innodb_bug49164.test +++ b/mysql-test/suite/innodb/t/innodb_bug49164.test @@ -8,7 +8,7 @@ connect (con1,localhost,root,,); connect (con2,localhost,root,,); connection con1; -SET tx_isolation = 'READ-COMMITTED'; +SET transaction_isolation = 'READ-COMMITTED'; CREATE TABLE bug49164 (a INT, b BIGINT, c TINYINT, PRIMARY KEY (a, b)) ENGINE=InnoDB; @@ -25,7 +25,7 @@ update bug49164 set c=7; connection con2; -SET tx_isolation = 'READ-COMMITTED'; +SET transaction_isolation = 'READ-COMMITTED'; begin; select * from bug49164; commit; diff --git a/mysql-test/suite/innodb/t/innodb_bug53756.test b/mysql-test/suite/innodb/t/innodb_bug53756.test index a676868aea7..86633e1c124 100644 --- a/mysql-test/suite/innodb/t/innodb_bug53756.test +++ b/mysql-test/suite/innodb/t/innodb_bug53756.test @@ -25,37 +25,37 @@ COMMIT; --echo --echo # Start a transaction in the default connection for isolation. START TRANSACTION; -SELECT @@tx_isolation; +SELECT @@transaction_isolation; SELECT * FROM bug_53756; --connect (con1,localhost,root,,) START TRANSACTION; -SELECT @@tx_isolation; +SELECT @@transaction_isolation; DELETE FROM bug_53756 WHERE pk=1; --connect (con2,localhost,root,,) START TRANSACTION; -SELECT @@tx_isolation; +SELECT @@transaction_isolation; DELETE FROM bug_53756 WHERE pk=2; --connect (con3,localhost,root,,) START TRANSACTION; -SELECT @@tx_isolation; +SELECT @@transaction_isolation; UPDATE bug_53756 SET c1=77 WHERE pk=3; --connect (con4,localhost,root,,) START TRANSACTION; -SELECT @@tx_isolation; +SELECT @@transaction_isolation; UPDATE bug_53756 SET c1=88 WHERE pk=4; --connect (con5,localhost,root,,) START TRANSACTION; -SELECT @@tx_isolation; +SELECT @@transaction_isolation; INSERT INTO bug_53756 VALUES(5, 55); --connect (con6,localhost,root,,) START TRANSACTION; -SELECT @@tx_isolation; +SELECT @@transaction_isolation; INSERT INTO bug_53756 VALUES(6, 66); --connection con1 diff --git a/mysql-test/suite/innodb/t/innodb_defrag_binlog.opt b/mysql-test/suite/innodb/t/innodb_defrag_binlog.opt deleted file mode 100644 index 8a432b8c76e..00000000000 --- a/mysql-test/suite/innodb/t/innodb_defrag_binlog.opt +++ /dev/null @@ -1,5 +0,0 @@ ---loose-innodb-buffer-pool-stats ---loose-innodb-buffer-page ---loose-innodb-buffer-page-lru ---binlog-format=row ---innodb-defragment=1
\ No newline at end of file diff --git a/mysql-test/suite/innodb/t/innodb_defrag_binlog.test b/mysql-test/suite/innodb/t/innodb_defrag_binlog.test deleted file mode 100644 index db6849f8477..00000000000 --- a/mysql-test/suite/innodb/t/innodb_defrag_binlog.test +++ /dev/null @@ -1,21 +0,0 @@ ---source include/have_innodb.inc ---source include/master-slave.inc ---source include/big_test.inc ---source include/not_valgrind.inc ---source include/not_embedded.inc - ---disable_warnings -drop table if exists t1; ---enable_warnings - -create table t1(a int not null primary key auto_increment, b varchar(256), key second(b)) engine=innodb; - -insert into t1 values (1, REPEAT("a", 256)); -insert into t1 values (2, REPEAT("a", 256)); -optimize table t1; - -drop table t1; - ---source include/show_binlog_events.inc - ---source include/rpl_end.inc diff --git a/mysql-test/suite/innodb/t/innodb_defrag_concurrent.opt b/mysql-test/suite/innodb/t/innodb_defrag_concurrent.opt deleted file mode 100644 index 3242c6cf2ab..00000000000 --- a/mysql-test/suite/innodb/t/innodb_defrag_concurrent.opt +++ /dev/null @@ -1,5 +0,0 @@ ---loose-innodb-buffer-pool-stats ---loose-innodb-buffer-page ---loose-innodb-buffer-page-lru ---innodb-log-buffer-size=3m ---innodb-defragment=1
\ No newline at end of file diff --git a/mysql-test/suite/innodb/t/innodb_defrag_concurrent.test b/mysql-test/suite/innodb/t/innodb_defrag_concurrent.test deleted file mode 100644 index 1e4e14eb7c6..00000000000 --- a/mysql-test/suite/innodb/t/innodb_defrag_concurrent.test +++ /dev/null @@ -1,143 +0,0 @@ ---source include/have_innodb.inc ---source include/big_test.inc ---source include/not_valgrind.inc ---source include/not_embedded.inc ---source include/have_sequence.inc - -SET @n_pages= @@GLOBAL.innodb_defragment_n_pages; -SET @accuracy= @@GLOBAL.innodb_defragment_stats_accuracy; -SET @sp= @@GLOBAL.innodb_stats_persistent; - -SET GLOBAL innodb_stats_persistent = 0; -set global innodb_defragment_stats_accuracy = 80; - -# Create table. -# -# TODO: Currently we do not defragment spatial indexes, -# because doing it properly would require -# appropriate logic around the SSN (split -# sequence number). -# -# Also do not defragment auxiliary tables related to FULLTEXT INDEX. -# -# Both types added to this test to make sure they do not cause -# problems. -# -CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, -b VARCHAR(256), -c INT, -g GEOMETRY NOT NULL, -t VARCHAR(256), -KEY second(a, b), -KEY third(c), -SPATIAL gk(g), -FULLTEXT INDEX fti(t)) ENGINE=INNODB; - -connect (con1,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); -connect (con2,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); -connect (con3,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); -connect (con4,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); - -connection default; - -SET @@global.innodb_defragment_n_pages = 20; - -CREATE TEMPORARY TABLE tt (a INT, KEY(a)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; -INSERT INTO tt SELECT 0 FROM seq_1_to_180; -INSERT INTO tt SELECT 5 FROM seq_1_to_160; -INSERT INTO tt SELECT 1 FROM seq_1_to_1000; -OPTIMIZE TABLE tt; - -let $data_size = 20000; -let $delete_size = 2000; - -# Populate table. -let $i = $data_size; ---disable_query_log -while ($i) -{ - eval - INSERT INTO t1 VALUES ($data_size + 1 - $i, REPEAT('A', 256), $i, Point($i,$i), 'This is a test message.'); - dec $i; -} ---enable_query_log - -select count(*) from t1; -select count(*) from t1 force index (second); -select count(*) from t1 force index (third); - -# Delete some data ---disable_query_log -let $size = $delete_size; -while ($size) -{ - let $j = 100 * $size; - eval delete from t1 where a between $j - 20 and $j; - dec $size; -} ---enable_query_log - -select count(*) from t1; -select count(*) from t1 force index (second); -select count(*) from t1 force index (third); - -# Above delete will free some pages and insert causes page split and these could cause defrag -select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed'); -select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split'); -select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag'); - -connection con1; ---send optimize table t1; - -connection default; ---send INSERT INTO t1 VALUES (400000, REPEAT('A', 256),300000, Point(1,1),'More like a test but different.'); - -connection con2; ---send INSERT INTO t1 VALUES (500000, REPEAT('A', 256),400000, Point(1,1),'Totally different text book.'); - -connection con3; ---send DELETE FROM t1 where a between 1 and 100; - -connection con4; ---send UPDATE t1 SET c = c + 1 where c between 2000 and 8000; - -connection con1; ---disable_result_log ---reap ---enable_result_log - -connection con2; ---reap - -connection con3; ---reap - -connection con4; ---reap - -connection default; ---reap - -disconnect con1; -disconnect con2; -disconnect con3; -disconnect con4; - -optimize table t1; -check table t1 extended; - -select count(*) from t1; -select count(*) from t1 force index (second); -select count(*) from t1 force index (third); - -# Now pages are freed -select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed'); -select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split'); -select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag'); - -drop table t1; - -# reset system -SET GLOBAL innodb_defragment_n_pages = @n_pages; -SET GLOBAL innodb_defragment_stats_accuracy = @accuracy; -SET GLOBAL innodb_stats_persistent = @sp; diff --git a/mysql-test/suite/innodb/t/innodb_defrag_stats.opt b/mysql-test/suite/innodb/t/innodb_defrag_stats.opt deleted file mode 100644 index d3525162f03..00000000000 --- a/mysql-test/suite/innodb/t/innodb_defrag_stats.opt +++ /dev/null @@ -1 +0,0 @@ ---innodb-defragment=1 diff --git a/mysql-test/suite/innodb/t/innodb_defrag_stats.test b/mysql-test/suite/innodb/t/innodb_defrag_stats.test deleted file mode 100644 index ef79d8d6ade..00000000000 --- a/mysql-test/suite/innodb/t/innodb_defrag_stats.test +++ /dev/null @@ -1,88 +0,0 @@ ---source include/have_innodb.inc ---source include/not_valgrind.inc ---source include/not_embedded.inc ---source include/have_sequence.inc - -SET GLOBAL innodb_defragment_stats_accuracy = 20; - -DELETE FROM mysql.innodb_index_stats; - ---echo # Create table. -CREATE TABLE t1 (a INT PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), - KEY SECOND(a, b)) ENGINE=INNODB STATS_PERSISTENT=0; - -INSERT INTO t1 SELECT 100*FLOOR(seq/70)+seq%70, REPEAT('A', 256) -FROM seq_1_to_1024; - ---echo # Not enough page splits to trigger persistent stats write yet. -SELECT * FROM mysql.innodb_index_stats; - -INSERT INTO t1 SELECT 100*FLOOR(seq/70)+seq%70, REPEAT('A', 256) -FROM seq_1025_to_1433; - -BEGIN; -let $num_delete = 20; -while ($num_delete) -{ - eval INSERT INTO t1 SELECT 100*$num_delete+seq, REPEAT('A', 256) - FROM seq_70_to_99; - dec $num_delete; -} -ROLLBACK; - -SELECT @@GLOBAL.innodb_force_recovery<2 "have background defragmentation"; - -# Wait for defrag_pool to be processed. - -let $wait_timeout=30; -let $wait_condition = SELECT COUNT(*)>0 FROM mysql.innodb_index_stats; ---source include/wait_condition.inc - ---sorted_result -SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats; - -optimize table t1; - ---sorted_result -SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats; - -set global innodb_defragment_stats_accuracy = 40; - -INSERT INTO t1 (b) SELECT b from t1; - ---sorted_result -SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats; - -INSERT INTO t1 (b) SELECT b from t1; - ---sorted_result -SELECT stat_name FROM mysql.innodb_index_stats WHERE table_name='t1'; - ---echo # Table rename should cause stats rename. -rename table t1 to t2; - ---sorted_result -SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats; - -drop index SECOND on t2; - ---echo # ---echo # MDEV-26636: Statistics must not be written for temporary tables ---echo # -SET GLOBAL innodb_defragment_stats_accuracy = 1; -CREATE TEMPORARY TABLE t (a INT PRIMARY KEY, c CHAR(255) NOT NULL) -ENGINE=InnoDB; -INSERT INTO t SELECT seq, '' FROM seq_1_to_100; - ---source include/restart_mysqld.inc - ---sorted_result -SELECT table_name, index_name, stat_name FROM mysql.innodb_index_stats; - ---echo # Clean up -# Starting with 10.6, DROP TABLE will not touch persistent statistics -# (not defragmentation statistics either) if the table has none! -ALTER TABLE t2 STATS_PERSISTENT=1; -DROP TABLE t2; - -SELECT * FROM mysql.innodb_index_stats; diff --git a/mysql-test/suite/innodb/t/innodb_defrag_stats_many_tables.opt b/mysql-test/suite/innodb/t/innodb_defrag_stats_many_tables.opt deleted file mode 100644 index d3525162f03..00000000000 --- a/mysql-test/suite/innodb/t/innodb_defrag_stats_many_tables.opt +++ /dev/null @@ -1 +0,0 @@ ---innodb-defragment=1 diff --git a/mysql-test/suite/innodb/t/innodb_defrag_stats_many_tables.test b/mysql-test/suite/innodb/t/innodb_defrag_stats_many_tables.test deleted file mode 100644 index a0f43fa6841..00000000000 --- a/mysql-test/suite/innodb/t/innodb_defrag_stats_many_tables.test +++ /dev/null @@ -1,77 +0,0 @@ ---source include/have_innodb.inc ---source include/big_test.inc ---source include/not_valgrind.inc ---source include/not_embedded.inc - ---disable_warnings -DROP TABLE if exists t1; ---enable_warnings - -let $num_tables = 505; - -SET @start_table_definition_cache = @@global.table_definition_cache; -SET @@global.table_definition_cache = 400; - -SET @start_flush_log_at_trx_commit = @@global.innodb_flush_log_at_trx_commit; -SET @@global.innodb_flush_log_at_trx_commit=2; - -# set stats accuracy to be pretty high so stats sync is easily triggered. -SET @start_innodb_defragment_stats_accuracy = @@global.innodb_defragment_stats_accuracy; -SET @@global.innodb_defragment_stats_accuracy = 80; - -# Create table. -CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), KEY SECOND(a, b)) ENGINE=INNODB; - -# Populate data -INSERT INTO t1 VALUES(1, REPEAT('A', 256)); -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; - -select stat_value > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name = 'n_page_split'; - -# Create many tables to over flow the table definition cache - ---echo Create $num_tables table to overflow the table cache. ---disable_query_log -let $count = $num_tables; -while ($count) -{ - EVAL CREATE TABLE t_$count (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT) ENGINE=INNODB; - EVAL INSERT INTO t_$count VALUES (1), (2); - dec $count; -} ---enable_query_log ---echo Sleep for a while to make sure t1 is evicted. -select sleep(15); - ---echo Reload t1 to get defrag stats from persistent storage -INSERT INTO t1 (b) SELECT b from t1; - ---echo make sure the stats thread will wake up and do the write even if there's a race condition between set and reset. -select sleep(15); - -select stat_value > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name = 'n_page_split'; - - -# Clean up -SET @@global.innodb_defragment_stats_accuracy = @start_innodb_defragment_stats_accuracy; -SET @@global.table_definition_cache = @start_table_definition_cache; ---disable_query_log -let $count = $num_tables; -while ($count) -{ - EVAL DROP TABLE t_$count; - dec $count; -} -set @@global.innodb_flush_log_at_trx_commit = @start_flush_log_at_trx_commit; ---enable_query_log -DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb_defragment.opt b/mysql-test/suite/innodb/t/innodb_defragment.opt deleted file mode 100644 index 12b046be786..00000000000 --- a/mysql-test/suite/innodb/t/innodb_defragment.opt +++ /dev/null @@ -1,4 +0,0 @@ ---loose-innodb-buffer-pool-stats ---loose-innodb-buffer-page ---loose-innodb-buffer-page-lru ---innodb-defragment=1 diff --git a/mysql-test/suite/innodb/t/innodb_defragment.test b/mysql-test/suite/innodb/t/innodb_defragment.test deleted file mode 100644 index 51ef78377cb..00000000000 --- a/mysql-test/suite/innodb/t/innodb_defragment.test +++ /dev/null @@ -1,157 +0,0 @@ ---source include/have_innodb.inc ---source include/big_test.inc ---source include/not_embedded.inc -# Valgrind is to slow for this test ---source include/not_valgrind.inc - -set global innodb_defragment_stats_accuracy = 80; - -# Create table. -CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), KEY SECOND(a, b)) ENGINE=INNODB; - -## Test-1 defragment an empty table -optimize table t1; - -## Test-2 defragment a single page table -INSERT INTO t1 VALUES (100000, REPEAT('A', 256)); -INSERT INTO t1 VALUES (200000, REPEAT('A', 256)); -INSERT INTO t1 VALUES (300000, REPEAT('A', 256)); -INSERT INTO t1 VALUES (400000, REPEAT('A', 256)); - -optimize table t1; - -## Test-3 defragment (somewhat) in parallel with delete queries -let $data_size = 10000; -let $delete_size = 100; - -delimiter //; -create procedure defragment() -begin - set @i = 0; - repeat - set @i = @i + 1; - optimize table t1; - until @i = 3 end repeat; -end // -delimiter ;// - - -# Populate table. -let $i = $data_size; ---disable_query_log -BEGIN; -while ($i) -{ - eval - INSERT INTO t1 VALUES ($data_size + 1 - $i, REPEAT('A', 256)); - dec $i; -} -COMMIT; ---enable_query_log - -select count(stat_value) from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed'); -select count(stat_value) from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split'); -select count(stat_value) from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag'); - -select count(*) from t1; - -connect (con1,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); - -connection con1; ---send call defragment() - -connection default; - ---disable_query_log -let $size = $delete_size; -while ($size) -{ - let $j = 100 * $size; - eval delete from t1 where a between $j - 20 and $j; - dec $size; -} ---enable_query_log - -connection con1; ---disable_result_log ---reap ---enable_result_log - -connection default; -disconnect con1; - -optimize table t1; - ---source include/restart_mysqld.inc -select count(*) from t1; - -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed'); -select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split'); -select count(stat_value) > 0 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag'); - -select count(*) from t1 force index (second); - -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_pages_freed'); -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_page_split'); -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_leaf_pages_defrag'); - -## Test-4 defragment with larger n_pages - -# delete some more records ---disable_query_log -let $size = $delete_size; -while ($size) -{ - let $j = 100 * $size; - eval delete from t1 where a between $j - 30 and $j - 20; - dec $size; -} ---enable_query_log - -SET @@global.innodb_defragment_n_pages = 3; - -# This will not reduce number of pages by a lot -optimize table t1; - ---source include/restart_mysqld.inc - -select count(stat_value) < 3 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed'); -select count(stat_value) < 3 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split'); -select count(stat_value) < 3 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag'); - -select count(*) from t1; - -# We didn't create large wholes with the previous deletion, so if innodb_defragment_n_pages = 3, we won't be able to free up many pages. - -select count(stat_value) < 3 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed'); -select count(stat_value) < 3 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split'); -select count(stat_value) < 3 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag'); - - -select count(*) from t1 force index (second); - -# Same holds for secondary index, not many pages are released. -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_pages_freed'); -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_page_split'); -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_leaf_pages_defrag'); - -SET @@global.innodb_defragment_n_pages = 10; - -optimize table t1; - ---source include/restart_mysqld.inc - -select count(stat_value) > 1 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_pages_freed'); -select count(stat_value) > 1 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_page_split'); -select count(stat_value) > 1 from mysql.innodb_index_stats where table_name like '%t1%' and stat_name in ('n_leaf_pages_defrag'); - - -select count(*) from t1 force index (second); - -# Same holds for secondary index, not many pages are released. -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_pages_freed'); -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_page_split'); -select count(stat_value) = 0 from mysql.innodb_index_stats where table_name like '%t1%' and index_name = 'second' and stat_name in ('n_leaf_pages_defrag'); - -DROP PROCEDURE defragment; -DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb_defragment_fill_factor.opt b/mysql-test/suite/innodb/t/innodb_defragment_fill_factor.opt deleted file mode 100644 index 6426bac41a0..00000000000 --- a/mysql-test/suite/innodb/t/innodb_defragment_fill_factor.opt +++ /dev/null @@ -1,4 +0,0 @@ ---loose-innodb-buffer-pool-stats ---loose-innodb-buffer-page ---loose-innodb-buffer-page-lru ---innodb-defragment=1
\ No newline at end of file diff --git a/mysql-test/suite/innodb/t/innodb_defragment_fill_factor.test b/mysql-test/suite/innodb/t/innodb_defragment_fill_factor.test deleted file mode 100644 index 3a5897b9911..00000000000 --- a/mysql-test/suite/innodb/t/innodb_defragment_fill_factor.test +++ /dev/null @@ -1,203 +0,0 @@ ---source include/have_innodb.inc ---source include/big_test.inc ---source include/not_valgrind.inc ---source include/not_embedded.inc ---source include/have_innodb_16k.inc - ---echo Testing tables with large records -# Create table. -CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), c VARCHAR(256), KEY SECOND(a, b,c)) ENGINE=INNODB; - -# Populate table. -INSERT INTO t1 VALUES (1, REPEAT('A', 256), REPEAT('B', 256)); -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; - ---disable_query_log -let $size = 10; -while ($size) -{ - let $j = 100 * $size; - eval delete from t1 where a between $j - 20 and $j + 5; - dec $size; -} ---enable_query_log - -SET GLOBAL innodb_fast_shutdown = 0; ---source include/restart_mysqld.inc -optimize table t1; - -select count(*) from t1; - ---let $primary_before = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY', Value, 1) - -select count(*) from t1 force index (second); - ---let $second_before = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second', Value, 1) - ---echo # A few more insertions on the page should not cause a page split. -insert into t1 values (81, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (83, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (87, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (82, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (86, REPEAT('A', 256), REPEAT('B', 256)); ---let $primary_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY', Value, 1) ---let $second_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second', Value, 1) - -if ($primary_before != $primary_after) { - --echo Insertion caused page split on primary, which should be avoided by innodb_defragment_fill_factor. -} - -if ($second_before != $second_after) { - --echo Insertion caused page split on second, which should be avoided by innodb_defragment_fill_factor. -} - ---echo # Insert more rows to cause a page split -insert into t1 values (180, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (181, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (182, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (183, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (184, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (185, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (186, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (187, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (188, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (189, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (190, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (191, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (192, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (193, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (194, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (195, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (196, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (197, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (198, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (199, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (200, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (201, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (202, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (203, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (204, REPEAT('A', 256), REPEAT('B', 256)); - ---let $primary_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY', Value, 1) - ---let $second_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second', Value, 1) - -if ($primary_before == $primary_after) { - --echo Too little space is reserved on primary index. -} - -if ($second_before == $second_after) { - --echo Too little space is reserved on second index. -} - -DROP TABLE t1; - ---echo Testing table with small records -CREATE TABLE t2 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(16), c VARCHAR(32), KEY SECOND(a,b,c)) ENGINE=INNODB; -# Populate table. ---disable_query_log -INSERT INTO t2 VALUES (1, REPEAT('A', 16), REPEAT('B', 32)); -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; ---enable_query_log - ---disable_query_log -let $size = 40; -while ($size) -{ - let $j = 100 * $size; - eval delete from t2 where a between $j - 20 and $j; - dec $size; -} ---enable_query_log - -SET GLOBAL innodb_fast_shutdown = 0; ---source include/restart_mysqld.inc -optimize table t2; - -select count(*) from t2; -select count(*) from t2 force index(second); - ---let $second_before = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t2%' and index_name = 'second', Value, 1) - ---echo The page should have room for about 20 insertions -insert into t2 values(1181, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1191, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1182, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1192, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1183, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1193, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1184, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1194, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1185, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1195, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1186, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1196, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1187, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1197, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1188, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1198, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1189, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1199, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1190, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1180, REPEAT('A', 16), REPEAT('B',32)); - ---let $second_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t2%' and index_name = 'second', Value, 1) - -if ($second_before != $second_after) { - --echo Insertion caused page split on second, which should be avoided by innodb_defragment_fill_factor. -} - ---echo # Insert more rows to cause a page split -insert into t2 values (180, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (181, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (182, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (183, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (184, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (185, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (186, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (187, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (188, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (189, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (190, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (191, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (192, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (193, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (194, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (195, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (196, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (197, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (198, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (199, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (200, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (201, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (202, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (203, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (204, REPEAT('A', 16), REPEAT('B', 32)); - ---let $second_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t2%' and index_name = 'second', Value, 1) - -if ($second_before == $second_after) { - --echo Too little space is reserved on second index. -} - -DROP TABLE t2; diff --git a/mysql-test/suite/innodb/t/innodb_defragment_small.test b/mysql-test/suite/innodb/t/innodb_defragment_small.test deleted file mode 100644 index 6259dac448e..00000000000 --- a/mysql-test/suite/innodb/t/innodb_defragment_small.test +++ /dev/null @@ -1,41 +0,0 @@ ---source include/have_innodb.inc - -SET @innodb_defragment_orig=@@GLOBAL.innodb_defragment; -SET @innodb_optimize_fulltext_orig=@@GLOBAL.innodb_optimize_fulltext_only; -SET GLOBAL innodb_defragment = 1; -SET GLOBAL innodb_optimize_fulltext_only = 0; - ---echo # ---echo # MDEV-12198 innodb_defragment=1 crashes server on ---echo # OPTIMIZE TABLE when FULLTEXT index exists ---echo # - -CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(256), - KEY(a, b), FULLTEXT KEY(b)) ENGINE=INNODB; -OPTIMIZE TABLE t1; - -INSERT INTO t1 VALUES (100000, REPEAT('A', 256)); -INSERT INTO t1 VALUES (200000, REPEAT('A', 256)); -INSERT INTO t1 VALUES (300000, REPEAT('A', 256)); -INSERT INTO t1 VALUES (400000, REPEAT('A', 256)); - -OPTIMIZE TABLE t1; - ---echo # ---echo # MDEV-15824 innodb_defragment=ON trumps ---echo # innodb_optimize_fulltext_only=ON in OPTIMIZE TABLE ---echo # - -SET GLOBAL innodb_optimize_fulltext_only = 1; -OPTIMIZE TABLE t1; -SET GLOBAL innodb_defragment = 0; -OPTIMIZE TABLE t1; - -DROP TABLE t1; - -CREATE TABLE t1 (c POINT PRIMARY KEY, SPATIAL INDEX(c)) ENGINE=InnoDB; -OPTIMIZE TABLE t1; -DROP TABLE t1; - -SET GLOBAL innodb_defragment = @innodb_defragment_orig; -SET GLOBAL innodb_optimize_fulltext_only = @innodb_optimize_fulltext_orig; diff --git a/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1.test b/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1.test index ea31d4a14c5..56a86a2c4d9 100644 --- a/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1.test +++ b/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1.test @@ -108,9 +108,9 @@ drop table t1, t2; --echo # handler::unlock_row() in InnoDB does nothing. --echo # Thus in order to reproduce the condition that led to the --echo # warning, one needs to relax isolation by either ---echo # setting a weaker tx_isolation value, or by turning on +--echo # setting a weaker transaction_isolation value, or by turning on --echo # the unsafe replication switch. -set @@session.tx_isolation="read-committed"; +set @@session.transaction_isolation="read-committed"; --echo # Prepare data. We need a table with a unique index, --echo # for join_read_key to be used. The other column @@ -236,7 +236,7 @@ connection default; commit; disconnect con1; -set @@session.tx_isolation=default; +set @@session.transaction_isolation=default; drop table t1; --echo # diff --git a/mysql-test/suite/innodb/t/innodb_mysql.test b/mysql-test/suite/innodb/t/innodb_mysql.test index d495186db25..c4453302166 100644 --- a/mysql-test/suite/innodb/t/innodb_mysql.test +++ b/mysql-test/suite/innodb/t/innodb_mysql.test @@ -41,7 +41,7 @@ drop table t1, t2; SET SESSION BINLOG_FORMAT=STATEMENT; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; -query_vertical select @@session.sql_log_bin, @@session.binlog_format, @@session.tx_isolation; +query_vertical select @@session.sql_log_bin, @@session.binlog_format, @@session.transaction_isolation; CREATE TABLE t1 ( a INT ) ENGINE=InnoDB; INSERT INTO t1 VALUES(1); DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/insert_into_empty.test b/mysql-test/suite/innodb/t/insert_into_empty.test index 8452cecf700..60f04133c82 100644 --- a/mysql-test/suite/innodb/t/insert_into_empty.test +++ b/mysql-test/suite/innodb/t/insert_into_empty.test @@ -47,7 +47,7 @@ SET GLOBAL innodb_adaptive_hash_index = @save_ahi; CREATE TEMPORARY TABLE t (c INT) ENGINE=InnoDB; CREATE TEMPORARY TABLE t2 (c INT) ENGINE=InnoDB; -SET tx_read_only=1; +SET transaction_read_only=1; BEGIN; INSERT INTO t2 VALUES(0); INSERT INTO t VALUES(0); @@ -60,7 +60,7 @@ INSERT INTO t VALUES(0); --error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION DROP TEMPORARY TABLE t,t2; -SET tx_read_only=0; +SET transaction_read_only=0; DROP TEMPORARY TABLE t,t2; --echo # diff --git a/mysql-test/suite/innodb/t/instant_alter_debug.test b/mysql-test/suite/innodb/t/instant_alter_debug.test index 64f94a78f2e..faa9bdbcf1c 100644 --- a/mysql-test/suite/innodb/t/instant_alter_debug.test +++ b/mysql-test/suite/innodb/t/instant_alter_debug.test @@ -325,11 +325,6 @@ SET GLOBAL innodb_limit_optimistic_insert_debug = @old_limit; ALTER TABLE t1 ADD COLUMN b INT, ALGORITHM=INSTANT; -SET @old_defragment = @@innodb_defragment; -SET GLOBAL innodb_defragment = 1; -OPTIMIZE TABLE t1; -SET GLOBAL innodb_defragment = @old_defragment; - # Exploit MDEV-17468 to force the table definition to be reloaded ALTER TABLE t1 ADD vb INT AS (b) VIRTUAL; CHECK TABLE t1; diff --git a/mysql-test/suite/innodb/t/temporary_table.test b/mysql-test/suite/innodb/t/temporary_table.test index b09ff7c7c30..a374f9e1bba 100644 --- a/mysql-test/suite/innodb/t/temporary_table.test +++ b/mysql-test/suite/innodb/t/temporary_table.test @@ -541,11 +541,11 @@ COMMIT; DROP TABLE t1; CREATE TEMPORARY TABLE t(c INT) ENGINE=InnoDB; -SET SESSION tx_read_only=TRUE; +SET SESSION TRANSACTION_READ_ONLY=TRUE; LOCK TABLE test.t READ; SELECT * FROM t; INSERT INTO t VALUES(0xADC3); -SET SESSION tx_read_only=FALSE; +SET SESSION TRANSACTION_READ_ONLY=FALSE; DROP TABLE t; CREATE TEMPORARY TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; @@ -585,27 +585,27 @@ DROP TABLE t1; CREATE TEMPORARY TABLE tmp (a INT) ENGINE=InnoDB; INSERT INTO tmp () VALUES (),(); -SET TX_READ_ONLY= 1; +SET TRANSACTION_READ_ONLY= 1; INSERT INTO tmp SELECT * FROM tmp; -SET TX_READ_ONLY= 0; +SET TRANSACTION_READ_ONLY= 0; DROP TABLE tmp; SET sql_mode=''; -SET GLOBAL tx_read_only=TRUE; +SET GLOBAL TRANSACTION_READ_ONLY=TRUE; CREATE TEMPORARY TABLE t (c INT); -SET SESSION tx_read_only=DEFAULT; +SET SESSION TRANSACTION_READ_ONLY=DEFAULT; INSERT INTO t VALUES(1); INSERT INTO t SELECT * FROM t; -SET SESSION tx_read_only=FALSE; -SET GLOBAL tx_read_only=OFF; +SET SESSION TRANSACTION_READ_ONLY=FALSE; +SET GLOBAL TRANSACTION_READ_ONLY=OFF; DROP TABLE t; CREATE TEMPORARY TABLE t(a INT); -SET SESSION tx_read_only=ON; +SET SESSION TRANSACTION_READ_ONLY=ON; LOCK TABLE t READ; SELECT COUNT(*)FROM t; INSERT INTO t VALUES (0); -SET SESSION tx_read_only=OFF; +SET SESSION TRANSACTION_READ_ONLY=OFF; DROP TABLE t; CREATE TEMPORARY TABLE t (a INT) ENGINE=InnoDB; diff --git a/mysql-test/suite/innodb_fts/r/innodb_fts_transaction.result b/mysql-test/suite/innodb_fts/r/innodb_fts_transaction.result index fc6a1d1afe7..f372652cb70 100644 --- a/mysql-test/suite/innodb_fts/r/innodb_fts_transaction.result +++ b/mysql-test/suite/innodb_fts/r/innodb_fts_transaction.result @@ -534,8 +534,8 @@ INSERT INTO t1 (a,b) VALUES ('Sævör grét', 'áðan því úlpan var ónýt'); connect con2,localhost,root,,; SET NAMES UTF8; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ CREATE FULLTEXT INDEX idx on t1 (a,b); INSERT INTO t1 (a,b) VALUES @@ -649,8 +649,8 @@ INSERT INTO t1 (a,b) VALUES ('Я могу есть стекло', 'оно мне Mне вредит'); connect con2,localhost,root,,; SET NAMES UTF8; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ CREATE FULLTEXT INDEX idx on t1 (a,b); INSERT INTO t1 (a,b) VALUES @@ -794,8 +794,8 @@ INSERT INTO t1 (a,b) VALUES ('Sævör grét', 'áðan því úlpan var ónýt'); connect con2,localhost,root,,; SET NAMES UTF8; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ CREATE FULLTEXT INDEX idx on t1 (a,b); INSERT INTO t1 (a,b) VALUES @@ -914,8 +914,8 @@ INSERT INTO t1 (a,b) VALUES ('Я могу есть стекло', 'оно мне Mне вредит'); connect con2,localhost,root,,; SET NAMES UTF8; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ CREATE FULLTEXT INDEX idx on t1 (a,b); INSERT INTO t1 (a,b) VALUES diff --git a/mysql-test/suite/innodb_fts/t/innodb_fts_transaction.test b/mysql-test/suite/innodb_fts/t/innodb_fts_transaction.test index 026aeb635cd..463de63c3f9 100644 --- a/mysql-test/suite/innodb_fts/t/innodb_fts_transaction.test +++ b/mysql-test/suite/innodb_fts/t/innodb_fts_transaction.test @@ -608,7 +608,7 @@ INSERT INTO t1 (a,b) VALUES --connect (con2,localhost,root,,) SET NAMES UTF8; -select @@session.tx_isolation; +select @@session.transaction_isolation; # Create the FTS index again CREATE FULLTEXT INDEX idx on t1 (a,b); @@ -704,7 +704,7 @@ INSERT INTO t1 (a,b) VALUES --connect (con2,localhost,root,,) SET NAMES UTF8; -select @@session.tx_isolation; +select @@session.transaction_isolation; # Create the FTS index again CREATE FULLTEXT INDEX idx on t1 (a,b); @@ -823,7 +823,7 @@ INSERT INTO t1 (a,b) VALUES --connect (con2,localhost,root,,) SET NAMES UTF8; -select @@session.tx_isolation; +select @@session.transaction_isolation; # Create the FTS index again CREATE FULLTEXT INDEX idx on t1 (a,b); @@ -919,7 +919,7 @@ INSERT INTO t1 (a,b) VALUES --connect (con2,localhost,root,,) SET NAMES UTF8; -select @@session.tx_isolation; +select @@session.transaction_isolation; # Create the FTS index again CREATE FULLTEXT INDEX idx on t1 (a,b); diff --git a/mysql-test/suite/innodb_gis/r/repeatable_spatial.result b/mysql-test/suite/innodb_gis/r/repeatable_spatial.result index 065312f612f..561b1f77ae7 100644 --- a/mysql-test/suite/innodb_gis/r/repeatable_spatial.result +++ b/mysql-test/suite/innodb_gis/r/repeatable_spatial.result @@ -19,8 +19,8 @@ COUNT(*) connect con1,localhost,root,,; connection con1; SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ; -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation REPEATABLE-READ SELECT COUNT(*) FROM tab; COUNT(*) @@ -32,8 +32,8 @@ c1 ST_AsText(c2) ST_AsText(c3) ST_AsText(c4) ST_AsText(c5) connect con2,localhost,root,,; connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation READ-COMMITTED START TRANSACTION; INSERT INTO tab(c1,c2,c3,c4,c5) @@ -106,8 +106,8 @@ COUNT(*) connect con1,localhost,root,,; connection con1; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation REPEATABLE-READ SELECT COUNT(*) FROM tab; COUNT(*) @@ -119,8 +119,8 @@ c1 ST_AsText(c2) ST_AsText(c3) ST_AsText(c4) ST_AsText(c5) connect con2,localhost,root,,; connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation READ-COMMITTED START TRANSACTION; INSERT INTO tab(c1,c2,c3,c4,c5) diff --git a/mysql-test/suite/innodb_gis/r/rtree_concurrent_srch.result b/mysql-test/suite/innodb_gis/r/rtree_concurrent_srch.result index 81b82691876..9d25d0e96b4 100644 --- a/mysql-test/suite/innodb_gis/r/rtree_concurrent_srch.result +++ b/mysql-test/suite/innodb_gis/r/rtree_concurrent_srch.result @@ -58,8 +58,8 @@ insert into t1 select * from t1; insert into t1 select * from t1; connection a; set session transaction isolation level serializable; -select @@tx_isolation; -@@tx_isolation +select @@transaction_isolation; +@@transaction_isolation SERIALIZABLE start transaction; set @g1 = ST_GeomFromText('Polygon((100 100, 100 110, 110 110, 110 100, 100 100))'); @@ -69,8 +69,8 @@ count(*) connect b,localhost,root,,; set session transaction isolation level serializable; set session innodb_lock_wait_timeout = 1; -select @@tx_isolation; -@@tx_isolation +select @@transaction_isolation; +@@transaction_isolation SERIALIZABLE insert into t1 select * from t1; insert into t1 select * from t1; @@ -92,8 +92,8 @@ connection b; select @@innodb_lock_wait_timeout; @@innodb_lock_wait_timeout 1 -select @@tx_isolation; -@@tx_isolation +select @@transaction_isolation; +@@transaction_isolation SERIALIZABLE insert into t1 select * from t1; ERROR HY000: Lock wait timeout exceeded; try restarting transaction @@ -120,8 +120,8 @@ insert into t1 select * from t1; insert into t1 select * from t1; connection a; set session transaction isolation level serializable; -select @@tx_isolation; -@@tx_isolation +select @@transaction_isolation; +@@transaction_isolation SERIALIZABLE start transaction; set @g1 = ST_GeomFromText('Polygon((100 100, 100 110, 110 110, 110 100, 100 100))'); @@ -131,8 +131,8 @@ count(*) connection b; set session transaction isolation level serializable; set session innodb_lock_wait_timeout = 1; -select @@tx_isolation; -@@tx_isolation +select @@transaction_isolation; +@@transaction_isolation SERIALIZABLE insert into t1 select * from t1; insert into t1 select * from t1; @@ -158,8 +158,8 @@ connection b; select @@innodb_lock_wait_timeout; @@innodb_lock_wait_timeout 1 -select @@tx_isolation; -@@tx_isolation +select @@transaction_isolation; +@@transaction_isolation SERIALIZABLE INSERT INTO t1 VALUES (1, ST_GeomFromText('LineString(8 105, 200 105)')); ERROR HY000: Lock wait timeout exceeded; try restarting transaction @@ -227,8 +227,8 @@ end| CALL insert_t1(0, 1000); connection a; set session transaction isolation level serializable; -select @@tx_isolation; -@@tx_isolation +select @@transaction_isolation; +@@transaction_isolation SERIALIZABLE start transaction; set @g1 = ST_GeomFromText('Polygon((800 800, 800 1000, 1000 1000, 1000 800, 800 800))'); diff --git a/mysql-test/suite/innodb_gis/t/repeatable_spatial.test b/mysql-test/suite/innodb_gis/t/repeatable_spatial.test index 3152911b257..16372dc14dc 100644 --- a/mysql-test/suite/innodb_gis/t/repeatable_spatial.test +++ b/mysql-test/suite/innodb_gis/t/repeatable_spatial.test @@ -40,7 +40,7 @@ connection con1; SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ; -SELECT @@tx_isolation; +SELECT @@transaction_isolation; # Record count should be 1 SELECT COUNT(*) FROM tab; @@ -54,7 +54,7 @@ connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; -SELECT @@tx_isolation; +SELECT @@transaction_isolation; START TRANSACTION; @@ -155,7 +155,7 @@ connection con1; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; -SELECT @@tx_isolation; +SELECT @@transaction_isolation; # Record count should be 1 SELECT COUNT(*) FROM tab; @@ -169,7 +169,7 @@ connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; -SELECT @@tx_isolation; +SELECT @@transaction_isolation; START TRANSACTION; diff --git a/mysql-test/suite/innodb_gis/t/rtree_concurrent_srch.test b/mysql-test/suite/innodb_gis/t/rtree_concurrent_srch.test index c4a6448f387..017c650fca3 100644 --- a/mysql-test/suite/innodb_gis/t/rtree_concurrent_srch.test +++ b/mysql-test/suite/innodb_gis/t/rtree_concurrent_srch.test @@ -79,7 +79,7 @@ insert into t1 select * from t1; # Connection 'a' will place predicate lock on almost all pages connection a; set session transaction isolation level serializable; -select @@tx_isolation; +select @@transaction_isolation; start transaction; set @g1 = ST_GeomFromText('Polygon((100 100, 100 110, 110 110, 110 100, 100 100))'); select count(*) from t1 where MBRwithin(t1.c2, @g1); @@ -89,7 +89,7 @@ connect (b,localhost,root,,); set session transaction isolation level serializable; set session innodb_lock_wait_timeout = 1; -select @@tx_isolation; +select @@transaction_isolation; insert into t1 select * from t1; insert into t1 select * from t1; @@ -115,7 +115,7 @@ select count(*) from t1 where MBRwithin(t1.c2, @g1); connection b; select @@innodb_lock_wait_timeout; -select @@tx_isolation; +select @@transaction_isolation; --error ER_LOCK_WAIT_TIMEOUT insert into t1 select * from t1; @@ -146,7 +146,7 @@ insert into t1 select * from t1; # Connection 'a' will place predicate lock on almost all pages connection a; set session transaction isolation level serializable; -select @@tx_isolation; +select @@transaction_isolation; start transaction; set @g1 = ST_GeomFromText('Polygon((100 100, 100 110, 110 110, 110 100, 100 100))'); select count(*) from t1 where MBRwithin(t1.c2, @g1); @@ -156,7 +156,7 @@ connection b; set session transaction isolation level serializable; set session innodb_lock_wait_timeout = 1; -select @@tx_isolation; +select @@transaction_isolation; insert into t1 select * from t1; insert into t1 select * from t1; @@ -181,7 +181,7 @@ select count(*) from t1 where MBRIntersects(t1.c2, @g1); connection b; select @@innodb_lock_wait_timeout; -select @@tx_isolation; +select @@transaction_isolation; # this should conflict with the "MBRIntersects" predicate lock in session "a" --error ER_LOCK_WAIT_TIMEOUT @@ -264,7 +264,7 @@ CALL insert_t1(0, 1000); # Connection 'a' will place predicate lock on root and last leaf page connection a; set session transaction isolation level serializable; -select @@tx_isolation; +select @@transaction_isolation; start transaction; set @g1 = ST_GeomFromText('Polygon((800 800, 800 1000, 1000 1000, 1000 800, 800 800))'); select count(*) from t1 where MBRwithin(t1.c2, @g1); diff --git a/mysql-test/suite/innodb_zip/r/bug56680.result b/mysql-test/suite/innodb_zip/r/bug56680.result index 3c325351c3a..45c768eeca5 100644 --- a/mysql-test/suite/innodb_zip/r/bug56680.result +++ b/mysql-test/suite/innodb_zip/r/bug56680.result @@ -1,4 +1,4 @@ -SET GLOBAL tx_isolation='REPEATABLE-READ'; +SET GLOBAL transaction_isolation='REPEATABLE-READ'; CREATE TABLE bug56680( a INT AUTO_INCREMENT PRIMARY KEY, b CHAR(1), @@ -28,7 +28,7 @@ connection default; SELECT b FROM bug56680; b x -SET GLOBAL tx_isolation='READ-UNCOMMITTED'; +SET GLOBAL transaction_isolation='READ-UNCOMMITTED'; INSERT INTO bug56680 SELECT 0,b,c FROM bug56680; INSERT INTO bug56680 SELECT 0,b,c FROM bug56680; INSERT INTO bug56680 SELECT 0,b,c FROM bug56680; diff --git a/mysql-test/suite/innodb_zip/r/index_large_prefix.result b/mysql-test/suite/innodb_zip/r/index_large_prefix.result index 81bdcdeb740..0c6a9104f7c 100644 --- a/mysql-test/suite/innodb_zip/r/index_large_prefix.result +++ b/mysql-test/suite/innodb_zip/r/index_large_prefix.result @@ -10,8 +10,8 @@ show warnings; Level Code Message begin; update worklog5743 set a = (repeat("x", 17000)); -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ connect con1,localhost,root,,; select a = repeat("x", 17000) from worklog5743; @@ -22,8 +22,8 @@ a = repeat("b", 16000) 1 connect con2,localhost,root,,; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a = repeat("x", 17000) from worklog5743; a = repeat("x", 17000) @@ -42,8 +42,8 @@ insert into worklog5743 values(9, repeat("a", 10000)); begin; update worklog5743 set a1 = 1000; connection con1; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ explain select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; id select_type table type possible_keys key key_len ref rows Extra @@ -53,8 +53,8 @@ a1 a2 = repeat("a", 10000) 9 1 connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; a1 a2 = repeat("a", 10000) @@ -68,8 +68,8 @@ insert into worklog5743 values(9, repeat("a", 10000)); begin; update worklog5743 set a1 = 1000; connection con1; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ explain select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; id select_type table type possible_keys key key_len ref rows Extra @@ -79,8 +79,8 @@ a1 a2 = repeat("a", 10000) 9 1 connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; a1 a2 = repeat("a", 10000) @@ -258,8 +258,8 @@ select a1, left(a2, 20) from worklog5743_16; a1 left(a2, 20) 1000 aaaaaaaaaaaaaaaaaaaa connection con1; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ explain select a1, left(a2, 20) from worklog5743_1 where a1 = 9; id select_type table type possible_keys key key_len ref rows Extra @@ -293,8 +293,8 @@ a1 left(a2, 20) 9 aaaaaaaaaaaaaaaaaaaa connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a1, left(a2, 20) from worklog5743_1 where a1 = 9; a1 left(a2, 20) @@ -367,8 +367,8 @@ repeat("a", 3068)); begin; update worklog5743 set a1 = 1000; connection con1; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ explain select a1 from worklog5743 where a1 = 9; id select_type table type possible_keys key key_len ref rows Extra @@ -378,8 +378,8 @@ a1 9 connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a1 from worklog5743 where a1 = 9; a1 @@ -399,8 +399,8 @@ insert into worklog5743 values(repeat("a", 20000)); begin; insert into worklog5743 values(repeat("b", 20000)); update worklog5743 set a = (repeat("x", 25000)); -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ connection con1; select a = repeat("a", 20000) from worklog5743; @@ -409,8 +409,8 @@ a = repeat("a", 20000) disconnect con1; connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a = repeat("x", 25000) from worklog5743; a = repeat("x", 25000) diff --git a/mysql-test/suite/innodb_zip/r/index_large_prefix_4k.result b/mysql-test/suite/innodb_zip/r/index_large_prefix_4k.result index d1e7220b0ba..1f3b72ec2c9 100644 --- a/mysql-test/suite/innodb_zip/r/index_large_prefix_4k.result +++ b/mysql-test/suite/innodb_zip/r/index_large_prefix_4k.result @@ -13,8 +13,8 @@ Level Code Message SET sql_mode= default; begin; update worklog5743 set a = (repeat("x", 17000)); -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ connect con1,localhost,root,,; select a = repeat("x", 17000) from worklog5743; @@ -25,8 +25,8 @@ a = repeat("b", 16000) 1 connect con2,localhost,root,,; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a = repeat("x", 17000) from worklog5743; a = repeat("x", 17000) @@ -45,8 +45,8 @@ insert into worklog5743 values(9, repeat("a", 10000)); begin; update worklog5743 set a1 = 1111; connection con1; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ explain select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; id select_type table type possible_keys key key_len ref rows Extra @@ -56,8 +56,8 @@ a1 a2 = repeat("a", 10000) 9 1 connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; a1 a2 = repeat("a", 10000) @@ -71,8 +71,8 @@ insert into worklog5743 values(9, repeat("a", 10000)); begin; update worklog5743 set a1 = 2222; connection con1; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ explain select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; id select_type table type possible_keys key key_len ref rows Extra @@ -82,8 +82,8 @@ a1 a2 = repeat("a", 10000) 9 1 connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; a1 a2 = repeat("a", 10000) @@ -183,8 +183,8 @@ select a1, left(a2, 20) from worklog5743_4; a1 left(a2, 20) 1000 aaaaaaaaaaaaaaaaaaaa connection con1; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ explain select a1, left(a2, 20) from worklog5743_1 where a1 = 9; id select_type table type possible_keys key key_len ref rows Extra @@ -206,8 +206,8 @@ a1 left(a2, 20) 9 aaaaaaaaaaaaaaaaaaaa connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a1, left(a2, 20) from worklog5743_1 where a1 = 9; a1 left(a2, 20) @@ -261,8 +261,8 @@ insert into worklog5743 values(9, repeat("a", 764)); begin; update worklog5743 set a1 = 4444; connection con1; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ explain select a1 from worklog5743 where a1 = 9; id select_type table type possible_keys key key_len ref rows Extra @@ -272,8 +272,8 @@ a1 9 connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a1 from worklog5743 where a1 = 9; a1 @@ -289,8 +289,8 @@ insert into worklog5743 values(repeat("a", 20000)); begin; insert into worklog5743 values(repeat("b", 20000)); update worklog5743 set a = (repeat("x", 25000)); -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ connection con1; select a = repeat("a", 20000) from worklog5743; @@ -299,8 +299,8 @@ a = repeat("a", 20000) disconnect con1; connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a = repeat("x", 25000) from worklog5743; a = repeat("x", 25000) diff --git a/mysql-test/suite/innodb_zip/r/index_large_prefix_8k.result b/mysql-test/suite/innodb_zip/r/index_large_prefix_8k.result index ef5b5984f3c..3474fb637c2 100644 --- a/mysql-test/suite/innodb_zip/r/index_large_prefix_8k.result +++ b/mysql-test/suite/innodb_zip/r/index_large_prefix_8k.result @@ -16,8 +16,8 @@ Note 1071 Specified key was too long; max key length is 1536 bytes SET sql_mode= default; begin; update worklog5743 set a = (repeat("x", 17000)); -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ connect con1,localhost,root,,; select a = repeat("x", 17000) from worklog5743; @@ -28,8 +28,8 @@ a = repeat("b", 16000) 1 connect con2,localhost,root,,; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a = repeat("x", 17000) from worklog5743; a = repeat("x", 17000) @@ -48,8 +48,8 @@ insert into worklog5743 values(9, repeat("a", 10000)); begin; update worklog5743 set a1 = 1000; connection con1; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ explain select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; id select_type table type possible_keys key key_len ref rows Extra @@ -59,8 +59,8 @@ a1 a2 = repeat("a", 10000) 9 1 connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; a1 a2 = repeat("a", 10000) @@ -74,8 +74,8 @@ insert into worklog5743 values(9, repeat("a", 10000)); begin; update worklog5743 set a1 = 1000; connection con1; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ explain select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; id select_type table type possible_keys key key_len ref rows Extra @@ -85,8 +85,8 @@ a1 a2 = repeat("a", 10000) 9 1 connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; a1 a2 = repeat("a", 10000) @@ -217,8 +217,8 @@ select a1, left(a2, 20) from worklog5743_8; a1 left(a2, 20) 1000 aaaaaaaaaaaaaaaaaaaa connection con1; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ explain select a1, left(a2, 20) from worklog5743_1 where a1 = 9; id select_type table type possible_keys key key_len ref rows Extra @@ -246,8 +246,8 @@ a1 left(a2, 20) 9 aaaaaaaaaaaaaaaaaaaa connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a1, left(a2, 20) from worklog5743_1 where a1 = 9; a1 left(a2, 20) @@ -295,8 +295,8 @@ update worklog5743 set a1 = 1000; begin; update worklog5743 set a1 = 1000; connection con1; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ explain select a1 from worklog5743 where a1 = 9; id select_type table type possible_keys key key_len ref rows Extra @@ -305,8 +305,8 @@ select a1 from worklog5743 where a1 = 9; a1 connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a1 from worklog5743 where a1 = 9; a1 @@ -325,8 +325,8 @@ insert into worklog5743 values(repeat("a", 20000)); begin; insert into worklog5743 values(repeat("b", 20000)); update worklog5743 set a = (repeat("x", 25000)); -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ connection con1; select a = repeat("a", 20000) from worklog5743; @@ -335,8 +335,8 @@ a = repeat("a", 20000) disconnect con1; connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED select a = repeat("x", 25000) from worklog5743; a = repeat("x", 25000) diff --git a/mysql-test/suite/innodb_zip/r/prefix_index_liftedlimit.result b/mysql-test/suite/innodb_zip/r/prefix_index_liftedlimit.result index 43a63a29e71..d29082ad9d4 100644 --- a/mysql-test/suite/innodb_zip/r/prefix_index_liftedlimit.result +++ b/mysql-test/suite/innodb_zip/r/prefix_index_liftedlimit.result @@ -793,16 +793,16 @@ col_1_text = REPEAT("a", 200) col_2_text = REPEAT("o", 200) 1 1 0 1 connection con1; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation REPEATABLE-READ SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM worklog5743; col_1_text = REPEAT("b", 200) col_2_text = REPEAT("o", 200) 0 1 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM worklog5743; @@ -864,8 +864,8 @@ col_1_text = REPEAT("a", 200) col_2_text = REPEAT("o", 200) COMMIT; connection con1; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; -@@session.tx_isolation +select @@session.transaction_isolation; +@@session.transaction_isolation READ-UNCOMMITTED SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM worklog5743; diff --git a/mysql-test/suite/innodb_zip/t/bug56680.test b/mysql-test/suite/innodb_zip/t/bug56680.test index 0d441dea0f5..adb632afe37 100644 --- a/mysql-test/suite/innodb_zip/t/bug56680.test +++ b/mysql-test/suite/innodb_zip/t/bug56680.test @@ -15,7 +15,7 @@ -- error 0,ER_UNKNOWN_SYSTEM_VARIABLE SET GLOBAL innodb_change_buffering_debug = 1; -- enable_query_log -SET GLOBAL tx_isolation='REPEATABLE-READ'; +SET GLOBAL transaction_isolation='REPEATABLE-READ'; CREATE TABLE bug56680( a INT AUTO_INCREMENT PRIMARY KEY, @@ -50,7 +50,7 @@ SELECT b FROM bug56680; # For the rest of this test, use the READ UNCOMMITTED isolation level # to see what exists in the secondary index. -SET GLOBAL tx_isolation='READ-UNCOMMITTED'; +SET GLOBAL transaction_isolation='READ-UNCOMMITTED'; # Create enough rows for the table, so that the insert buffer will be # used for modifying the secondary index page. There must be multiple diff --git a/mysql-test/suite/innodb_zip/t/index_large_prefix.test b/mysql-test/suite/innodb_zip/t/index_large_prefix.test index 5c1e31a2db7..65634542c1f 100644 --- a/mysql-test/suite/innodb_zip/t/index_large_prefix.test +++ b/mysql-test/suite/innodb_zip/t/index_large_prefix.test @@ -40,7 +40,7 @@ update worklog5743 set a = (repeat("x", 17000)); # Start a new session to select the column to force it build # an earlier version of the clustered index through undo log. So it should # just see the result of repeat("b", 16000) -select @@session.tx_isolation; +select @@session.transaction_isolation; --connect (con1,localhost,root,,) select a = repeat("x", 17000) from worklog5743; select a = repeat("b", 16000) from worklog5743; @@ -49,7 +49,7 @@ select a = repeat("b", 16000) from worklog5743; # should see the uncommitted update --connect (con2,localhost,root,,) SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a = repeat("x", 17000) from worklog5743; # Roll back the transaction @@ -73,7 +73,7 @@ update worklog5743 set a1 = 1000; # Do a select from another connection that would use the secondary index --connection con1 -select @@session.tx_isolation; +select @@session.transaction_isolation; explain select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; @@ -81,7 +81,7 @@ select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; # row with a1 = 9 --connection con2 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; --connection default @@ -103,7 +103,7 @@ update worklog5743 set a1 = 1000; # Do a select from another connection that would use the secondary index --connection con1 -select @@session.tx_isolation; +select @@session.transaction_isolation; explain select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; @@ -111,7 +111,7 @@ select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; # row with a1 = 9 --connection con2 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; --connection default @@ -247,7 +247,7 @@ select a1, left(a2, 20) from worklog5743_16; # Do a select from another connection that would use the secondary index --connection con1 -select @@session.tx_isolation; +select @@session.transaction_isolation; explain select a1, left(a2, 20) from worklog5743_1 where a1 = 9; explain select a1, left(a2, 20) from worklog5743_2 where a1 = 9; explain select a1, left(a2, 20) from worklog5743_4 where a1 = 9; @@ -263,7 +263,7 @@ select a1, left(a2, 20) from worklog5743_16 where a1 = 9; # row with a1 = 9 --connection con2 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a1, left(a2, 20) from worklog5743_1 where a1 = 9; select a1, left(a2, 20) from worklog5743_2 where a1 = 9; select a1, left(a2, 20) from worklog5743_4 where a1 = 9; @@ -318,14 +318,14 @@ update worklog5743 set a1 = 1000; # Do a select from another connection that would use the secondary index --connection con1 -select @@session.tx_isolation; +select @@session.transaction_isolation; explain select a1 from worklog5743 where a1 = 9; select a1 from worklog5743 where a1 = 9; # Do read uncommitted, it would show there is no row with a1 = 9 --connection con2 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a1 from worklog5743 where a1 = 9; --connection default @@ -358,14 +358,14 @@ update worklog5743 set a = (repeat("x", 25000)); # Start a new session to select the table to force it build # an earlier version of the cluster index through undo log -select @@session.tx_isolation; +select @@session.transaction_isolation; --connection con1 select a = repeat("a", 20000) from worklog5743; --disconnect con1 --connection con2 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a = repeat("x", 25000) from worklog5743; --disconnect con2 diff --git a/mysql-test/suite/innodb_zip/t/index_large_prefix_4k.test b/mysql-test/suite/innodb_zip/t/index_large_prefix_4k.test index 8ada226779a..960ad1ebcf5 100644 --- a/mysql-test/suite/innodb_zip/t/index_large_prefix_4k.test +++ b/mysql-test/suite/innodb_zip/t/index_large_prefix_4k.test @@ -41,7 +41,7 @@ update worklog5743 set a = (repeat("x", 17000)); # Start a new session to select the column to force it build # an earlier version of the clustered index through undo log. So it should # just see the result of repeat("b", 16000) -select @@session.tx_isolation; +select @@session.transaction_isolation; --connect (con1,localhost,root,,) select a = repeat("x", 17000) from worklog5743; select a = repeat("b", 16000) from worklog5743; @@ -50,7 +50,7 @@ select a = repeat("b", 16000) from worklog5743; # should see the uncommitted update --connect (con2,localhost,root,,) SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a = repeat("x", 17000) from worklog5743; # Roll back the transaction @@ -74,7 +74,7 @@ update worklog5743 set a1 = 1111; # Do a select from another connection that would use the secondary index --connection con1 -select @@session.tx_isolation; +select @@session.transaction_isolation; explain select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; @@ -82,7 +82,7 @@ select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; # row with a1 = 9 --connection con2 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; --connection default @@ -104,7 +104,7 @@ update worklog5743 set a1 = 2222; # Do a select from another connection that would use the secondary index --connection con1 -select @@session.tx_isolation; +select @@session.transaction_isolation; explain select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; @@ -112,7 +112,7 @@ select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; # row with a1 = 9 --connection con2 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; --connection default @@ -195,7 +195,7 @@ select a1, left(a2, 20) from worklog5743_4; # Do a select from another connection that would use the secondary index --connection con1 -select @@session.tx_isolation; +select @@session.transaction_isolation; explain select a1, left(a2, 20) from worklog5743_1 where a1 = 9; explain select a1, left(a2, 20) from worklog5743_2 where a1 = 9; explain select a1, left(a2, 20) from worklog5743_4 where a1 = 9; @@ -207,7 +207,7 @@ select a1, left(a2, 20) from worklog5743_4 where a1 = 9; # row with a1 = 9 --connection con2 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a1, left(a2, 20) from worklog5743_1 where a1 = 9; select a1, left(a2, 20) from worklog5743_2 where a1 = 9; select a1, left(a2, 20) from worklog5743_4 where a1 = 9; @@ -293,14 +293,14 @@ update worklog5743 set a1 = 4444; # Do a select from another connection that would use the secondary index --connection con1 -select @@session.tx_isolation; +select @@session.transaction_isolation; explain select a1 from worklog5743 where a1 = 9; select a1 from worklog5743 where a1 = 9; # Do read uncommitted, it would show there is no row with a1 = 9 --connection con2 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a1 from worklog5743 where a1 = 9; --connection default @@ -327,14 +327,14 @@ update worklog5743 set a = (repeat("x", 25000)); # Start a new session to select the table to force it build # an earlier version of the cluster index through undo log -select @@session.tx_isolation; +select @@session.transaction_isolation; --connection con1 select a = repeat("a", 20000) from worklog5743; --disconnect con1 --connection con2 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a = repeat("x", 25000) from worklog5743; --disconnect con2 diff --git a/mysql-test/suite/innodb_zip/t/index_large_prefix_8k.test b/mysql-test/suite/innodb_zip/t/index_large_prefix_8k.test index e20de5e3e93..23fb37e8d73 100644 --- a/mysql-test/suite/innodb_zip/t/index_large_prefix_8k.test +++ b/mysql-test/suite/innodb_zip/t/index_large_prefix_8k.test @@ -42,7 +42,7 @@ update worklog5743 set a = (repeat("x", 17000)); # Start a new session to select the column to force it build # an earlier version of the clustered index through undo log. So it should # just see the result of repeat("b", 16000) -select @@session.tx_isolation; +select @@session.transaction_isolation; --connect (con1,localhost,root,,) select a = repeat("x", 17000) from worklog5743; select a = repeat("b", 16000) from worklog5743; @@ -51,7 +51,7 @@ select a = repeat("b", 16000) from worklog5743; # should see the uncommitted update --connect (con2,localhost,root,,) SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a = repeat("x", 17000) from worklog5743; # Roll back the transaction @@ -75,7 +75,7 @@ update worklog5743 set a1 = 1000; # Do a select from another connection that would use the secondary index --connection con1 -select @@session.tx_isolation; +select @@session.transaction_isolation; explain select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; @@ -83,7 +83,7 @@ select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; # row with a1 = 9 --connection con2 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; --connection default @@ -105,7 +105,7 @@ update worklog5743 set a1 = 1000; # Do a select from another connection that would use the secondary index --connection con1 -select @@session.tx_isolation; +select @@session.transaction_isolation; explain select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; @@ -113,7 +113,7 @@ select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; # row with a1 = 9 --connection con2 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9; --connection default @@ -217,7 +217,7 @@ select a1, left(a2, 20) from worklog5743_8; # Do a select from another connection that would use the secondary index --connection con1 -select @@session.tx_isolation; +select @@session.transaction_isolation; explain select a1, left(a2, 20) from worklog5743_1 where a1 = 9; explain select a1, left(a2, 20) from worklog5743_2 where a1 = 9; explain select a1, left(a2, 20) from worklog5743_4 where a1 = 9; @@ -231,7 +231,7 @@ select a1, left(a2, 20) from worklog5743_8 where a1 = 9; # row with a1 = 9 --connection con2 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a1, left(a2, 20) from worklog5743_1 where a1 = 9; select a1, left(a2, 20) from worklog5743_2 where a1 = 9; select a1, left(a2, 20) from worklog5743_4 where a1 = 9; @@ -314,14 +314,14 @@ update worklog5743 set a1 = 1000; # Do a select from another connection that would use the secondary index --connection con1 -select @@session.tx_isolation; +select @@session.transaction_isolation; explain select a1 from worklog5743 where a1 = 9; select a1 from worklog5743 where a1 = 9; # Do read uncommitted, it would show there is no row with a1 = 9 --connection con2 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a1 from worklog5743 where a1 = 9; --connection default @@ -353,14 +353,14 @@ update worklog5743 set a = (repeat("x", 25000)); # Start a new session to select the table to force it build # an earlier version of the cluster index through undo log -select @@session.tx_isolation; +select @@session.transaction_isolation; --connection con1 select a = repeat("a", 20000) from worklog5743; --disconnect con1 --connection con2 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; select a = repeat("x", 25000) from worklog5743; --disconnect con2 diff --git a/mysql-test/suite/innodb_zip/t/prefix_index_liftedlimit.test b/mysql-test/suite/innodb_zip/t/prefix_index_liftedlimit.test index 32d7eacd29f..de27ddce658 100644 --- a/mysql-test/suite/innodb_zip/t/prefix_index_liftedlimit.test +++ b/mysql-test/suite/innodb_zip/t/prefix_index_liftedlimit.test @@ -722,11 +722,11 @@ SELECT col_1_text = REPEAT("a", 200) , col_2_text = REPEAT("o", 200) FROM worklog5743; --connection con1 -select @@session.tx_isolation; +select @@session.transaction_isolation; SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM worklog5743; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM worklog5743; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; @@ -789,7 +789,7 @@ WHERE info='COMMIT'; --connection con1 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -select @@session.tx_isolation; +select @@session.transaction_isolation; SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM worklog5743; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; diff --git a/mysql-test/suite/json/r/json_table.result b/mysql-test/suite/json/r/json_table.result index 900348d8a13..ed385f86a31 100644 --- a/mysql-test/suite/json/r/json_table.result +++ b/mysql-test/suite/json/r/json_table.result @@ -1146,3 +1146,104 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp # # End of 10.9 tests # +# +# MDEV-29390: Improve coverage for UPDATE and DELETE statements in MTR test suites +# +# Multi-update with JSON_TABLE +create table t1 ( name varchar(10), +color varchar(10), +price decimal(8,2), +instock BOOLEAN); +insert into t1 values ("Laptop", "black", 20000, 1); +insert into t1 values ("Jacket", "brown", 5000, 1); +insert into t1 values ("Jeans", "blue", 5000, 1); +select * from t1; +name color price instock +Laptop black 20000.00 1 +Jacket brown 5000.00 1 +Jeans blue 5000.00 1 +set @json=' +[ + {"name":"Laptop", "color":"black", "price":"1000", "ordered":"3"}, + {"name":"Jeans", "color":"blue", "ordered":"0"}, + {"name":"Phone", "color":"red", "ordered":"0"} +]'; +select * from json_table(@json, '$[*]' +columns( +name varchar(10) path '$.name', +color varchar(10) path '$.color', +price decimal(8,2) path '$.price', +ordered boolean path '$.ordered' ) +) as jt; +name color price ordered +Laptop black 1000.00 3 +Jeans blue NULL 0 +Phone red NULL 0 +explain update t1, JSON_TABLE(@json,'$[*]' +COLUMNS ( +name varchar(10) path '$.name', +color varchar(10) path '$.color', +price decimal(8,2) path '$.price', +ordered boolean path '$.ordered' + )) AS jt1 +SET t1.instock=0 where t1.name=jt1.name and jt1.ordered=3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE jt1 ALL NULL NULL NULL NULL 40 Table function: json_table; Using where +update t1, JSON_TABLE(@json,'$[*]' +COLUMNS ( +name varchar(10) path '$.name', +color varchar(10) path '$.color', +price decimal(8,2) path '$.price', +ordered boolean path '$.ordered' + )) AS jt1 +SET t1.instock=0 where t1.name=jt1.name and jt1.ordered=2; +select * from t1; +name color price instock +Laptop black 20000.00 1 +Jacket brown 5000.00 1 +Jeans blue 5000.00 1 +explain update t1 +SET t1.instock=2 where t1.name in ( +select jt1.name from json_table(@json, '$[*]' +columns( +name varchar(10) path '$.name', +color varchar(10) path '$.color', +price decimal(8,2) path '$.price', +ordered boolean path '$.ordered' ) +) as jt1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 +1 PRIMARY jt1 ALL NULL NULL NULL NULL 40 Table function: json_table; Using where; FirstMatch(t1) +update t1 +SET t1.instock=2 where t1.name in ( +select jt1.name from json_table(@json, '$[*]' +columns( +name varchar(10) path '$.name', +color varchar(10) path '$.color', +price decimal(8,2) path '$.price', +ordered boolean path '$.ordered' ) +) as jt1); +select * from t1; +name color price instock +Laptop black 20000.00 2 +Jacket brown 5000.00 1 +Jeans blue 5000.00 2 +update t1, JSON_TABLE(@json,'$[*]' +COLUMNS ( +name varchar(10) path '$.name', +color varchar(10) path '$.color', +price decimal(8,2) path '$.price', +ordered boolean path '$.ordered' + )) AS jt1 +SET t1.instock=0, jt1.ordered=1 where t1.name=jt1.name; +ERROR HY000: The target table jt1 of the UPDATE is not updatable +select * from t1; +name color price instock +Laptop black 20000.00 2 +Jacket brown 5000.00 1 +Jeans blue 5000.00 2 +drop table t1; +# +# End of 11.0 tests +# diff --git a/mysql-test/suite/json/t/json_table.test b/mysql-test/suite/json/t/json_table.test index 982922ff595..5a8fe984c79 100644 --- a/mysql-test/suite/json/t/json_table.test +++ b/mysql-test/suite/json/t/json_table.test @@ -997,3 +997,97 @@ COLUMNS --echo # --echo # End of 10.9 tests --echo # + +--echo # +--echo # MDEV-29390: Improve coverage for UPDATE and DELETE statements in MTR test suites +--echo # + +--echo # Multi-update with JSON_TABLE + +create table t1 ( name varchar(10), + color varchar(10), + price decimal(8,2), + instock BOOLEAN); + +insert into t1 values ("Laptop", "black", 20000, 1); +insert into t1 values ("Jacket", "brown", 5000, 1); +insert into t1 values ("Jeans", "blue", 5000, 1); + +select * from t1; + +set @json=' +[ + {"name":"Laptop", "color":"black", "price":"1000", "ordered":"3"}, + {"name":"Jeans", "color":"blue", "ordered":"0"}, + {"name":"Phone", "color":"red", "ordered":"0"} +]'; + +select * from json_table(@json, '$[*]' + columns( + name varchar(10) path '$.name', + color varchar(10) path '$.color', + price decimal(8,2) path '$.price', + ordered boolean path '$.ordered' ) +) as jt; + +explain update t1, JSON_TABLE(@json,'$[*]' + COLUMNS ( + name varchar(10) path '$.name', + color varchar(10) path '$.color', + price decimal(8,2) path '$.price', + ordered boolean path '$.ordered' + )) AS jt1 + SET t1.instock=0 where t1.name=jt1.name and jt1.ordered=3; + +update t1, JSON_TABLE(@json,'$[*]' + COLUMNS ( + name varchar(10) path '$.name', + color varchar(10) path '$.color', + price decimal(8,2) path '$.price', + ordered boolean path '$.ordered' + )) AS jt1 + SET t1.instock=0 where t1.name=jt1.name and jt1.ordered=2; + +select * from t1; + +explain update t1 + SET t1.instock=2 where t1.name in ( + select jt1.name from json_table(@json, '$[*]' + columns( + name varchar(10) path '$.name', + color varchar(10) path '$.color', + price decimal(8,2) path '$.price', + ordered boolean path '$.ordered' ) + ) as jt1); + + +update t1 + SET t1.instock=2 where t1.name in ( + select jt1.name from json_table(@json, '$[*]' + columns( + name varchar(10) path '$.name', + color varchar(10) path '$.color', + price decimal(8,2) path '$.price', + ordered boolean path '$.ordered' ) + ) as jt1); + +select * from t1; + + +-- error ER_NON_UPDATABLE_TABLE +update t1, JSON_TABLE(@json,'$[*]' + COLUMNS ( + name varchar(10) path '$.name', + color varchar(10) path '$.color', + price decimal(8,2) path '$.price', + ordered boolean path '$.ordered' + )) AS jt1 + SET t1.instock=0, jt1.ordered=1 where t1.name=jt1.name; + +select * from t1; + +drop table t1; + +--echo # +--echo # End of 11.0 tests +--echo # diff --git a/mysql-test/suite/mariabackup/compat_xtrabackup.result b/mysql-test/suite/mariabackup/compat_xtrabackup.result new file mode 100644 index 00000000000..484dc0d7d46 --- /dev/null +++ b/mysql-test/suite/mariabackup/compat_xtrabackup.result @@ -0,0 +1,21 @@ +call mtr.add_suppression("InnoDB: New log files created"); +# +# Start of 10.11 tests +# +# +# MDEV-18931 Rename Mariabackup's xtrabackup_* files to mariadb_backup_* +# +CREATE TABLE t1(i INT PRIMARY KEY) ENGINE MYISAM; +INSERT INTO t1 VALUES (1); +# Prepare full backup, apply incremental one +# shutdown server +# remove datadir +# xtrabackup move back +# restart +SELECT * FROM test.t1; +i +1 +DROP TABLE t1; +# +# End of 10.11 tests +# diff --git a/mysql-test/suite/mariabackup/compat_xtrabackup.test b/mysql-test/suite/mariabackup/compat_xtrabackup.test new file mode 100644 index 00000000000..67d043fd436 --- /dev/null +++ b/mysql-test/suite/mariabackup/compat_xtrabackup.test @@ -0,0 +1,62 @@ +call mtr.add_suppression("InnoDB: New log files created"); + +--echo # +--echo # Start of 10.11 tests +--echo # + +--echo # +--echo # MDEV-18931 Rename Mariabackup's xtrabackup_* files to mariadb_backup_* +--echo # + +--let $basedir=$MYSQLTEST_VARDIR/tmp/backup +--let $incremental_dir=$MYSQLTEST_VARDIR/tmp/backup_inc1 + +CREATE TABLE t1(i INT PRIMARY KEY) ENGINE MYISAM; +INSERT INTO t1 VALUES (1); + +--disable_result_log +--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir +--enable_result_log + +--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$incremental_dir --incremental-basedir=$basedir + +# +# Emulate a backup created by an older version: +# Rename mariadb_backup_checkpoints +# + +--move_file $basedir/mariadb_backup_checkpoints $basedir/xtrabackup_checkpoints +--move_file $incremental_dir/mariadb_backup_checkpoints $incremental_dir/xtrabackup_checkpoints + +# +# Emulate a backup created by an older version: +# Rename mariadb_backup_info +# Note, mariadb_backup_info is not currently used during --prepare or --restore +# But it's still good to rename it: +# - we can start using it during --prepare or --restore +# - to provide full emulation +# + +--move_file $basedir/mariadb_backup_info $basedir/mariadb_backup_info +--move_file $incremental_dir/mariadb_backup_info $incremental_dir/mariadb_backup_info + + +--disable_result_log +--echo # Prepare full backup, apply incremental one +--exec $XTRABACKUP --prepare --target-dir=$basedir +--exec $XTRABACKUP --prepare --target-dir=$basedir --incremental-dir=$incremental_dir +--enable_result_log + +--let $targetdir=$basedir +--source include/restart_and_restore.inc +--enable_result_log + +SELECT * FROM test.t1; + +DROP TABLE t1; +--rmdir $basedir +--rmdir $incremental_dir + +--echo # +--echo # End of 10.11 tests +--echo # diff --git a/mysql-test/suite/mariabackup/extra_lsndir.result b/mysql-test/suite/mariabackup/extra_lsndir.result index a25c45a13d1..58e395eb65e 100644 --- a/mysql-test/suite/mariabackup/extra_lsndir.result +++ b/mysql-test/suite/mariabackup/extra_lsndir.result @@ -1,2 +1,2 @@ -xtrabackup_checkpoints -xtrabackup_info +mariadb_backup_checkpoints +mariadb_backup_info diff --git a/mysql-test/suite/mariabackup/extra_lsndir_stream.result b/mysql-test/suite/mariabackup/extra_lsndir_stream.result index a25c45a13d1..58e395eb65e 100644 --- a/mysql-test/suite/mariabackup/extra_lsndir_stream.result +++ b/mysql-test/suite/mariabackup/extra_lsndir_stream.result @@ -1,2 +1,2 @@ -xtrabackup_checkpoints -xtrabackup_info +mariadb_backup_checkpoints +mariadb_backup_info diff --git a/mysql-test/suite/mariabackup/include/show_xtrabackup_slave_info.inc b/mysql-test/suite/mariabackup/include/show_xtrabackup_slave_info.inc index 4a83c9c394e..ba0116a81cf 100644 --- a/mysql-test/suite/mariabackup/include/show_xtrabackup_slave_info.inc +++ b/mysql-test/suite/mariabackup/include/show_xtrabackup_slave_info.inc @@ -1,8 +1,8 @@ --disable_query_log ---file_exists $targetdir/xtrabackup_slave_info +--file_exists $targetdir/mariadb_backup_slave_info CREATE TEMPORARY TABLE tmp_slave_info(lineno SERIAL, line TEXT); --replace_result $targetdir TARGETDIR ---eval LOAD DATA LOCAL INFILE '$targetdir/xtrabackup_slave_info' INTO TABLE tmp_slave_info (line); +--eval LOAD DATA LOCAL INFILE '$targetdir/mariadb_backup_slave_info' INTO TABLE tmp_slave_info (line); SELECT lineno, regexp_replace( diff --git a/mysql-test/suite/mariabackup/rpl_slave_info.result b/mysql-test/suite/mariabackup/rpl_slave_info.result index ec27166ecfb..2b9b6223401 100644 --- a/mysql-test/suite/mariabackup/rpl_slave_info.result +++ b/mysql-test/suite/mariabackup/rpl_slave_info.result @@ -11,8 +11,8 @@ connection master; CREATE TABLE t(i INT); connection slave; "using_gtid: Slave_Pos" -FOUND 1 /gtid_slave_pos/ in xtrabackup_slave_info -NOT FOUND /MASTER_LOG_FILE/ in xtrabackup_slave_info +FOUND 1 /gtid_slave_pos/ in mariadb_backup_slave_info +NOT FOUND /MASTER_LOG_FILE/ in mariadb_backup_slave_info lineno line 1 SET GLOBAL gtid_slave_pos = '<NUM-NUM-NUM>'; 2 CHANGE MASTER TO master_use_gtid = slave_pos; @@ -21,8 +21,8 @@ lineno line ######################## include/stop_slave.inc SET GLOBAL gtid_slave_pos=""; -NOT FOUND /gtid_slave_pos/ in xtrabackup_slave_info -FOUND 1 /MASTER_LOG_FILE/ in xtrabackup_slave_info +NOT FOUND /gtid_slave_pos/ in mariadb_backup_slave_info +FOUND 1 /MASTER_LOG_FILE/ in mariadb_backup_slave_info lineno line 1 CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=<NUM>; ############### @@ -34,8 +34,8 @@ connection master; INSERT INTO t VALUES(1); connection slave; "using_gtid: No" -NOT FOUND /gtid_slave_pos/ in xtrabackup_slave_info -FOUND 1 /MASTER_LOG_FILE/ in xtrabackup_slave_info +NOT FOUND /gtid_slave_pos/ in mariadb_backup_slave_info +FOUND 1 /MASTER_LOG_FILE/ in mariadb_backup_slave_info lineno line 1 CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=<NUM>; connection master; diff --git a/mysql-test/suite/mariabackup/rpl_slave_info.test b/mysql-test/suite/mariabackup/rpl_slave_info.test index 1c5dd89acc9..73ad00f13a0 100644 --- a/mysql-test/suite/mariabackup/rpl_slave_info.test +++ b/mysql-test/suite/mariabackup/rpl_slave_info.test @@ -22,7 +22,7 @@ CREATE TABLE t(i INT); exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffix=.2 --slave-info --backup --target-dir=$targetdir; --enable_result_log ---let SEARCH_FILE=$targetdir/xtrabackup_slave_info +--let SEARCH_FILE=$targetdir/mariadb_backup_slave_info --let SEARCH_PATTERN=gtid_slave_pos --source include/search_pattern_in_file.inc --let SEARCH_PATTERN=MASTER_LOG_FILE @@ -45,7 +45,7 @@ SET GLOBAL gtid_slave_pos=""; exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffix=.2 --slave-info --backup --target-dir=$targetdir; --enable_result_log ---let SEARCH_FILE=$targetdir/xtrabackup_slave_info +--let SEARCH_FILE=$targetdir/mariadb_backup_slave_info --let SEARCH_PATTERN=gtid_slave_pos --source include/search_pattern_in_file.inc --let SEARCH_PATTERN=MASTER_LOG_FILE @@ -73,7 +73,7 @@ INSERT INTO t VALUES(1); exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffix=.2 --slave-info --backup --target-dir=$targetdir; --enable_result_log ---let SEARCH_FILE=$targetdir/xtrabackup_slave_info +--let SEARCH_FILE=$targetdir/mariadb_backup_slave_info --let SEARCH_PATTERN=gtid_slave_pos --source include/search_pattern_in_file.inc --let SEARCH_PATTERN=MASTER_LOG_FILE diff --git a/mysql-test/suite/mariabackup/slave_info_norpl.result b/mysql-test/suite/mariabackup/slave_info_norpl.result index 04ca2fb2242..18cda94065b 100644 --- a/mysql-test/suite/mariabackup/slave_info_norpl.result +++ b/mysql-test/suite/mariabackup/slave_info_norpl.result @@ -8,7 +8,7 @@ SELECT @@global.gtid_slave_pos; @@global.gtid_slave_pos -# Without any masters the file xtrabackup_slave_info is not created +# Without any masters the file mariadb_backup_slave_info is not created line [00] YYYY-MM-DD hh:mm:ss Failed to get master binlog coordinates from SHOW SLAVE STATUS.This means that the server is not a replication slave. Ignoring the --slave-info option diff --git a/mysql-test/suite/mariabackup/slave_info_norpl.test b/mysql-test/suite/mariabackup/slave_info_norpl.test index 0d2d2ed4861..298aaa2dda5 100644 --- a/mysql-test/suite/mariabackup/slave_info_norpl.test +++ b/mysql-test/suite/mariabackup/slave_info_norpl.test @@ -19,13 +19,13 @@ SELECT @@global.gtid_slave_pos; --echo ---echo # Without any masters the file xtrabackup_slave_info is not created +--echo # Without any masters the file mariadb_backup_slave_info is not created --disable_result_log exec $XTRABACKUP $XTRABACKUP_ARGS >$XTRABACKUP_OUT; --enable_result_log --error 1 ---file_exists $targetdir/xtrabackup_slave_info +--file_exists $targetdir/mariadb_backup_slave_info --source include/show_xtrabackup_slave_info_out.inc --remove_file $XTRABACKUP_OUT rmdir $targetdir; diff --git a/mysql-test/suite/merge/merge.result b/mysql-test/suite/merge/merge.result index 590a2f74e34..d0df8334949 100644 --- a/mysql-test/suite/merge/merge.result +++ b/mysql-test/suite/merge/merge.result @@ -3898,9 +3898,6 @@ DROP TABLE t1; DROP TABLE m1; set global default_storage_engine=@save_default_storage_engine; # -# End of 10.0 tests -# -# # MDEV-27407 Different ASC/DESC index attributes on MERGE and underlying table can cause wrong results # create table t (a int, key(a desc)) engine=myisam; @@ -3981,3 +3978,12 @@ set use_stat_tables=default; # # End of 11.0 tests # +# +# MDEV-29174: UPDATE of view that uses MERGE table +# +CREATE TABLE t1 (a int) ENGINE=MERGE; +CREATE VIEW v1 AS SELECT a FROM t1; +UPDATE v1 SET a=0; +DROP VIEW v1; +DROP TABLE t1; +# End of 11.1 tests diff --git a/mysql-test/suite/merge/merge.test b/mysql-test/suite/merge/merge.test index 21b296a81d7..f35a41a06b2 100644 --- a/mysql-test/suite/merge/merge.test +++ b/mysql-test/suite/merge/merge.test @@ -2860,10 +2860,6 @@ set global default_storage_engine=@save_default_storage_engine; --source include/wait_until_count_sessions.inc --echo # ---echo # End of 10.0 tests ---echo # - ---echo # --echo # MDEV-27407 Different ASC/DESC index attributes on MERGE and underlying table can cause wrong results --echo # create table t (a int, key(a desc)) engine=myisam; @@ -2935,3 +2931,14 @@ set use_stat_tables=default; --echo # --echo # End of 11.0 tests --echo # +--echo # +--echo # MDEV-29174: UPDATE of view that uses MERGE table +--echo # + +CREATE TABLE t1 (a int) ENGINE=MERGE; +CREATE VIEW v1 AS SELECT a FROM t1; +UPDATE v1 SET a=0; +DROP VIEW v1; +DROP TABLE t1; + +--echo # End of 11.1 tests diff --git a/mysql-test/suite/optimizer_unfixed_bugs/r/bug41029.result b/mysql-test/suite/optimizer_unfixed_bugs/r/bug41029.result index eaad67de20c..b04b7551af0 100644 --- a/mysql-test/suite/optimizer_unfixed_bugs/r/bug41029.result +++ b/mysql-test/suite/optimizer_unfixed_bugs/r/bug41029.result @@ -15,8 +15,8 @@ create table t1 (dummy int primary key, a int unique, b int) engine=innodb; insert into t1 values(1,1,1),(3,3,3),(5,5,5); commit; set session transaction isolation level repeatable read; -select @@tx_isolation; -@@tx_isolation +select @@transaction_isolation; +@@transaction_isolation REPEATABLE-READ start transaction; select * from t1 where a > 2 for update; diff --git a/mysql-test/suite/optimizer_unfixed_bugs/t/bug41029.test b/mysql-test/suite/optimizer_unfixed_bugs/t/bug41029.test index b7c0dc5332c..ba5eea05909 100644 --- a/mysql-test/suite/optimizer_unfixed_bugs/t/bug41029.test +++ b/mysql-test/suite/optimizer_unfixed_bugs/t/bug41029.test @@ -22,7 +22,7 @@ create table t1 (dummy int primary key, a int unique, b int) engine=innodb; insert into t1 values(1,1,1),(3,3,3),(5,5,5); commit; set session transaction isolation level repeatable read; -select @@tx_isolation; +select @@transaction_isolation; start transaction; select * from t1 where a > 2 for update; diff --git a/mysql-test/suite/perfschema/r/transaction.result b/mysql-test/suite/perfschema/r/transaction.result index 9a7eb5b3eb5..c516a4543c2 100644 --- a/mysql-test/suite/perfschema/r/transaction.result +++ b/mysql-test/suite/perfschema/r/transaction.result @@ -39,8 +39,8 @@ CALL clear_transaction_tables(); # ======================================================================== # connection con1; -SELECT @@global.tx_isolation; -@@global.tx_isolation +SELECT @@global.transaction_isolation; +@@global.transaction_isolation REPEATABLE-READ SELECT @@global.autocommit; @@global.autocommit @@ -48,8 +48,8 @@ SELECT @@global.autocommit; SELECT @@global.binlog_format; @@global.binlog_format ROW -SELECT @@tx_isolation; -@@tx_isolation +SELECT @@transaction_isolation; +@@transaction_isolation REPEATABLE-READ SELECT @@autocommit; @@autocommit diff --git a/mysql-test/suite/perfschema/t/transaction.test b/mysql-test/suite/perfschema/t/transaction.test index b616460374e..d950139f7d6 100644 --- a/mysql-test/suite/perfschema/t/transaction.test +++ b/mysql-test/suite/perfschema/t/transaction.test @@ -90,10 +90,10 @@ CALL clear_transaction_tables(); --echo # ======================================================================== --echo # --connection con1 -SELECT @@global.tx_isolation; +SELECT @@global.transaction_isolation; SELECT @@global.autocommit; SELECT @@global.binlog_format; -SELECT @@tx_isolation; +SELECT @@transaction_isolation; SELECT @@autocommit; SELECT @@binlog_format; diff --git a/mysql-test/suite/period/r/update.result b/mysql-test/suite/period/r/update.result index f726b4c07cf..004b9976f51 100644 --- a/mysql-test/suite/period/r/update.result +++ b/mysql-test/suite/period/r/update.result @@ -229,8 +229,8 @@ update t for portion of apptime from @s to g() set t.id= t.id + 5; ERROR HY000: Expression in FOR PORTION OF must be constant # success update t for portion of apptime from @s to h() set t.id= t.id + 5; -# select value is cached update t for portion of apptime from (select s from t2 limit 1) to h() set t.id= t.id + 5; +ERROR HY000: Expression in FOR PORTION OF must be constant # auto_inrement field is updated create or replace table t (id int primary key auto_increment, x int, s date, e date, period for apptime(s, e)); diff --git a/mysql-test/suite/period/t/update.test b/mysql-test/suite/period/t/update.test index 3f4dd2bdc68..fd67dc328c1 100644 --- a/mysql-test/suite/period/t/update.test +++ b/mysql-test/suite/period/t/update.test @@ -123,7 +123,7 @@ update t for portion of apptime from @s to g() set t.id= t.id + 5; --echo # success update t for portion of apptime from @s to h() set t.id= t.id + 5; ---echo # select value is cached +--error ER_NOT_CONSTANT_EXPRESSION update t for portion of apptime from (select s from t2 limit 1) to h() set t.id= t.id + 5; --echo # auto_inrement field is updated diff --git a/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result b/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result index eff939512e2..e8d377d5d2d 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result @@ -270,7 +270,7 @@ connection server_2; include/stop_slave.inc SET @old_format= @@GLOBAL.binlog_format; SET GLOBAL binlog_format= MIXED; -SET @old_isolation= @@GLOBAL.tx_isolation; +SET @old_isolation= @@GLOBAL.transaction_isolation; SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; SET GLOBAL slave_parallel_threads=0; SET GLOBAL slave_parallel_threads=10; @@ -346,7 +346,7 @@ a b 10 10 include/stop_slave.inc SET GLOBAL binlog_format= @old_format; -SET GLOBAL tx_isolation= @old_isolation; +SET GLOBAL transaction_isolation= @old_isolation; include/start_slave.inc *** MDEV-7888: ANALYZE TABLE does wakeup_subsequent_commits(), causing wrong binlog order and parallel replication hang *** connection server_1; diff --git a/mysql-test/suite/rpl/r/rpl_parallel_optimistic_nobinlog.result b/mysql-test/suite/rpl/r/rpl_parallel_optimistic_nobinlog.result index 4172abb17d9..28c5ceb1f6c 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_optimistic_nobinlog.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_optimistic_nobinlog.result @@ -6,7 +6,7 @@ CREATE TABLE t2 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; INSERT INTO t1 VALUES (1,0), (2,0), (3,0); INSERT INTO t2 VALUES (1,0), (2,0); connection server_2; -SET @old_isolation= @@GLOBAL.tx_isolation; +SET @old_isolation= @@GLOBAL.transaction_isolation; SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; include/stop_slave.inc SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; @@ -82,7 +82,7 @@ a b 10 10 connection server_2; include/stop_slave.inc -SET GLOBAL tx_isolation= @old_isolation; +SET GLOBAL transaction_isolation= @old_isolation; SET GLOBAL slave_parallel_mode=@old_parallel_mode; SET GLOBAL slave_parallel_threads=@old_parallel_threads; include/start_slave.inc diff --git a/mysql-test/suite/rpl/r/rpl_xa.result b/mysql-test/suite/rpl/r/rpl_xa.result index 061c7b360d0..91e2a1f3ab5 100644 --- a/mysql-test/suite/rpl/r/rpl_xa.result +++ b/mysql-test/suite/rpl/r/rpl_xa.result @@ -225,7 +225,7 @@ drop table t1, t2, t3, tm; create table t1 (a int primary key, b int unique) engine=innodb; insert t1 values (1,1),(3,3),(5,5); connection slave; -set session tx_isolation='repeatable-read'; +set session transaction_isolation='repeatable-read'; start transaction; select * from t1; a b diff --git a/mysql-test/suite/rpl/r/rpl_xa_gtid_pos_auto_engine.result b/mysql-test/suite/rpl/r/rpl_xa_gtid_pos_auto_engine.result index 35625cc7026..66300e4d6d3 100644 --- a/mysql-test/suite/rpl/r/rpl_xa_gtid_pos_auto_engine.result +++ b/mysql-test/suite/rpl/r/rpl_xa_gtid_pos_auto_engine.result @@ -234,7 +234,7 @@ drop table t1, t2, t3, tm; create table t1 (a int primary key, b int unique) engine=innodb; insert t1 values (1,1),(3,3),(5,5); connection slave; -set session tx_isolation='repeatable-read'; +set session transaction_isolation='repeatable-read'; start transaction; select * from t1; a b diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test index f5e48282326..81c787bba5b 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test @@ -272,7 +272,7 @@ eval SELECT IF($retry1=$retry2, "Ok, no retry", SET @old_format= @@GLOBAL.binlog_format; # Use MIXED format; we cannot binlog ROW events on slave in STATEMENT format. SET GLOBAL binlog_format= MIXED; -SET @old_isolation= @@GLOBAL.tx_isolation; +SET @old_isolation= @@GLOBAL.transaction_isolation; SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; # Reset the worker threads to make the new settings take effect. SET GLOBAL slave_parallel_threads=0; @@ -317,7 +317,7 @@ SELECT * FROM t2 ORDER BY a; --source include/stop_slave.inc SET GLOBAL binlog_format= @old_format; -SET GLOBAL tx_isolation= @old_isolation; +SET GLOBAL transaction_isolation= @old_isolation; --source include/start_slave.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.test index ee0de499edf..b8df2ffae46 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.test @@ -14,7 +14,7 @@ INSERT INTO t2 VALUES (1,0), (2,0); --connection server_2 --sync_with_master -SET @old_isolation= @@GLOBAL.tx_isolation; +SET @old_isolation= @@GLOBAL.transaction_isolation; SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; --source include/stop_slave.inc SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; @@ -62,7 +62,7 @@ SELECT * FROM t2 ORDER BY a; --connection server_2 --source include/stop_slave.inc -SET GLOBAL tx_isolation= @old_isolation; +SET GLOBAL transaction_isolation= @old_isolation; SET GLOBAL slave_parallel_mode=@old_parallel_mode; SET GLOBAL slave_parallel_threads=@old_parallel_threads; --source include/start_slave.inc diff --git a/mysql-test/suite/rpl/t/rpl_xa.inc b/mysql-test/suite/rpl/t/rpl_xa.inc index d22d2d2ef3d..30e7a4bbe4a 100644 --- a/mysql-test/suite/rpl/t/rpl_xa.inc +++ b/mysql-test/suite/rpl/t/rpl_xa.inc @@ -363,7 +363,7 @@ sync_slave_with_master; # set a strong isolation level to keep the read view below. # alternatively a long-running select can do that too even in read-committed -set session tx_isolation='repeatable-read'; +set session transaction_isolation='repeatable-read'; start transaction; # opens a read view to disable purge on the slave select * from t1; diff --git a/mysql-test/suite/sys_vars/r/innodb_defragment_basic.result b/mysql-test/suite/sys_vars/r/innodb_defragment_basic.result deleted file mode 100644 index d9226fee99f..00000000000 --- a/mysql-test/suite/sys_vars/r/innodb_defragment_basic.result +++ /dev/null @@ -1,24 +0,0 @@ -SET @orig = @@global.innodb_defragment; -SELECT @orig; -@orig -0 -SET GLOBAL innodb_defragment = OFF; -Warnings: -Warning 1287 '@@innodb_defragment' is deprecated and will be removed in a future release -SELECT @@global.innodb_defragment; -@@global.innodb_defragment -0 -SET GLOBAL innodb_defragment = ON; -Warnings: -Warning 1287 '@@innodb_defragment' is deprecated and will be removed in a future release -SELECT @@global.innodb_defragment; -@@global.innodb_defragment -1 -SET GLOBAL innodb_defragment = 100; -ERROR 42000: Variable 'innodb_defragment' can't be set to the value of '100' -SELECT @@global.innodb_defragment; -@@global.innodb_defragment -1 -SET GLOBAL innodb_defragment = @orig; -Warnings: -Warning 1287 '@@innodb_defragment' is deprecated and will be removed in a future release diff --git a/mysql-test/suite/sys_vars/r/innodb_defragment_fill_factor_basic.result b/mysql-test/suite/sys_vars/r/innodb_defragment_fill_factor_basic.result deleted file mode 100644 index 04db2580f15..00000000000 --- a/mysql-test/suite/sys_vars/r/innodb_defragment_fill_factor_basic.result +++ /dev/null @@ -1,47 +0,0 @@ -SET @start_innodb_defragment_fill_factor = @@global.innodb_defragment_fill_factor; -SELECT @start_innodb_defragment_fill_factor; -@start_innodb_defragment_fill_factor -0.9 -SELECT COUNT(@@global.innodb_defragment_fill_factor); -COUNT(@@global.innodb_defragment_fill_factor) -1 -SET @@global.innodb_defragment_fill_factor = 0.77777777777777; -Warnings: -Warning 1287 '@@innodb_defragment_fill_factor' is deprecated and will be removed in a future release -SELECT @@global.innodb_defragment_fill_factor; -@@global.innodb_defragment_fill_factor -0.777778 -SET @@global.innodb_defragment_fill_factor = 1; -Warnings: -Warning 1287 '@@innodb_defragment_fill_factor' is deprecated and will be removed in a future release -SELECT @@global.innodb_defragment_fill_factor; -@@global.innodb_defragment_fill_factor -1.000000 -SET @@global.innodb_defragment_fill_factor = 0.7; -Warnings: -Warning 1287 '@@innodb_defragment_fill_factor' is deprecated and will be removed in a future release -SELECT @@global.innodb_defragment_fill_factor; -@@global.innodb_defragment_fill_factor -0.700000 -SET @@global.innodb_defragment_fill_factor = -1; -Warnings: -Warning 1287 '@@innodb_defragment_fill_factor' is deprecated and will be removed in a future release -Warning 1292 Truncated incorrect innodb_defragment_fill_factor value: '-1' -SELECT @@global.innodb_defragment_fill_factor; -@@global.innodb_defragment_fill_factor -0.700000 -SET @@global.innodb_defragment_fill_factor = 2; -Warnings: -Warning 1287 '@@innodb_defragment_fill_factor' is deprecated and will be removed in a future release -Warning 1292 Truncated incorrect innodb_defragment_fill_factor value: '2' -SELECT @@global.innodb_defragment_fill_factor; -@@global.innodb_defragment_fill_factor -1.000000 -SET @@global.innodb_defragment_fill_factor = "abc"; -ERROR 42000: Incorrect argument type to variable 'innodb_defragment_fill_factor' -SELECT @@global.innodb_defragment_fill_factor; -@@global.innodb_defragment_fill_factor -1.000000 -SET @@global.innodb_defragment_fill_factor = @start_innodb_defragment_fill_factor; -Warnings: -Warning 1287 '@@innodb_defragment_fill_factor' is deprecated and will be removed in a future release diff --git a/mysql-test/suite/sys_vars/r/innodb_defragment_fill_factor_n_recs_basic.result b/mysql-test/suite/sys_vars/r/innodb_defragment_fill_factor_n_recs_basic.result deleted file mode 100644 index 12bec5204f6..00000000000 --- a/mysql-test/suite/sys_vars/r/innodb_defragment_fill_factor_n_recs_basic.result +++ /dev/null @@ -1,52 +0,0 @@ -SET @start_innodb_defragment_fill_factor_n_recs = @@global.innodb_defragment_fill_factor_n_recs; -SELECT @start_innodb_defragment_fill_factor_n_recs; -@start_innodb_defragment_fill_factor_n_recs -20 -SELECT COUNT(@@global.innodb_defragment_fill_factor_n_recs); -COUNT(@@global.innodb_defragment_fill_factor_n_recs) -1 -SET @@global.innodb_defragment_fill_factor_n_recs = 50; -Warnings: -Warning 1287 '@@innodb_defragment_fill_factor_n_recs' is deprecated and will be removed in a future release -SELECT @@global.innodb_defragment_fill_factor_n_recs; -@@global.innodb_defragment_fill_factor_n_recs -50 -SET @@global.innodb_defragment_fill_factor_n_recs = 100; -Warnings: -Warning 1287 '@@innodb_defragment_fill_factor_n_recs' is deprecated and will be removed in a future release -SELECT @@global.innodb_defragment_fill_factor_n_recs; -@@global.innodb_defragment_fill_factor_n_recs -100 -SET @@global.innodb_defragment_fill_factor_n_recs = 1; -Warnings: -Warning 1287 '@@innodb_defragment_fill_factor_n_recs' is deprecated and will be removed in a future release -SELECT @@global.innodb_defragment_fill_factor_n_recs; -@@global.innodb_defragment_fill_factor_n_recs -1 -SET @@global.innodb_defragment_fill_factor_n_recs = -1; -Warnings: -Warning 1287 '@@innodb_defragment_fill_factor_n_recs' is deprecated and will be removed in a future release -Warning 1292 Truncated incorrect innodb_defragment_fill_factor... value: '-1' -SELECT @@global.innodb_defragment_fill_factor_n_recs; -@@global.innodb_defragment_fill_factor_n_recs -1 -SET @@global.innodb_defragment_fill_factor_n_recs = 10000; -Warnings: -Warning 1287 '@@innodb_defragment_fill_factor_n_recs' is deprecated and will be removed in a future release -Warning 1292 Truncated incorrect innodb_defragment_fill_factor... value: '10000' -SELECT @@global.innodb_defragment_fill_factor_n_recs; -@@global.innodb_defragment_fill_factor_n_recs -100 -SET @@global.innodb_defragment_fill_factor_n_recs = 10.5; -ERROR 42000: Incorrect argument type to variable 'innodb_defragment_fill_factor_n_recs' -SELECT @@global.innodb_defragment_fill_factor_n_recs; -@@global.innodb_defragment_fill_factor_n_recs -100 -SET @@global.innodb_defragment_fill_factor_n_recs = "abc"; -ERROR 42000: Incorrect argument type to variable 'innodb_defragment_fill_factor_n_recs' -SELECT @@global.innodb_defragment_fill_factor_n_recs; -@@global.innodb_defragment_fill_factor_n_recs -100 -SET @@global.innodb_defragment_fill_factor_n_recs = @start_innodb_defragment_fill_factor_n_recs; -Warnings: -Warning 1287 '@@innodb_defragment_fill_factor_n_recs' is deprecated and will be removed in a future release diff --git a/mysql-test/suite/sys_vars/r/innodb_defragment_frequency_basic.result b/mysql-test/suite/sys_vars/r/innodb_defragment_frequency_basic.result deleted file mode 100644 index b9f76d60dac..00000000000 --- a/mysql-test/suite/sys_vars/r/innodb_defragment_frequency_basic.result +++ /dev/null @@ -1,52 +0,0 @@ -SET @start_innodb_defragment_frequency = @@global.innodb_defragment_frequency; -SELECT @start_innodb_defragment_frequency; -@start_innodb_defragment_frequency -40 -SELECT COUNT(@@global.innodb_defragment_frequency); -COUNT(@@global.innodb_defragment_frequency) -1 -SET @@global.innodb_defragment_frequency = 200; -Warnings: -Warning 1287 '@@innodb_defragment_frequency' is deprecated and will be removed in a future release -SELECT @@global.innodb_defragment_frequency; -@@global.innodb_defragment_frequency -200 -SET @@global.innodb_defragment_frequency = 1; -Warnings: -Warning 1287 '@@innodb_defragment_frequency' is deprecated and will be removed in a future release -SELECT @@global.innodb_defragment_frequency; -@@global.innodb_defragment_frequency -1 -SET @@global.innodb_defragment_frequency = 1000; -Warnings: -Warning 1287 '@@innodb_defragment_frequency' is deprecated and will be removed in a future release -SELECT @@global.innodb_defragment_frequency; -@@global.innodb_defragment_frequency -1000 -SET @@global.innodb_defragment_frequency = -1; -Warnings: -Warning 1287 '@@innodb_defragment_frequency' is deprecated and will be removed in a future release -Warning 1292 Truncated incorrect innodb_defragment_frequency value: '-1' -SELECT @@global.innodb_defragment_frequency; -@@global.innodb_defragment_frequency -1 -SET @@global.innodb_defragment_frequency = 10000; -Warnings: -Warning 1287 '@@innodb_defragment_frequency' is deprecated and will be removed in a future release -Warning 1292 Truncated incorrect innodb_defragment_frequency value: '10000' -SELECT @@global.innodb_defragment_frequency; -@@global.innodb_defragment_frequency -1000 -SET @@global.innodb_defragment_frequency = 10.5; -ERROR 42000: Incorrect argument type to variable 'innodb_defragment_frequency' -SELECT @@global.innodb_defragment_frequency; -@@global.innodb_defragment_frequency -1000 -SET @@global.innodb_defragment_frequency = "abc"; -ERROR 42000: Incorrect argument type to variable 'innodb_defragment_frequency' -SELECT @@global.innodb_defragment_frequency; -@@global.innodb_defragment_frequency -1000 -SET @@global.innodb_defragment_frequency = @start_innodb_defragment_frequency; -Warnings: -Warning 1287 '@@innodb_defragment_frequency' is deprecated and will be removed in a future release diff --git a/mysql-test/suite/sys_vars/r/innodb_defragment_n_pages_basic.result b/mysql-test/suite/sys_vars/r/innodb_defragment_n_pages_basic.result deleted file mode 100644 index 823ddad7d59..00000000000 --- a/mysql-test/suite/sys_vars/r/innodb_defragment_n_pages_basic.result +++ /dev/null @@ -1,36 +0,0 @@ -SET @start_innodb_defragment_n_pages = @@global.innodb_defragment_n_pages; -SELECT @start_innodb_defragment_n_pages; -@start_innodb_defragment_n_pages -7 -SELECT COUNT(@@global.innodb_defragment_n_pages); -COUNT(@@global.innodb_defragment_n_pages) -1 -SET @@global.innodb_defragment_n_pages = 1; -Warnings: -Warning 1287 '@@innodb_defragment_n_pages' is deprecated and will be removed in a future release -Warning 1292 Truncated incorrect innodb_defragment_n_pages value: '1' -SELECT @@global.innodb_defragment_n_pages; -@@global.innodb_defragment_n_pages -2 -SET @@global.innodb_defragment_n_pages = 2; -Warnings: -Warning 1287 '@@innodb_defragment_n_pages' is deprecated and will be removed in a future release -SELECT @@global.innodb_defragment_n_pages; -@@global.innodb_defragment_n_pages -2 -SET @@global.innodb_defragment_n_pages = 32; -Warnings: -Warning 1287 '@@innodb_defragment_n_pages' is deprecated and will be removed in a future release -SELECT @@global.innodb_defragment_n_pages; -@@global.innodb_defragment_n_pages -32 -SET @@global.innodb_defragment_n_pages = 64; -Warnings: -Warning 1287 '@@innodb_defragment_n_pages' is deprecated and will be removed in a future release -Warning 1292 Truncated incorrect innodb_defragment_n_pages value: '64' -SELECT @@global.innodb_defragment_n_pages; -@@global.innodb_defragment_n_pages -32 -SET @@global.innodb_defragment_n_pages = @start_innodb_defragment_n_pages; -Warnings: -Warning 1287 '@@innodb_defragment_n_pages' is deprecated and will be removed in a future release diff --git a/mysql-test/suite/sys_vars/r/innodb_defragment_stats_accuracy_basic.result b/mysql-test/suite/sys_vars/r/innodb_defragment_stats_accuracy_basic.result deleted file mode 100644 index 7a2abfa1350..00000000000 --- a/mysql-test/suite/sys_vars/r/innodb_defragment_stats_accuracy_basic.result +++ /dev/null @@ -1,41 +0,0 @@ -SET @start_innodb_defragment_stats_accuracy = @@global.innodb_defragment_stats_accuracy; -SELECT @start_innodb_defragment_stats_accuracy; -@start_innodb_defragment_stats_accuracy -0 -SELECT COUNT(@@global.innodb_defragment_stats_accuracy); -COUNT(@@global.innodb_defragment_stats_accuracy) -1 -SET @@global.innodb_defragment_stats_accuracy = 1; -Warnings: -Warning 1287 '@@innodb_defragment_stats_accuracy' is deprecated and will be removed in a future release -SELECT @@global.innodb_defragment_stats_accuracy; -@@global.innodb_defragment_stats_accuracy -1 -SET @@global.innodb_defragment_stats_accuracy = 1000; -Warnings: -Warning 1287 '@@innodb_defragment_stats_accuracy' is deprecated and will be removed in a future release -SELECT @@global.innodb_defragment_stats_accuracy; -@@global.innodb_defragment_stats_accuracy -1000 -SET @@global.innodb_defragment_stats_accuracy = -1; -Warnings: -Warning 1287 '@@innodb_defragment_stats_accuracy' is deprecated and will be removed in a future release -Warning 1292 Truncated incorrect innodb_defragment_stats_accuracy value: '-1' -SELECT @@global.innodb_defragment_stats_accuracy; -@@global.innodb_defragment_stats_accuracy -0 -SET @@global.innodb_defragment_stats_accuracy = 1000000000000; -Warnings: -Warning 1287 '@@innodb_defragment_stats_accuracy' is deprecated and will be removed in a future release -Warning 1292 Truncated incorrect innodb_defragment_stats_accuracy value: '1000000000000' -SELECT @@global.innodb_defragment_stats_accuracy; -@@global.innodb_defragment_stats_accuracy -4294967295 -SET @@global.innodb_defragment_stats_accuracy = "abc"; -ERROR 42000: Incorrect argument type to variable 'innodb_defragment_stats_accuracy' -SELECT @@global.innodb_defragment_stats_accuracy; -@@global.innodb_defragment_stats_accuracy -4294967295 -SET @@global.innodb_defragment_stats_accuracy = @start_innodb_defragment_stats_accuracy; -Warnings: -Warning 1287 '@@innodb_defragment_stats_accuracy' is deprecated and will be removed in a future release diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index 23bb062af74..a2bf4415ba1 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -415,78 +415,6 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST redundant,compact,dynamic READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME INNODB_DEFRAGMENT -SESSION_VALUE NULL -DEFAULT_VALUE OFF -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Enable/disable InnoDB defragmentation (default FALSE). When set to FALSE, all existing defragmentation will be paused. And new defragmentation command will fail.Paused defragmentation commands will resume when this variable is set to true again. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME INNODB_DEFRAGMENT_FILL_FACTOR -SESSION_VALUE NULL -DEFAULT_VALUE 0.900000 -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE DOUBLE -VARIABLE_COMMENT A number between [0.7, 1] that tells defragmentation how full it should fill a page. Default is 0.9. Number below 0.7 won't make much sense.This variable, together with innodb_defragment_fill_factor_n_recs, is introduced so defragmentation won't pack the page too full and cause page split on the next insert on every page. The variable indicating more defragmentation gain is the one effective. -NUMERIC_MIN_VALUE 0.7 -NUMERIC_MAX_VALUE 1 -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME INNODB_DEFRAGMENT_FILL_FACTOR_N_RECS -SESSION_VALUE NULL -DEFAULT_VALUE 20 -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE INT UNSIGNED -VARIABLE_COMMENT How many records of space defragmentation should leave on the page. This variable, together with innodb_defragment_fill_factor, is introduced so defragmentation won't pack the page too full and cause page split on the next insert on every page. The variable indicating more defragmentation gain is the one effective. -NUMERIC_MIN_VALUE 1 -NUMERIC_MAX_VALUE 100 -NUMERIC_BLOCK_SIZE 0 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME INNODB_DEFRAGMENT_FREQUENCY -SESSION_VALUE NULL -DEFAULT_VALUE 40 -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE INT UNSIGNED -VARIABLE_COMMENT Do not defragment a single index more than this number of time per second.This controls the number of time defragmentation thread can request X_LOCK on an index. Defragmentation thread will check whether 1/defragment_frequency (s) has passed since it worked on this index last time, and put the index back to the queue if not enough time has passed. The actual frequency can only be lower than this given number. -NUMERIC_MIN_VALUE 1 -NUMERIC_MAX_VALUE 1000 -NUMERIC_BLOCK_SIZE 0 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME INNODB_DEFRAGMENT_N_PAGES -SESSION_VALUE NULL -DEFAULT_VALUE 7 -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE INT UNSIGNED -VARIABLE_COMMENT Number of pages considered at once when merging multiple pages to defragment -NUMERIC_MIN_VALUE 2 -NUMERIC_MAX_VALUE 32 -NUMERIC_BLOCK_SIZE 0 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME INNODB_DEFRAGMENT_STATS_ACCURACY -SESSION_VALUE NULL -DEFAULT_VALUE 0 -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE INT UNSIGNED -VARIABLE_COMMENT How many defragment stats changes there are before the stats are written to persistent storage. Set to 0 meaning disable defragment stats tracking. -NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 4294967295 -NUMERIC_BLOCK_SIZE 0 -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME INNODB_DISABLE_SORT_FILE_CACHE SESSION_VALUE NULL DEFAULT_VALUE OFF diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index bbf6c22b70f..88d3bb1789e 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -3902,6 +3902,16 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME TRANSACTION_ISOLATION +VARIABLE_SCOPE SESSION +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Default transaction isolation level +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST READ-UNCOMMITTED,READ-COMMITTED,REPEATABLE-READ,SERIALIZABLE +READ_ONLY NO +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME TRANSACTION_PREALLOC_SIZE VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED @@ -3912,10 +3922,20 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME TRANSACTION_READ_ONLY +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Default transaction access mode. If set to OFF, the default, access is read/write. If set to ON, access is read-only. The SET TRANSACTION statement can also change the value of this variable. See SET TRANSACTION and START TRANSACTION. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME TX_ISOLATION VARIABLE_SCOPE SESSION VARIABLE_TYPE ENUM -VARIABLE_COMMENT Default transaction isolation level +VARIABLE_COMMENT Default transaction isolation level.This variable is deprecated and will be removed in a future release. NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL @@ -3925,7 +3945,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME TX_READ_ONLY VARIABLE_SCOPE SESSION VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Default transaction access mode. If set to OFF, the default, access is read/write. If set to ON, access is read-only. The SET TRANSACTION statement can also change the value of this variable. See SET TRANSACTION and START TRANSACTION. +VARIABLE_COMMENT Default transaction access mode. If set to OFF, the default, access is read/write. If set to ON, access is read-only. The SET TRANSACTION statement can also change the value of this variable. See SET TRANSACTION and START TRANSACTION.This variable is deprecated and will be removed in a future release. NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 545a1ad7a6b..a37735fa769 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -4712,6 +4712,16 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME TRANSACTION_ISOLATION +VARIABLE_SCOPE SESSION +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Default transaction isolation level +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST READ-UNCOMMITTED,READ-COMMITTED,REPEATABLE-READ,SERIALIZABLE +READ_ONLY NO +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME TRANSACTION_PREALLOC_SIZE VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED @@ -4722,10 +4732,20 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME TRANSACTION_READ_ONLY +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Default transaction access mode. If set to OFF, the default, access is read/write. If set to ON, access is read-only. The SET TRANSACTION statement can also change the value of this variable. See SET TRANSACTION and START TRANSACTION. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME TX_ISOLATION VARIABLE_SCOPE SESSION VARIABLE_TYPE ENUM -VARIABLE_COMMENT Default transaction isolation level +VARIABLE_COMMENT Default transaction isolation level.This variable is deprecated and will be removed in a future release. NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL @@ -4735,7 +4755,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME TX_READ_ONLY VARIABLE_SCOPE SESSION VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Default transaction access mode. If set to OFF, the default, access is read/write. If set to ON, access is read-only. The SET TRANSACTION statement can also change the value of this variable. See SET TRANSACTION and START TRANSACTION. +VARIABLE_COMMENT Default transaction access mode. If set to OFF, the default, access is read/write. If set to ON, access is read-only. The SET TRANSACTION statement can also change the value of this variable. See SET TRANSACTION and START TRANSACTION.This variable is deprecated and will be removed in a future release. NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL diff --git a/mysql-test/suite/sys_vars/r/sysvars_star.result b/mysql-test/suite/sys_vars/r/sysvars_star.result index b3357fda3af..b4c0ea87581 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_star.result +++ b/mysql-test/suite/sys_vars/r/sysvars_star.result @@ -60,7 +60,7 @@ VARIABLE_NAME PLUGIN_MATURITY SESSION_VALUE NULL GLOBAL_VALUE alpha GLOBAL_VALUE_ORIGIN CONFIG -DEFAULT_VALUE beta +DEFAULT_VALUE alpha VARIABLE_SCOPE GLOBAL VARIABLE_TYPE ENUM VARIABLE_COMMENT The lowest desirable plugin maturity. Plugins less mature than that will not be installed or loaded diff --git a/mysql-test/suite/sys_vars/r/transaction_isolation_basic.result b/mysql-test/suite/sys_vars/r/transaction_isolation_basic.result new file mode 100644 index 00000000000..ef5d60072a9 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/transaction_isolation_basic.result @@ -0,0 +1,141 @@ +SET @global_start_value = @@global.transaction_isolation; +SELECT @global_start_value; +@global_start_value +REPEATABLE-READ +SET @session_start_value = @@session.transaction_isolation; +SELECT @session_start_value; +@session_start_value +REPEATABLE-READ +'#--------------------FN_DYNVARS_183_01------------------------#' +SET @@global.transaction_isolation = 'READ-UNCOMMITTED'; +SET @@global.transaction_isolation = DEFAULT; +SELECT @@global.transaction_isolation; +@@global.transaction_isolation +REPEATABLE-READ +SET @@session.transaction_isolation = DEFAULT; +SELECT @@session.transaction_isolation; +@@session.transaction_isolation +REPEATABLE-READ +'#---------------------FN_DYNVARS_183_02-------------------------#' +SET @@global.transaction_isolation = NULL; +ERROR 42000: Variable 'transaction_isolation' can't be set to the value of 'NULL' +SET @@global.transaction_isolation = ''; +ERROR 42000: Variable 'transaction_isolation' can't be set to the value of '' +SET @@session.transaction_isolation = NULL; +ERROR 42000: Variable 'transaction_isolation' can't be set to the value of 'NULL' +SET @@session.transaction_isolation = ''; +ERROR 42000: Variable 'transaction_isolation' can't be set to the value of '' +'#--------------------FN_DYNVARS_183_03------------------------#' +SET @@global.transaction_isolation = 'READ-UNCOMMITTED'; +SELECT @@global.transaction_isolation; +@@global.transaction_isolation +READ-UNCOMMITTED +SET @@global.transaction_isolation = 'read-COMMITTED'; +SELECT @@global.transaction_isolation; +@@global.transaction_isolation +READ-COMMITTED +SET @@global.transaction_isolation = 'REPEATABLE-READ'; +SELECT @@global.transaction_isolation; +@@global.transaction_isolation +REPEATABLE-READ +SET @@global.transaction_isolation = 'SERIALIZable'; +SELECT @@global.transaction_isolation; +@@global.transaction_isolation +SERIALIZABLE +SET @@session.transaction_isolation = 'READ-UNCOMMITTED'; +SELECT @@session.transaction_isolation; +@@session.transaction_isolation +READ-UNCOMMITTED +SET @@session.transaction_isolation = 'READ-COMMITTED'; +SELECT @@session.transaction_isolation; +@@session.transaction_isolation +READ-COMMITTED +SET @@session.transaction_isolation = 'REPEATABLE-READ'; +SELECT @@session.transaction_isolation; +@@session.transaction_isolation +REPEATABLE-READ +SET @@session.transaction_isolation = 'serializable'; +SELECT @@session.transaction_isolation; +@@session.transaction_isolation +SERIALIZABLE +'#--------------------FN_DYNVARS_183_04-------------------------#' +SET @@global.transaction_isolation = -1; +ERROR 42000: Variable 'transaction_isolation' can't be set to the value of '-1' +SET @@global.transaction_isolation = READUNCOMMITTED; +ERROR 42000: Variable 'transaction_isolation' can't be set to the value of 'READUNCOMMITTED' +SET @@global.transaction_isolation = 'REPEATABLE'; +ERROR 42000: Variable 'transaction_isolation' can't be set to the value of 'REPEATABLE' +SET @@global.transaction_isolation = OFF; +ERROR 42000: Variable 'transaction_isolation' can't be set to the value of 'OFF' +SET @@global.transaction_isolation = ON; +ERROR 42000: Variable 'transaction_isolation' can't be set to the value of 'ON' +SET @@global.transaction_isolation = 'NON-SERIALIZABLE'; +ERROR 42000: Variable 'transaction_isolation' can't be set to the value of 'NON-SERIALIZABLE' +SET @@transaction_isolation = -1; +ERROR 42000: Variable 'transaction_isolation' can't be set to the value of '-1' +SET @@transaction_isolation = READUNCOMMITTED; +ERROR 42000: Variable 'transaction_isolation' can't be set to the value of 'READUNCOMMITTED' +SET @@transaction_isolation = 'REPEATABLE'; +ERROR 42000: Variable 'transaction_isolation' can't be set to the value of 'REPEATABLE' +SET @@transaction_isolation = 'NONE'; +ERROR 42000: Variable 'transaction_isolation' can't be set to the value of 'NONE' +SET @@transaction_isolation = 'ALL'; +ERROR 42000: Variable 'transaction_isolation' can't be set to the value of 'ALL' +'#-------------------FN_DYNVARS_183_05----------------------------#' +SELECT @@session.transaction_isolation = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.SESSION_VARIABLES +WHERE VARIABLE_NAME='transaction_isolation'; +@@session.transaction_isolation = VARIABLE_VALUE +1 +'#----------------------FN_DYNVARS_183_06------------------------#' +SELECT @@global.transaction_isolation = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='transaction_isolation'; +@@global.transaction_isolation = VARIABLE_VALUE +1 +'#---------------------FN_DYNVARS_183_07-------------------------#' +SET @@global.transaction_isolation = 0; +SELECT @@global.transaction_isolation; +@@global.transaction_isolation +READ-UNCOMMITTED +SET @@global.transaction_isolation = 1; +SELECT @@global.transaction_isolation; +@@global.transaction_isolation +READ-COMMITTED +SET @@global.transaction_isolation = 2; +SELECT @@global.transaction_isolation; +@@global.transaction_isolation +REPEATABLE-READ +SET @@global.transaction_isolation = 3; +SELECT @@global.transaction_isolation; +@@global.transaction_isolation +SERIALIZABLE +SET @@global.transaction_isolation = 0.4; +ERROR 42000: Incorrect argument type to variable 'transaction_isolation' +'#---------------------FN_DYNVARS_183_08----------------------#' +SET @@global.transaction_isolation = TRUE; +SELECT @@global.transaction_isolation; +@@global.transaction_isolation +READ-COMMITTED +SET @@global.transaction_isolation = FALSE; +SELECT @@global.transaction_isolation; +@@global.transaction_isolation +READ-UNCOMMITTED +'#---------------------FN_DYNVARS_183_09----------------------#' +SET transaction_isolation = 'REPEATABLE-READ'; +SET session transaction_isolation = 'REPEATABLE-READ'; +SELECT @@transaction_isolation; +@@transaction_isolation +REPEATABLE-READ +SET global transaction_isolation = 'REPEATABLE-READ'; +SELECT @@global.transaction_isolation; +@@global.transaction_isolation +REPEATABLE-READ +SET @@global.transaction_isolation = @global_start_value; +SELECT @@global.transaction_isolation; +@@global.transaction_isolation +REPEATABLE-READ +SET @@session.transaction_isolation = @session_start_value; +SELECT @@session.transaction_isolation; +@@session.transaction_isolation +REPEATABLE-READ diff --git a/mysql-test/suite/sys_vars/r/tx_isolation_func.result b/mysql-test/suite/sys_vars/r/transaction_isolation_func.result index 3f6bd0b485b..b27050a0f50 100644 --- a/mysql-test/suite/sys_vars/r/tx_isolation_func.result +++ b/mysql-test/suite/sys_vars/r/transaction_isolation_func.result @@ -1,6 +1,6 @@ ** Setup ** -SET @session_tx_isolation = @@SESSION.tx_isolation; -SET @global_tx_isolation = @@GLOBAL.tx_isolation; +SET @session_transaction_isolation = @@SESSION.transaction_isolation; +SET @global_transaction_isolation = @@GLOBAL.transaction_isolation; connect con0,localhost,root,,; connection con0; SET SESSION AUTOCOMMIT = OFF; @@ -20,10 +20,10 @@ INSERT INTO t1 VALUES(22, 22); INSERT INTO t1 VALUES(24, 24); '#----------------------------FN_DYNVARS_184_01--------------------------------------#' connection con0; -SET SESSION tx_isolation = 'READ-UNCOMMITTED'; +SET SESSION transaction_isolation = 'READ-UNCOMMITTED'; set binlog_format=mixed; connection con1; -SET SESSION tx_isolation = 'READ-UNCOMMITTED'; +SET SESSION transaction_isolation = 'READ-UNCOMMITTED'; set binlog_format=mixed; connection con0; START TRANSACTION; @@ -114,9 +114,9 @@ connection con0; COMMIT; '#----------------------------FN_DYNVARS_184_03--------------------------------------#' connection con0; -SET SESSION tx_isolation = 'READ-COMMITTED'; +SET SESSION transaction_isolation = 'READ-COMMITTED'; connection con1; -SET SESSION tx_isolation = 'READ-COMMITTED'; +SET SESSION transaction_isolation = 'READ-COMMITTED'; connection con0; START TRANSACTION; SELECT * FROM t1 WHERE a % 2 = 0 FOR UPDATE; @@ -168,9 +168,9 @@ connection con0; COMMIT; '#----------------------------FN_DYNVARS_184_04--------------------------------------#' connection con0; -SET SESSION tx_isolation = 'REPEATABLE-READ'; +SET SESSION transaction_isolation = 'REPEATABLE-READ'; connection con1; -SET SESSION tx_isolation = 'REPEATABLE-READ'; +SET SESSION transaction_isolation = 'REPEATABLE-READ'; connection con0; START TRANSACTION; SELECT * FROM t1 WHERE a % 2 = 0 FOR UPDATE; @@ -332,9 +332,9 @@ connection con0; COMMIT; '#----------------------------FN_DYNVARS_184_07--------------------------------------#' connection con0; -SET SESSION tx_isolation = 'SERIALIZABLE'; +SET SESSION transaction_isolation = 'SERIALIZABLE'; connection con1; -SET SESSION tx_isolation = 'SERIALIZABLE'; +SET SESSION transaction_isolation = 'SERIALIZABLE'; connection con0; START TRANSACTION; SELECT * FROM t1 WHERE a % 2 = 0 FOR UPDATE; @@ -363,40 +363,40 @@ COMMIT; connection con0; COMMIT; '#----------------------------FN_DYNVARS_184_08--------------------------------------#' -SET GLOBAL tx_isolation = 'READ-UNCOMMITTED'; +SET GLOBAL transaction_isolation = 'READ-UNCOMMITTED'; connect con_int1,localhost,root,,; connection con_int1; -SELECT @@SESSION.tx_isolation; -@@SESSION.tx_isolation +SELECT @@SESSION.transaction_isolation; +@@SESSION.transaction_isolation READ-UNCOMMITTED READ-UNCOMMITTED Expected -SET SESSION tx_isolation = 'SERIALIZABLE'; +SET SESSION transaction_isolation = 'SERIALIZABLE'; connect con_int2,localhost,root,,; connection con_int2; -SELECT @@SESSION.tx_isolation; -@@SESSION.tx_isolation +SELECT @@SESSION.transaction_isolation; +@@SESSION.transaction_isolation READ-UNCOMMITTED READ-UNCOMMITTED Expected -SET SESSION tx_isolation = 'REPEATABLE-READ'; +SET SESSION transaction_isolation = 'REPEATABLE-READ'; connection con_int2; -SELECT @@SESSION.tx_isolation; -@@SESSION.tx_isolation +SELECT @@SESSION.transaction_isolation; +@@SESSION.transaction_isolation REPEATABLE-READ REPEATABLE-READ Expected connection con_int1; -SELECT @@SESSION.tx_isolation; -@@SESSION.tx_isolation +SELECT @@SESSION.transaction_isolation; +@@SESSION.transaction_isolation SERIALIZABLE SERIALIZABLE Expected -SELECT @@GLOBAL.tx_isolation; -@@GLOBAL.tx_isolation +SELECT @@GLOBAL.transaction_isolation; +@@GLOBAL.transaction_isolation READ-UNCOMMITTED READ-UNCOMMITTED Expected connection default; disconnect con_int1; disconnect con_int2; -SET @@SESSION.tx_isolation = @session_tx_isolation; -SET @@GLOBAL.tx_isolation = @global_tx_isolation; +SET @@SESSION.transaction_isolation = @session_transaction_isolation; +SET @@GLOBAL.transaction_isolation = @global_transaction_isolation; connection default; disconnect con0; disconnect con1; diff --git a/mysql-test/suite/sys_vars/r/transaction_read_only_basic.result b/mysql-test/suite/sys_vars/r/transaction_read_only_basic.result new file mode 100644 index 00000000000..b0d1d8bcab7 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/transaction_read_only_basic.result @@ -0,0 +1,181 @@ +#################################################################### +# START OF transaction_read_only TESTS # +#################################################################### +############################################################# +# Save initial value # +############################################################# +SET @start_global_value = @@global.transaction_read_only; +SELECT @start_global_value; +@start_global_value +0 +SET @start_session_value = @@session.transaction_read_only; +SELECT @start_session_value; +@start_session_value +0 +######################################################################## +# Display the DEFAULT value of transaction_read_only # +######################################################################## +SET @@global.transaction_read_only = ON; +SET @@global.transaction_read_only = DEFAULT; +SELECT @@global.transaction_read_only; +@@global.transaction_read_only +0 +SET @@session.transaction_read_only = ON; +SET @@session.transaction_read_only = DEFAULT; +SELECT @@session.transaction_read_only; +@@session.transaction_read_only +0 +############################################################################### +# Change the value of transaction_read_only to a valid value for GLOBAL Scope # +############################################################################### +SET @@global.transaction_read_only = ON; +SELECT @@global.transaction_read_only; +@@global.transaction_read_only +1 +SET @@global.transaction_read_only = OFF; +SELECT @@global.transaction_read_only; +@@global.transaction_read_only +0 +SET @@global.transaction_read_only = 0; +SELECT @@global.transaction_read_only; +@@global.transaction_read_only +0 +SET @@global.transaction_read_only = 1; +SELECT @@global.transaction_read_only; +@@global.transaction_read_only +1 +SET @@global.transaction_read_only = TRUE; +SELECT @@global.transaction_read_only; +@@global.transaction_read_only +1 +SET @@global.transaction_read_only = FALSE; +SELECT @@global.transaction_read_only; +@@global.transaction_read_only +0 +################################################################################ +# Change the value of transaction_read_only to a valid value for SESSION Scope # +################################################################################ +SET @@session.transaction_read_only = ON; +SELECT @@session.transaction_read_only; +@@session.transaction_read_only +1 +SET @@session.transaction_read_only = OFF; +SELECT @@session.transaction_read_only; +@@session.transaction_read_only +0 +SET @@session.transaction_read_only = 0; +SELECT @@session.transaction_read_only; +@@session.transaction_read_only +0 +SET @@session.transaction_read_only = 1; +SELECT @@session.transaction_read_only; +@@session.transaction_read_only +1 +SET @@session.transaction_read_only = TRUE; +SELECT @@session.transaction_read_only; +@@session.transaction_read_only +1 +SET @@session.transaction_read_only = FALSE; +SELECT @@session.transaction_read_only; +@@session.transaction_read_only +0 +################################################################# +# Change the value of transaction_read_only to an invalid value # +################################################################# +SET @@global.transaction_read_only = 'ONN'; +ERROR 42000: Variable 'transaction_read_only' can't be set to the value of 'ONN' +SET @@global.transaction_read_only = "OFFF"; +ERROR 42000: Variable 'transaction_read_only' can't be set to the value of 'OFFF' +SET @@global.transaction_read_only = TTRUE; +ERROR 42000: Variable 'transaction_read_only' can't be set to the value of 'TTRUE' +SET @@global.transaction_read_only = FELSE; +ERROR 42000: Variable 'transaction_read_only' can't be set to the value of 'FELSE' +SET @@global.transaction_read_only = -1024; +ERROR 42000: Variable 'transaction_read_only' can't be set to the value of '-1024' +SET @@global.transaction_read_only = 65536; +ERROR 42000: Variable 'transaction_read_only' can't be set to the value of '65536' +SET @@global.transaction_read_only = 65530.34; +ERROR 42000: Incorrect argument type to variable 'transaction_read_only' +SET @@global.transaction_read_only = test; +ERROR 42000: Variable 'transaction_read_only' can't be set to the value of 'test' +SET @@session.transaction_read_only = ONN; +ERROR 42000: Variable 'transaction_read_only' can't be set to the value of 'ONN' +SET @@session.transaction_read_only = ONF; +ERROR 42000: Variable 'transaction_read_only' can't be set to the value of 'ONF' +SET @@session.transaction_read_only = OF; +ERROR 42000: Variable 'transaction_read_only' can't be set to the value of 'OF' +SET @@session.transaction_read_only = 'OFN'; +ERROR 42000: Variable 'transaction_read_only' can't be set to the value of 'OFN' +SET @@session.transaction_read_only = -2; +ERROR 42000: Variable 'transaction_read_only' can't be set to the value of '-2' +SET @@session.transaction_read_only = 65530.34; +ERROR 42000: Incorrect argument type to variable 'transaction_read_only' +SET @@session.transaction_read_only = 65550; +ERROR 42000: Variable 'transaction_read_only' can't be set to the value of '65550' +SET @@session.transaction_read_only = test; +ERROR 42000: Variable 'transaction_read_only' can't be set to the value of 'test' +SELECT @@session.transaction_read_only; +@@session.transaction_read_only +0 +#################################################################### +# Check if the value in GLOBAL Table matches value in variable # +#################################################################### +SELECT IF(@@global.transaction_read_only, "ON", "OFF") = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='transaction_read_only'; +IF(@@global.transaction_read_only, "ON", "OFF") = VARIABLE_VALUE +1 +#################################################################### +# Check if the value in SESSION Table matches value in variable # +#################################################################### +SELECT IF(@@session.transaction_read_only, "ON", "OFF") = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.SESSION_VARIABLES +WHERE VARIABLE_NAME='transaction_read_only'; +IF(@@session.transaction_read_only, "ON", "OFF") = VARIABLE_VALUE +1 +############################################################################### +# Check if accessing variable with and without GLOBAL point to same variable # +############################################################################### +SET @@transaction_read_only = OFF; +SET @@global.transaction_read_only = ON; +SELECT @@transaction_read_only = @@global.transaction_read_only; +@@transaction_read_only = @@global.transaction_read_only +0 +############################################################################## +# Check if accessing variable with SESSION,LOCAL and without SCOPE points # +# to same session variable # +############################################################################## +SET @@transaction_read_only = ON; +SELECT @@transaction_read_only = @@local.transaction_read_only; +@@transaction_read_only = @@local.transaction_read_only +1 +SELECT @@local.transaction_read_only = @@session.transaction_read_only; +@@local.transaction_read_only = @@session.transaction_read_only +1 +############################################################################### +# Check if transaction_read_only can be accessed with and without @@ sign # +############################################################################### +# @@session is synonym for SESSION +SET @@session.transaction_read_only= 0; +# Without modifier, SET changes session variable +SET transaction_read_only = 1; +SELECT @@transaction_read_only; +@@transaction_read_only +1 +# name1.name2 refers to database_name.table_name +SELECT session.transaction_read_only; +ERROR 42S02: Unknown table 'session' in field list +#################################### +# Restore initial value # +#################################### +SET @@global.transaction_read_only = @start_global_value; +SELECT @@global.transaction_read_only; +@@global.transaction_read_only +0 +SET @@session.transaction_read_only = @start_session_value; +SELECT @@session.transaction_read_only; +@@session.transaction_read_only +0 +######################################################### +# END OF transaction_read_only TESTS # +######################################################### diff --git a/mysql-test/suite/sys_vars/r/tx_compatibility.result b/mysql-test/suite/sys_vars/r/tx_compatibility.result new file mode 100644 index 00000000000..4cf1cd61a09 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/tx_compatibility.result @@ -0,0 +1,139 @@ +# +# MDEV-21921 Make transaction_isolation and transaction_read_only into +# system variables +# +SET @saved_global_isolation= @@global.transaction_isolation; +SET @saved_global_read_only= @@global.transaction_read_only; +# Case 1: Check the influence of --transaction_* on +# @@session.transaction_* and @@global.transaction_*, +# @@session.tx_*, @@global.tx_*. +SELECT @@session.transaction_isolation, @@global.transaction_isolation, +@@session.tx_isolation, @@global.tx_isolation; +@@session.transaction_isolation @@global.transaction_isolation @@session.tx_isolation @@global.tx_isolation +SERIALIZABLE SERIALIZABLE SERIALIZABLE SERIALIZABLE +SHOW GLOBAL VARIABLES LIKE '%_isolation'; +Variable_name Value +transaction_isolation SERIALIZABLE +tx_isolation SERIALIZABLE +SHOW SESSION VARIABLES LIKE '%_isolation'; +Variable_name Value +transaction_isolation SERIALIZABLE +tx_isolation SERIALIZABLE +SELECT @@session.transaction_read_only, @@global.transaction_read_only, +@@session.tx_read_only, @@global.tx_read_only; +@@session.transaction_read_only @@global.transaction_read_only @@session.tx_read_only @@global.tx_read_only +1 1 1 1 +SHOW GLOBAL VARIABLES LIKE '%_read_only'; +Variable_name Value +transaction_read_only ON +tx_read_only ON +SHOW SESSION VARIABLES LIKE '%_read_only'; +Variable_name Value +transaction_read_only ON +tx_read_only ON +# Case 2: Check that the change to tx_* is reflected to transaction_*. +SET tx_isolation= 'REPEATABLE-READ'; +Warnings: +Warning 1287 '@@tx_isolation' is deprecated and will be removed in a future release. Please use '@@transaction_isolation' instead +SET @@global.tx_isolation= 'SERIALIZABLE'; +Warnings: +Warning 1287 '@@tx_isolation' is deprecated and will be removed in a future release. Please use '@@transaction_isolation' instead +SELECT @@session.tx_isolation, @@global.tx_isolation, +@@session.transaction_isolation, @@global.transaction_isolation; +@@session.tx_isolation @@global.tx_isolation @@session.transaction_isolation @@global.transaction_isolation +REPEATABLE-READ SERIALIZABLE REPEATABLE-READ SERIALIZABLE +SHOW GLOBAL VARIABLES LIKE '%_isolation'; +Variable_name Value +transaction_isolation SERIALIZABLE +tx_isolation SERIALIZABLE +SHOW SESSION VARIABLES LIKE '%_isolation'; +Variable_name Value +transaction_isolation REPEATABLE-READ +tx_isolation REPEATABLE-READ +SET STATEMENT tx_isolation= 'SERIALIZABLE' FOR SHOW SESSION VARIABLES LIKE '%_isolation'; +Variable_name Value +transaction_isolation SERIALIZABLE +tx_isolation SERIALIZABLE +Warnings: +Warning 1287 '@@tx_isolation' is deprecated and will be removed in a future release. Please use '@@transaction_isolation' instead +Warning 1287 '@@tx_isolation' is deprecated and will be removed in a future release. Please use '@@transaction_isolation' instead +SHOW SESSION VARIABLES LIKE '%_isolation'; +Variable_name Value +transaction_isolation REPEATABLE-READ +tx_isolation REPEATABLE-READ +SET tx_read_only= OFF; +Warnings: +Warning 1287 '@@tx_read_only' is deprecated and will be removed in a future release. Please use '@@transaction_read_only' instead +SET @@global.tx_read_only= ON; +Warnings: +Warning 1287 '@@tx_read_only' is deprecated and will be removed in a future release. Please use '@@transaction_read_only' instead +SELECT @@session.tx_read_only, @@global.tx_read_only, +@@session.transaction_read_only, @@global.transaction_read_only; +@@session.tx_read_only @@global.tx_read_only @@session.transaction_read_only @@global.transaction_read_only +0 1 0 1 +SHOW GLOBAL VARIABLES LIKE '%_read_only'; +Variable_name Value +transaction_read_only ON +tx_read_only ON +SHOW SESSION VARIABLES LIKE '%_read_only'; +Variable_name Value +transaction_read_only OFF +tx_read_only OFF +SET STATEMENT tx_read_only= ON FOR SHOW SESSION VARIABLES LIKE '%_read_only'; +Variable_name Value +transaction_read_only ON +tx_read_only ON +Warnings: +Warning 1287 '@@tx_read_only' is deprecated and will be removed in a future release. Please use '@@transaction_read_only' instead +Warning 1287 '@@tx_read_only' is deprecated and will be removed in a future release. Please use '@@transaction_read_only' instead +SHOW SESSION VARIABLES LIKE '%_read_only'; +Variable_name Value +transaction_read_only OFF +tx_read_only OFF +# Case 3: Check that the change to transaction_* is reflected to tx_*. +SET transaction_isolation= 'SERIALIZABLE'; +SET @@global.transaction_isolation= 'REPEATABLE-READ'; +SELECT @@session.tx_isolation, @@global.tx_isolation, +@@session.transaction_isolation, @@global.transaction_isolation; +@@session.tx_isolation @@global.tx_isolation @@session.transaction_isolation @@global.transaction_isolation +SERIALIZABLE REPEATABLE-READ SERIALIZABLE REPEATABLE-READ +SHOW GLOBAL VARIABLES LIKE '%_isolation'; +Variable_name Value +transaction_isolation REPEATABLE-READ +tx_isolation REPEATABLE-READ +SHOW SESSION VARIABLES LIKE '%_isolation'; +Variable_name Value +transaction_isolation SERIALIZABLE +tx_isolation SERIALIZABLE +SET STATEMENT transaction_isolation= 'REPEATABLE-READ' FOR SHOW SESSION VARIABLES LIKE '%_isolation'; +Variable_name Value +transaction_isolation REPEATABLE-READ +tx_isolation REPEATABLE-READ +SHOW SESSION VARIABLES LIKE '%_isolation'; +Variable_name Value +transaction_isolation SERIALIZABLE +tx_isolation SERIALIZABLE +SET transaction_read_only= ON; +SET @@global.transaction_read_only= OFF; +SELECT @@session.tx_read_only, @@global.tx_read_only, +@@session.transaction_read_only, @@global.transaction_read_only; +@@session.tx_read_only @@global.tx_read_only @@session.transaction_read_only @@global.transaction_read_only +1 0 1 0 +SHOW GLOBAL VARIABLES LIKE '%_read_only'; +Variable_name Value +transaction_read_only OFF +tx_read_only OFF +SHOW SESSION VARIABLES LIKE '%_read_only'; +Variable_name Value +transaction_read_only ON +tx_read_only ON +SET STATEMENT transaction_read_only= OFF FOR SHOW SESSION VARIABLES LIKE '%_read_only'; +Variable_name Value +transaction_read_only OFF +tx_read_only OFF +SHOW SESSION VARIABLES LIKE '%_read_only'; +Variable_name Value +transaction_read_only ON +tx_read_only ON +SET @@global.transaction_isolation= @saved_global_isolation; +SET @@global.transaction_read_only= @saved_global_read_only; diff --git a/mysql-test/suite/sys_vars/r/tx_isolation_basic.result b/mysql-test/suite/sys_vars/r/tx_isolation_basic.result deleted file mode 100644 index f6ee2c92fa5..00000000000 --- a/mysql-test/suite/sys_vars/r/tx_isolation_basic.result +++ /dev/null @@ -1,141 +0,0 @@ -SET @global_start_value = @@global.tx_isolation; -SELECT @global_start_value; -@global_start_value -REPEATABLE-READ -SET @session_start_value = @@session.tx_isolation; -SELECT @session_start_value; -@session_start_value -REPEATABLE-READ -'#--------------------FN_DYNVARS_183_01------------------------#' -SET @@global.tx_isolation = 'READ-UNCOMMITTED'; -SET @@global.tx_isolation = DEFAULT; -SELECT @@global.tx_isolation; -@@global.tx_isolation -REPEATABLE-READ -SET @@session.tx_isolation = DEFAULT; -SELECT @@session.tx_isolation; -@@session.tx_isolation -REPEATABLE-READ -'#---------------------FN_DYNVARS_183_02-------------------------#' -SET @@global.tx_isolation = NULL; -ERROR 42000: Variable 'tx_isolation' can't be set to the value of 'NULL' -SET @@global.tx_isolation = ''; -ERROR 42000: Variable 'tx_isolation' can't be set to the value of '' -SET @@session.tx_isolation = NULL; -ERROR 42000: Variable 'tx_isolation' can't be set to the value of 'NULL' -SET @@session.tx_isolation = ''; -ERROR 42000: Variable 'tx_isolation' can't be set to the value of '' -'#--------------------FN_DYNVARS_183_03------------------------#' -SET @@global.tx_isolation = 'READ-UNCOMMITTED'; -SELECT @@global.tx_isolation; -@@global.tx_isolation -READ-UNCOMMITTED -SET @@global.tx_isolation = 'read-COMMITTED'; -SELECT @@global.tx_isolation; -@@global.tx_isolation -READ-COMMITTED -SET @@global.tx_isolation = 'REPEATABLE-READ'; -SELECT @@global.tx_isolation; -@@global.tx_isolation -REPEATABLE-READ -SET @@global.tx_isolation = 'SERIALIZable'; -SELECT @@global.tx_isolation; -@@global.tx_isolation -SERIALIZABLE -SET @@session.tx_isolation = 'READ-UNCOMMITTED'; -SELECT @@session.tx_isolation; -@@session.tx_isolation -READ-UNCOMMITTED -SET @@session.tx_isolation = 'READ-COMMITTED'; -SELECT @@session.tx_isolation; -@@session.tx_isolation -READ-COMMITTED -SET @@session.tx_isolation = 'REPEATABLE-READ'; -SELECT @@session.tx_isolation; -@@session.tx_isolation -REPEATABLE-READ -SET @@session.tx_isolation = 'serializable'; -SELECT @@session.tx_isolation; -@@session.tx_isolation -SERIALIZABLE -'#--------------------FN_DYNVARS_183_04-------------------------#' -SET @@global.tx_isolation = -1; -ERROR 42000: Variable 'tx_isolation' can't be set to the value of '-1' -SET @@global.tx_isolation = READUNCOMMITTED; -ERROR 42000: Variable 'tx_isolation' can't be set to the value of 'READUNCOMMITTED' -SET @@global.tx_isolation = 'REPEATABLE'; -ERROR 42000: Variable 'tx_isolation' can't be set to the value of 'REPEATABLE' -SET @@global.tx_isolation = OFF; -ERROR 42000: Variable 'tx_isolation' can't be set to the value of 'OFF' -SET @@global.tx_isolation = ON; -ERROR 42000: Variable 'tx_isolation' can't be set to the value of 'ON' -SET @@global.tx_isolation = 'NON-SERIALIZABLE'; -ERROR 42000: Variable 'tx_isolation' can't be set to the value of 'NON-SERIALIZABLE' -SET @@tx_isolation = -1; -ERROR 42000: Variable 'tx_isolation' can't be set to the value of '-1' -SET @@tx_isolation = READUNCOMMITTED; -ERROR 42000: Variable 'tx_isolation' can't be set to the value of 'READUNCOMMITTED' -SET @@tx_isolation = 'REPEATABLE'; -ERROR 42000: Variable 'tx_isolation' can't be set to the value of 'REPEATABLE' -SET @@tx_isolation = 'NONE'; -ERROR 42000: Variable 'tx_isolation' can't be set to the value of 'NONE' -SET @@tx_isolation = 'ALL'; -ERROR 42000: Variable 'tx_isolation' can't be set to the value of 'ALL' -'#-------------------FN_DYNVARS_183_05----------------------------#' -SELECT @@session.tx_isolation = VARIABLE_VALUE -FROM INFORMATION_SCHEMA.SESSION_VARIABLES -WHERE VARIABLE_NAME='tx_isolation'; -@@session.tx_isolation = VARIABLE_VALUE -1 -'#----------------------FN_DYNVARS_183_06------------------------#' -SELECT @@global.tx_isolation = VARIABLE_VALUE -FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES -WHERE VARIABLE_NAME='tx_isolation'; -@@global.tx_isolation = VARIABLE_VALUE -1 -'#---------------------FN_DYNVARS_183_07-------------------------#' -SET @@global.tx_isolation = 0; -SELECT @@global.tx_isolation; -@@global.tx_isolation -READ-UNCOMMITTED -SET @@global.tx_isolation = 1; -SELECT @@global.tx_isolation; -@@global.tx_isolation -READ-COMMITTED -SET @@global.tx_isolation = 2; -SELECT @@global.tx_isolation; -@@global.tx_isolation -REPEATABLE-READ -SET @@global.tx_isolation = 3; -SELECT @@global.tx_isolation; -@@global.tx_isolation -SERIALIZABLE -SET @@global.tx_isolation = 0.4; -ERROR 42000: Incorrect argument type to variable 'tx_isolation' -'#---------------------FN_DYNVARS_183_08----------------------#' -SET @@global.tx_isolation = TRUE; -SELECT @@global.tx_isolation; -@@global.tx_isolation -READ-COMMITTED -SET @@global.tx_isolation = FALSE; -SELECT @@global.tx_isolation; -@@global.tx_isolation -READ-UNCOMMITTED -'#---------------------FN_DYNVARS_183_09----------------------#' -SET tx_isolation = 'REPEATABLE-READ'; -SET session tx_isolation = 'REPEATABLE-READ'; -SELECT @@tx_isolation; -@@tx_isolation -REPEATABLE-READ -SET global tx_isolation = 'REPEATABLE-READ'; -SELECT @@global.tx_isolation; -@@global.tx_isolation -REPEATABLE-READ -SET @@global.tx_isolation = @global_start_value; -SELECT @@global.tx_isolation; -@@global.tx_isolation -REPEATABLE-READ -SET @@session.tx_isolation = @session_start_value; -SELECT @@session.tx_isolation; -@@session.tx_isolation -REPEATABLE-READ diff --git a/mysql-test/suite/sys_vars/r/tx_read_only_basic.result b/mysql-test/suite/sys_vars/r/tx_read_only_basic.result deleted file mode 100644 index 3750145083f..00000000000 --- a/mysql-test/suite/sys_vars/r/tx_read_only_basic.result +++ /dev/null @@ -1,181 +0,0 @@ -#################################################################### -# START OF tx_read_only TESTS # -#################################################################### -############################################################# -# Save initial value # -############################################################# -SET @start_global_value = @@global.tx_read_only; -SELECT @start_global_value; -@start_global_value -0 -SET @start_session_value = @@session.tx_read_only; -SELECT @start_session_value; -@start_session_value -0 -######################################################################## -# Display the DEFAULT value of tx_read_only # -######################################################################## -SET @@global.tx_read_only = ON; -SET @@global.tx_read_only = DEFAULT; -SELECT @@global.tx_read_only; -@@global.tx_read_only -0 -SET @@session.tx_read_only = ON; -SET @@session.tx_read_only = DEFAULT; -SELECT @@session.tx_read_only; -@@session.tx_read_only -0 -############################################################################## -# Change the value of tx_read_only to a valid value for GLOBAL Scope # -############################################################################## -SET @@global.tx_read_only = ON; -SELECT @@global.tx_read_only; -@@global.tx_read_only -1 -SET @@global.tx_read_only = OFF; -SELECT @@global.tx_read_only; -@@global.tx_read_only -0 -SET @@global.tx_read_only = 0; -SELECT @@global.tx_read_only; -@@global.tx_read_only -0 -SET @@global.tx_read_only = 1; -SELECT @@global.tx_read_only; -@@global.tx_read_only -1 -SET @@global.tx_read_only = TRUE; -SELECT @@global.tx_read_only; -@@global.tx_read_only -1 -SET @@global.tx_read_only = FALSE; -SELECT @@global.tx_read_only; -@@global.tx_read_only -0 -############################################################################### -# Change the value of tx_read_only to a valid value for SESSION Scope # -############################################################################### -SET @@session.tx_read_only = ON; -SELECT @@session.tx_read_only; -@@session.tx_read_only -1 -SET @@session.tx_read_only = OFF; -SELECT @@session.tx_read_only; -@@session.tx_read_only -0 -SET @@session.tx_read_only = 0; -SELECT @@session.tx_read_only; -@@session.tx_read_only -0 -SET @@session.tx_read_only = 1; -SELECT @@session.tx_read_only; -@@session.tx_read_only -1 -SET @@session.tx_read_only = TRUE; -SELECT @@session.tx_read_only; -@@session.tx_read_only -1 -SET @@session.tx_read_only = FALSE; -SELECT @@session.tx_read_only; -@@session.tx_read_only -0 -################################################################ -# Change the value of tx_read_only to an invalid value # -################################################################ -SET @@global.tx_read_only = 'ONN'; -ERROR 42000: Variable 'tx_read_only' can't be set to the value of 'ONN' -SET @@global.tx_read_only = "OFFF"; -ERROR 42000: Variable 'tx_read_only' can't be set to the value of 'OFFF' -SET @@global.tx_read_only = TTRUE; -ERROR 42000: Variable 'tx_read_only' can't be set to the value of 'TTRUE' -SET @@global.tx_read_only = FELSE; -ERROR 42000: Variable 'tx_read_only' can't be set to the value of 'FELSE' -SET @@global.tx_read_only = -1024; -ERROR 42000: Variable 'tx_read_only' can't be set to the value of '-1024' -SET @@global.tx_read_only = 65536; -ERROR 42000: Variable 'tx_read_only' can't be set to the value of '65536' -SET @@global.tx_read_only = 65530.34; -ERROR 42000: Incorrect argument type to variable 'tx_read_only' -SET @@global.tx_read_only = test; -ERROR 42000: Variable 'tx_read_only' can't be set to the value of 'test' -SET @@session.tx_read_only = ONN; -ERROR 42000: Variable 'tx_read_only' can't be set to the value of 'ONN' -SET @@session.tx_read_only = ONF; -ERROR 42000: Variable 'tx_read_only' can't be set to the value of 'ONF' -SET @@session.tx_read_only = OF; -ERROR 42000: Variable 'tx_read_only' can't be set to the value of 'OF' -SET @@session.tx_read_only = 'OFN'; -ERROR 42000: Variable 'tx_read_only' can't be set to the value of 'OFN' -SET @@session.tx_read_only = -2; -ERROR 42000: Variable 'tx_read_only' can't be set to the value of '-2' -SET @@session.tx_read_only = 65530.34; -ERROR 42000: Incorrect argument type to variable 'tx_read_only' -SET @@session.tx_read_only = 65550; -ERROR 42000: Variable 'tx_read_only' can't be set to the value of '65550' -SET @@session.tx_read_only = test; -ERROR 42000: Variable 'tx_read_only' can't be set to the value of 'test' -SELECT @@session.tx_read_only; -@@session.tx_read_only -0 -#################################################################### -# Check if the value in GLOBAL Table matches value in variable # -#################################################################### -SELECT IF(@@global.tx_read_only, "ON", "OFF") = VARIABLE_VALUE -FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES -WHERE VARIABLE_NAME='tx_read_only'; -IF(@@global.tx_read_only, "ON", "OFF") = VARIABLE_VALUE -1 -#################################################################### -# Check if the value in SESSION Table matches value in variable # -#################################################################### -SELECT IF(@@session.tx_read_only, "ON", "OFF") = VARIABLE_VALUE -FROM INFORMATION_SCHEMA.SESSION_VARIABLES -WHERE VARIABLE_NAME='tx_read_only'; -IF(@@session.tx_read_only, "ON", "OFF") = VARIABLE_VALUE -1 -############################################################################### -# Check if accessing variable with and without GLOBAL point to same variable # -############################################################################### -SET @@tx_read_only = OFF; -SET @@global.tx_read_only = ON; -SELECT @@tx_read_only = @@global.tx_read_only; -@@tx_read_only = @@global.tx_read_only -0 -############################################################################## -# Check if accessing variable with SESSION,LOCAL and without SCOPE points # -# to same session variable # -############################################################################## -SET @@tx_read_only = ON; -SELECT @@tx_read_only = @@local.tx_read_only; -@@tx_read_only = @@local.tx_read_only -1 -SELECT @@local.tx_read_only = @@session.tx_read_only; -@@local.tx_read_only = @@session.tx_read_only -1 -############################################################################### -# Check if tx_read_only can be accessed with and without @@ sign # -############################################################################### -# @@session is synonym for SESSION -SET @@session.tx_read_only= 0; -# Without modifier, SET changes session variable -SET tx_read_only = 1; -SELECT @@tx_read_only; -@@tx_read_only -1 -# name1.name2 refers to database_name.table_name -SELECT session.tx_read_only; -ERROR 42S02: Unknown table 'session' in field list -#################################### -# Restore initial value # -#################################### -SET @@global.tx_read_only = @start_global_value; -SELECT @@global.tx_read_only; -@@global.tx_read_only -0 -SET @@session.tx_read_only = @start_session_value; -SELECT @@session.tx_read_only; -@@session.tx_read_only -0 -######################################################### -# END OF tx_read_only TESTS # -######################################################### diff --git a/mysql-test/suite/sys_vars/t/innodb_defragment_basic.test b/mysql-test/suite/sys_vars/t/innodb_defragment_basic.test deleted file mode 100644 index 9667f63f687..00000000000 --- a/mysql-test/suite/sys_vars/t/innodb_defragment_basic.test +++ /dev/null @@ -1,20 +0,0 @@ --- source include/have_innodb.inc - -# Check the default value -SET @orig = @@global.innodb_defragment; -SELECT @orig; - -# Turn off -SET GLOBAL innodb_defragment = OFF; -SELECT @@global.innodb_defragment; - -# Turn on -SET GLOBAL innodb_defragment = ON; -SELECT @@global.innodb_defragment; - -# Wrong value ---error ER_WRONG_VALUE_FOR_VAR -SET GLOBAL innodb_defragment = 100; -SELECT @@global.innodb_defragment; - -SET GLOBAL innodb_defragment = @orig; diff --git a/mysql-test/suite/sys_vars/t/innodb_defragment_fill_factor_basic.test b/mysql-test/suite/sys_vars/t/innodb_defragment_fill_factor_basic.test deleted file mode 100644 index ae9863e806a..00000000000 --- a/mysql-test/suite/sys_vars/t/innodb_defragment_fill_factor_basic.test +++ /dev/null @@ -1,27 +0,0 @@ ---source include/have_innodb.inc - -SET @start_innodb_defragment_fill_factor = @@global.innodb_defragment_fill_factor; -SELECT @start_innodb_defragment_fill_factor; - -SELECT COUNT(@@global.innodb_defragment_fill_factor); - -SET @@global.innodb_defragment_fill_factor = 0.77777777777777; -SELECT @@global.innodb_defragment_fill_factor; - -SET @@global.innodb_defragment_fill_factor = 1; -SELECT @@global.innodb_defragment_fill_factor; - -SET @@global.innodb_defragment_fill_factor = 0.7; -SELECT @@global.innodb_defragment_fill_factor; - -SET @@global.innodb_defragment_fill_factor = -1; -SELECT @@global.innodb_defragment_fill_factor; - -SET @@global.innodb_defragment_fill_factor = 2; -SELECT @@global.innodb_defragment_fill_factor; - ---Error ER_WRONG_TYPE_FOR_VAR -SET @@global.innodb_defragment_fill_factor = "abc"; -SELECT @@global.innodb_defragment_fill_factor; - -SET @@global.innodb_defragment_fill_factor = @start_innodb_defragment_fill_factor; diff --git a/mysql-test/suite/sys_vars/t/innodb_defragment_fill_factor_n_recs_basic.test b/mysql-test/suite/sys_vars/t/innodb_defragment_fill_factor_n_recs_basic.test deleted file mode 100644 index 366817c4bbc..00000000000 --- a/mysql-test/suite/sys_vars/t/innodb_defragment_fill_factor_n_recs_basic.test +++ /dev/null @@ -1,31 +0,0 @@ ---source include/have_innodb.inc - -SET @start_innodb_defragment_fill_factor_n_recs = @@global.innodb_defragment_fill_factor_n_recs; -SELECT @start_innodb_defragment_fill_factor_n_recs; - -SELECT COUNT(@@global.innodb_defragment_fill_factor_n_recs); - -SET @@global.innodb_defragment_fill_factor_n_recs = 50; -SELECT @@global.innodb_defragment_fill_factor_n_recs; - -SET @@global.innodb_defragment_fill_factor_n_recs = 100; -SELECT @@global.innodb_defragment_fill_factor_n_recs; - -SET @@global.innodb_defragment_fill_factor_n_recs = 1; -SELECT @@global.innodb_defragment_fill_factor_n_recs; - -SET @@global.innodb_defragment_fill_factor_n_recs = -1; -SELECT @@global.innodb_defragment_fill_factor_n_recs; - -SET @@global.innodb_defragment_fill_factor_n_recs = 10000; -SELECT @@global.innodb_defragment_fill_factor_n_recs; - ---Error ER_WRONG_TYPE_FOR_VAR -SET @@global.innodb_defragment_fill_factor_n_recs = 10.5; -SELECT @@global.innodb_defragment_fill_factor_n_recs; - ---Error ER_WRONG_TYPE_FOR_VAR -SET @@global.innodb_defragment_fill_factor_n_recs = "abc"; -SELECT @@global.innodb_defragment_fill_factor_n_recs; - -SET @@global.innodb_defragment_fill_factor_n_recs = @start_innodb_defragment_fill_factor_n_recs; diff --git a/mysql-test/suite/sys_vars/t/innodb_defragment_frequency_basic.test b/mysql-test/suite/sys_vars/t/innodb_defragment_frequency_basic.test deleted file mode 100644 index 3ab45744a9c..00000000000 --- a/mysql-test/suite/sys_vars/t/innodb_defragment_frequency_basic.test +++ /dev/null @@ -1,37 +0,0 @@ ---source include/have_innodb.inc - -SET @start_innodb_defragment_frequency = @@global.innodb_defragment_frequency; -SELECT @start_innodb_defragment_frequency; - -SELECT COUNT(@@global.innodb_defragment_frequency); - -# test valid value -SET @@global.innodb_defragment_frequency = 200; -SELECT @@global.innodb_defragment_frequency; - -# test valid min -SET @@global.innodb_defragment_frequency = 1; -SELECT @@global.innodb_defragment_frequency; - -# test valid max -SET @@global.innodb_defragment_frequency = 1000; -SELECT @@global.innodb_defragment_frequency; - -# test invalid value < min -SET @@global.innodb_defragment_frequency = -1; -SELECT @@global.innodb_defragment_frequency; - -# test invalid value > max -SET @@global.innodb_defragment_frequency = 10000; -SELECT @@global.innodb_defragment_frequency; - -# test wrong type ---Error ER_WRONG_TYPE_FOR_VAR -SET @@global.innodb_defragment_frequency = 10.5; -SELECT @@global.innodb_defragment_frequency; - ---Error ER_WRONG_TYPE_FOR_VAR -SET @@global.innodb_defragment_frequency = "abc"; -SELECT @@global.innodb_defragment_frequency; - -SET @@global.innodb_defragment_frequency = @start_innodb_defragment_frequency; diff --git a/mysql-test/suite/sys_vars/t/innodb_defragment_n_pages_basic.test b/mysql-test/suite/sys_vars/t/innodb_defragment_n_pages_basic.test deleted file mode 100644 index 64aa20a615f..00000000000 --- a/mysql-test/suite/sys_vars/t/innodb_defragment_n_pages_basic.test +++ /dev/null @@ -1,22 +0,0 @@ ---source include/have_innodb.inc - -SET @start_innodb_defragment_n_pages = @@global.innodb_defragment_n_pages; -SELECT @start_innodb_defragment_n_pages; - -SELECT COUNT(@@global.innodb_defragment_n_pages); - -SET @@global.innodb_defragment_n_pages = 1; -SELECT @@global.innodb_defragment_n_pages; - -SET @@global.innodb_defragment_n_pages = 2; -SELECT @@global.innodb_defragment_n_pages; - -SET @@global.innodb_defragment_n_pages = 32; -SELECT @@global.innodb_defragment_n_pages; - -SET @@global.innodb_defragment_n_pages = 64; -SELECT @@global.innodb_defragment_n_pages; - -SET @@global.innodb_defragment_n_pages = @start_innodb_defragment_n_pages; - - diff --git a/mysql-test/suite/sys_vars/t/innodb_defragment_stats_accuracy_basic.test b/mysql-test/suite/sys_vars/t/innodb_defragment_stats_accuracy_basic.test deleted file mode 100644 index 062753f27ea..00000000000 --- a/mysql-test/suite/sys_vars/t/innodb_defragment_stats_accuracy_basic.test +++ /dev/null @@ -1,24 +0,0 @@ ---source include/have_innodb.inc - -SET @start_innodb_defragment_stats_accuracy = @@global.innodb_defragment_stats_accuracy; -SELECT @start_innodb_defragment_stats_accuracy; - -SELECT COUNT(@@global.innodb_defragment_stats_accuracy); - -SET @@global.innodb_defragment_stats_accuracy = 1; -SELECT @@global.innodb_defragment_stats_accuracy; - -SET @@global.innodb_defragment_stats_accuracy = 1000; -SELECT @@global.innodb_defragment_stats_accuracy; - -SET @@global.innodb_defragment_stats_accuracy = -1; -SELECT @@global.innodb_defragment_stats_accuracy; - -SET @@global.innodb_defragment_stats_accuracy = 1000000000000; -SELECT @@global.innodb_defragment_stats_accuracy; - ---Error ER_WRONG_TYPE_FOR_VAR -SET @@global.innodb_defragment_stats_accuracy = "abc"; -SELECT @@global.innodb_defragment_stats_accuracy; - -SET @@global.innodb_defragment_stats_accuracy = @start_innodb_defragment_stats_accuracy; diff --git a/mysql-test/suite/sys_vars/t/tx_isolation_basic.test b/mysql-test/suite/sys_vars/t/transaction_isolation_basic.test index 5b484cb9b1b..3f0e836141e 100644 --- a/mysql-test/suite/sys_vars/t/tx_isolation_basic.test +++ b/mysql-test/suite/sys_vars/t/transaction_isolation_basic.test @@ -1,6 +1,6 @@ -################# mysql-test\t\tx_isolation_basic.test ######################## +######## mysql-test\suite\sys_vars\t\transaction_isolation_basic.test ######### # # -# Variable Name: tx_isolation # +# Variable Name: transaction_isolation # # Scope: GLOBAL | SESSION # # Access Type: Dynamic # # Data Type: enumeration # @@ -11,7 +11,7 @@ # Creation Date: 2008-02-07 # # Author: Rizwan # # # -# Description: Test Cases of Dynamic System Variable tx_isolation # +# Description: Test Cases of Dynamic System Variable transaction_isolation # # that checks the behavior of this variable in the following ways# # * Default Value # # * Valid & Invalid values # @@ -26,31 +26,31 @@ --source include/load_sysvars.inc ######################################################################## -# START OF tx_isolation TESTS # +# START OF transaction_isolation TESTS # ######################################################################## ######################################################################### -# Saving initial value of tx_isolation in a temporary variable # +# Saving initial value of transaction_isolation in a temporary variable # ######################################################################### -SET @global_start_value = @@global.tx_isolation; +SET @global_start_value = @@global.transaction_isolation; SELECT @global_start_value; -SET @session_start_value = @@session.tx_isolation; +SET @session_start_value = @@session.transaction_isolation; SELECT @session_start_value; --echo '#--------------------FN_DYNVARS_183_01------------------------#' #################################################################### -# Display the DEFAULT value of tx_isolation # +# Display the DEFAULT value of transaction_isolation # #################################################################### -SET @@global.tx_isolation = 'READ-UNCOMMITTED'; -SET @@global.tx_isolation = DEFAULT; -SELECT @@global.tx_isolation; +SET @@global.transaction_isolation = 'READ-UNCOMMITTED'; +SET @@global.transaction_isolation = DEFAULT; +SELECT @@global.transaction_isolation; -SET @@session.tx_isolation = DEFAULT; -SELECT @@session.tx_isolation; +SET @@session.transaction_isolation = DEFAULT; +SELECT @@session.transaction_isolation; --echo '#---------------------FN_DYNVARS_183_02-------------------------#' ######################################################### @@ -58,97 +58,97 @@ SELECT @@session.tx_isolation; ######################################################### --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.tx_isolation = NULL; +SET @@global.transaction_isolation = NULL; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.tx_isolation = ''; +SET @@global.transaction_isolation = ''; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.tx_isolation = NULL; +SET @@session.transaction_isolation = NULL; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.tx_isolation = ''; +SET @@session.transaction_isolation = ''; --echo '#--------------------FN_DYNVARS_183_03------------------------#' ##################################################################### -# Change the value of tx_isolation to a valid value # +# Change the value of transaction_isolation to a valid value # ##################################################################### -SET @@global.tx_isolation = 'READ-UNCOMMITTED'; -SELECT @@global.tx_isolation; +SET @@global.transaction_isolation = 'READ-UNCOMMITTED'; +SELECT @@global.transaction_isolation; -SET @@global.tx_isolation = 'read-COMMITTED'; -SELECT @@global.tx_isolation; +SET @@global.transaction_isolation = 'read-COMMITTED'; +SELECT @@global.transaction_isolation; -SET @@global.tx_isolation = 'REPEATABLE-READ'; -SELECT @@global.tx_isolation; +SET @@global.transaction_isolation = 'REPEATABLE-READ'; +SELECT @@global.transaction_isolation; -SET @@global.tx_isolation = 'SERIALIZable'; -SELECT @@global.tx_isolation; +SET @@global.transaction_isolation = 'SERIALIZable'; +SELECT @@global.transaction_isolation; -SET @@session.tx_isolation = 'READ-UNCOMMITTED'; -SELECT @@session.tx_isolation; +SET @@session.transaction_isolation = 'READ-UNCOMMITTED'; +SELECT @@session.transaction_isolation; -SET @@session.tx_isolation = 'READ-COMMITTED'; -SELECT @@session.tx_isolation; +SET @@session.transaction_isolation = 'READ-COMMITTED'; +SELECT @@session.transaction_isolation; -SET @@session.tx_isolation = 'REPEATABLE-READ'; -SELECT @@session.tx_isolation; +SET @@session.transaction_isolation = 'REPEATABLE-READ'; +SELECT @@session.transaction_isolation; -SET @@session.tx_isolation = 'serializable'; -SELECT @@session.tx_isolation; +SET @@session.transaction_isolation = 'serializable'; +SELECT @@session.transaction_isolation; --echo '#--------------------FN_DYNVARS_183_04-------------------------#' ####################################################################### -# Change the value of tx_isolation to invalid value # +# Change the value of transaction_isolation to invalid value # ####################################################################### # for global scope --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.tx_isolation = -1; +SET @@global.transaction_isolation = -1; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.tx_isolation = READUNCOMMITTED; +SET @@global.transaction_isolation = READUNCOMMITTED; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.tx_isolation = 'REPEATABLE'; +SET @@global.transaction_isolation = 'REPEATABLE'; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.tx_isolation = OFF; +SET @@global.transaction_isolation = OFF; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.tx_isolation = ON; +SET @@global.transaction_isolation = ON; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.tx_isolation = 'NON-SERIALIZABLE'; +SET @@global.transaction_isolation = 'NON-SERIALIZABLE'; # for session scope --Error ER_WRONG_VALUE_FOR_VAR -SET @@tx_isolation = -1; +SET @@transaction_isolation = -1; --Error ER_WRONG_VALUE_FOR_VAR -SET @@tx_isolation = READUNCOMMITTED; +SET @@transaction_isolation = READUNCOMMITTED; --Error ER_WRONG_VALUE_FOR_VAR -SET @@tx_isolation = 'REPEATABLE'; +SET @@transaction_isolation = 'REPEATABLE'; --Error ER_WRONG_VALUE_FOR_VAR -SET @@tx_isolation = 'NONE'; +SET @@transaction_isolation = 'NONE'; --Error ER_WRONG_VALUE_FOR_VAR -SET @@tx_isolation = 'ALL'; +SET @@transaction_isolation = 'ALL'; --echo '#-------------------FN_DYNVARS_183_05----------------------------#' ######################################################################### # Check if the value in session Table matches value in variable # ######################################################################### -SELECT @@session.tx_isolation = VARIABLE_VALUE +SELECT @@session.transaction_isolation = VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES -WHERE VARIABLE_NAME='tx_isolation'; +WHERE VARIABLE_NAME='transaction_isolation'; --echo '#----------------------FN_DYNVARS_183_06------------------------#' ######################################################################### # Check if the value in GLOBAL Table matches value in variable # ######################################################################### -SELECT @@global.tx_isolation = VARIABLE_VALUE +SELECT @@global.transaction_isolation = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES -WHERE VARIABLE_NAME='tx_isolation'; +WHERE VARIABLE_NAME='transaction_isolation'; --echo '#---------------------FN_DYNVARS_183_07-------------------------#' @@ -157,56 +157,56 @@ WHERE VARIABLE_NAME='tx_isolation'; ################################################################### # test if variable accepts 0,1,2 -SET @@global.tx_isolation = 0; -SELECT @@global.tx_isolation; +SET @@global.transaction_isolation = 0; +SELECT @@global.transaction_isolation; -SET @@global.tx_isolation = 1; -SELECT @@global.tx_isolation; +SET @@global.transaction_isolation = 1; +SELECT @@global.transaction_isolation; -SET @@global.tx_isolation = 2; -SELECT @@global.tx_isolation; +SET @@global.transaction_isolation = 2; +SELECT @@global.transaction_isolation; -SET @@global.tx_isolation = 3; -SELECT @@global.tx_isolation; +SET @@global.transaction_isolation = 3; +SELECT @@global.transaction_isolation; --Error ER_WRONG_TYPE_FOR_VAR -SET @@global.tx_isolation = 0.4; +SET @@global.transaction_isolation = 0.4; --echo '#---------------------FN_DYNVARS_183_08----------------------#' ################################################################### # Check if TRUE and FALSE values can be used on variable # ################################################################### -SET @@global.tx_isolation = TRUE; -SELECT @@global.tx_isolation; -SET @@global.tx_isolation = FALSE; -SELECT @@global.tx_isolation; +SET @@global.transaction_isolation = TRUE; +SELECT @@global.transaction_isolation; +SET @@global.transaction_isolation = FALSE; +SELECT @@global.transaction_isolation; --echo '#---------------------FN_DYNVARS_183_09----------------------#' -######################################################################## -# Check if tx_isolation can be accessed with and without @@ sign # -######################################################################## +########################################################################### +# Check if transaction_isolation can be accessed with and without @@ sign # +########################################################################### -SET tx_isolation = 'REPEATABLE-READ'; +SET transaction_isolation = 'REPEATABLE-READ'; #using SET SESSION|GLOBAL syntax -SET session tx_isolation = 'REPEATABLE-READ'; -SELECT @@tx_isolation; +SET session transaction_isolation = 'REPEATABLE-READ'; +SELECT @@transaction_isolation; -SET global tx_isolation = 'REPEATABLE-READ'; -SELECT @@global.tx_isolation; +SET global transaction_isolation = 'REPEATABLE-READ'; +SELECT @@global.transaction_isolation; ############################## # Restore initial value # ############################## -SET @@global.tx_isolation = @global_start_value; -SELECT @@global.tx_isolation; +SET @@global.transaction_isolation = @global_start_value; +SELECT @@global.transaction_isolation; -SET @@session.tx_isolation = @session_start_value; -SELECT @@session.tx_isolation; +SET @@session.transaction_isolation = @session_start_value; +SELECT @@session.transaction_isolation; #################################################################### -# END OF tx_isolation TESTS # +# END OF transaction_isolation TESTS # #################################################################### diff --git a/mysql-test/suite/sys_vars/t/tx_isolation_func-master.opt b/mysql-test/suite/sys_vars/t/transaction_isolation_func-master.opt index 67166a46cd1..67166a46cd1 100644 --- a/mysql-test/suite/sys_vars/t/tx_isolation_func-master.opt +++ b/mysql-test/suite/sys_vars/t/transaction_isolation_func-master.opt diff --git a/mysql-test/suite/sys_vars/t/tx_isolation_func.test b/mysql-test/suite/sys_vars/t/transaction_isolation_func.test index 164422be06a..085d59cb0ee 100644 --- a/mysql-test/suite/sys_vars/t/tx_isolation_func.test +++ b/mysql-test/suite/sys_vars/t/transaction_isolation_func.test @@ -1,6 +1,6 @@ -############# mysql-test\t\tx_isolation_func.test ####################################### +############## mysql-test\suite\sys_vars\t\transaction_isolation_func.test ############## # # -# Variable Name: tx_isolation # +# Variable Name: transaction_isolation # # Scope: GLOBAL & SESSION # # Access Type: Dynamic # # Data Type: ENUMERATION # @@ -11,7 +11,7 @@ # Creation Date: 2008-02-25 # # Author: Sharique Abdullah # # # -# Description: Test Cases of Dynamic System Variable "tx_isolation" # +# Description: Test Cases of Dynamic System Variable "transaction_isolation" # # that checks behavior of this variable in the following ways # # * Functionality based on different values # # # @@ -26,8 +26,8 @@ # Setup # -SET @session_tx_isolation = @@SESSION.tx_isolation; -SET @global_tx_isolation = @@GLOBAL.tx_isolation; +SET @session_transaction_isolation = @@SESSION.transaction_isolation; +SET @global_transaction_isolation = @@GLOBAL.transaction_isolation; # # Creating connections @@ -68,11 +68,11 @@ INSERT INTO t1 VALUES(24, 24); # Testing for value READ-UNCOMMITTED # connection con0; -SET SESSION tx_isolation = 'READ-UNCOMMITTED'; +SET SESSION transaction_isolation = 'READ-UNCOMMITTED'; set binlog_format=mixed; connection con1; -SET SESSION tx_isolation = 'READ-UNCOMMITTED'; +SET SESSION transaction_isolation = 'READ-UNCOMMITTED'; set binlog_format=mixed; # @@ -139,10 +139,10 @@ COMMIT; # Testing for value READ-COMMITTED # connection con0; -SET SESSION tx_isolation = 'READ-COMMITTED'; +SET SESSION transaction_isolation = 'READ-COMMITTED'; connection con1; -SET SESSION tx_isolation = 'READ-COMMITTED'; +SET SESSION transaction_isolation = 'READ-COMMITTED'; # # Testing WHERE on keys using % on even rows @@ -177,10 +177,10 @@ COMMIT; # Testing for value REPEATABLE-READ # connection con0; -SET SESSION tx_isolation = 'REPEATABLE-READ'; +SET SESSION transaction_isolation = 'REPEATABLE-READ'; connection con1; -SET SESSION tx_isolation = 'REPEATABLE-READ'; +SET SESSION transaction_isolation = 'REPEATABLE-READ'; # # Testing WHERE on keys using % on even rows @@ -279,10 +279,10 @@ COMMIT; # Testing for value SERIALIZABLE # connection con0; -SET SESSION tx_isolation = 'SERIALIZABLE'; +SET SESSION transaction_isolation = 'SERIALIZABLE'; connection con1; -SET SESSION tx_isolation = 'SERIALIZABLE'; +SET SESSION transaction_isolation = 'SERIALIZABLE'; # # Testing WHERE on keys using # on even rows @@ -321,33 +321,33 @@ COMMIT; # Session data integrity check & GLOBAL Value check # -SET GLOBAL tx_isolation = 'READ-UNCOMMITTED'; +SET GLOBAL transaction_isolation = 'READ-UNCOMMITTED'; connect (con_int1,localhost,root,,); connection con_int1; -SELECT @@SESSION.tx_isolation; +SELECT @@SESSION.transaction_isolation; --echo READ-UNCOMMITTED Expected -SET SESSION tx_isolation = 'SERIALIZABLE'; +SET SESSION transaction_isolation = 'SERIALIZABLE'; connect (con_int2,localhost,root,,); connection con_int2; -SELECT @@SESSION.tx_isolation; +SELECT @@SESSION.transaction_isolation; --echo READ-UNCOMMITTED Expected -SET SESSION tx_isolation = 'REPEATABLE-READ'; +SET SESSION transaction_isolation = 'REPEATABLE-READ'; connection con_int2; -SELECT @@SESSION.tx_isolation; +SELECT @@SESSION.transaction_isolation; --echo REPEATABLE-READ Expected connection con_int1; -SELECT @@SESSION.tx_isolation; +SELECT @@SESSION.transaction_isolation; --echo SERIALIZABLE Expected -SELECT @@GLOBAL.tx_isolation; +SELECT @@GLOBAL.transaction_isolation; --echo READ-UNCOMMITTED Expected connection default; @@ -359,8 +359,8 @@ disconnect con_int2; # Cleanup # -SET @@SESSION.tx_isolation = @session_tx_isolation; -SET @@GLOBAL.tx_isolation = @global_tx_isolation; +SET @@SESSION.transaction_isolation = @session_transaction_isolation; +SET @@GLOBAL.transaction_isolation = @global_transaction_isolation; connection default; disconnect con0; diff --git a/mysql-test/suite/sys_vars/t/tx_read_only_basic.test b/mysql-test/suite/sys_vars/t/transaction_read_only_basic.test index 0ebfcc31a89..ba8d65a53f1 100644 --- a/mysql-test/suite/sys_vars/t/tx_read_only_basic.test +++ b/mysql-test/suite/sys_vars/t/transaction_read_only_basic.test @@ -1,6 +1,6 @@ -############## mysql-test\t\tx_read_only_basic.test ########################### +######## mysql-test\suite\sys_vars\t\transaction_read_only_basic.test ######### # # -# Variable Name: tx_read_only # +# Variable Name: transaction_read_only # # Scope: GLOBAL & SESSION # # Access Type: Dynamic # # Data Type: boolean # @@ -11,7 +11,7 @@ # Creation Date: 2012-01-12 # # Author: joh # # # -# Description: Test Cases of Dynamic System Variable tx_read_only # +# Description: Test Cases of Dynamic System Variable transaction_read_only # # that checks the behavior of this variable in the following ways# # * Default Value # # * Valid & Invalid values # @@ -26,7 +26,7 @@ --source include/load_sysvars.inc --echo #################################################################### ---echo # START OF tx_read_only TESTS # +--echo # START OF transaction_read_only TESTS # --echo #################################################################### @@ -34,101 +34,101 @@ --echo # Save initial value # --echo ############################################################# -SET @start_global_value = @@global.tx_read_only; +SET @start_global_value = @@global.transaction_read_only; SELECT @start_global_value; -SET @start_session_value = @@session.tx_read_only; +SET @start_session_value = @@session.transaction_read_only; SELECT @start_session_value; --echo ######################################################################## ---echo # Display the DEFAULT value of tx_read_only # +--echo # Display the DEFAULT value of transaction_read_only # --echo ######################################################################## -SET @@global.tx_read_only = ON; -SET @@global.tx_read_only = DEFAULT; -SELECT @@global.tx_read_only; +SET @@global.transaction_read_only = ON; +SET @@global.transaction_read_only = DEFAULT; +SELECT @@global.transaction_read_only; -SET @@session.tx_read_only = ON; -SET @@session.tx_read_only = DEFAULT; -SELECT @@session.tx_read_only; +SET @@session.transaction_read_only = ON; +SET @@session.transaction_read_only = DEFAULT; +SELECT @@session.transaction_read_only; ---echo ############################################################################## ---echo # Change the value of tx_read_only to a valid value for GLOBAL Scope # ---echo ############################################################################## +--echo ############################################################################### +--echo # Change the value of transaction_read_only to a valid value for GLOBAL Scope # +--echo ############################################################################### -SET @@global.tx_read_only = ON; -SELECT @@global.tx_read_only; -SET @@global.tx_read_only = OFF; -SELECT @@global.tx_read_only; -SET @@global.tx_read_only = 0; -SELECT @@global.tx_read_only; -SET @@global.tx_read_only = 1; -SELECT @@global.tx_read_only; -SET @@global.tx_read_only = TRUE; -SELECT @@global.tx_read_only; -SET @@global.tx_read_only = FALSE; -SELECT @@global.tx_read_only; +SET @@global.transaction_read_only = ON; +SELECT @@global.transaction_read_only; +SET @@global.transaction_read_only = OFF; +SELECT @@global.transaction_read_only; +SET @@global.transaction_read_only = 0; +SELECT @@global.transaction_read_only; +SET @@global.transaction_read_only = 1; +SELECT @@global.transaction_read_only; +SET @@global.transaction_read_only = TRUE; +SELECT @@global.transaction_read_only; +SET @@global.transaction_read_only = FALSE; +SELECT @@global.transaction_read_only; ---echo ############################################################################### ---echo # Change the value of tx_read_only to a valid value for SESSION Scope # ---echo ############################################################################### +--echo ################################################################################ +--echo # Change the value of transaction_read_only to a valid value for SESSION Scope # +--echo ################################################################################ -SET @@session.tx_read_only = ON; -SELECT @@session.tx_read_only; -SET @@session.tx_read_only = OFF; -SELECT @@session.tx_read_only; -SET @@session.tx_read_only = 0; -SELECT @@session.tx_read_only; -SET @@session.tx_read_only = 1; -SELECT @@session.tx_read_only; -SET @@session.tx_read_only = TRUE; -SELECT @@session.tx_read_only; -SET @@session.tx_read_only = FALSE; -SELECT @@session.tx_read_only; - - ---echo ################################################################ ---echo # Change the value of tx_read_only to an invalid value # ---echo ################################################################ +SET @@session.transaction_read_only = ON; +SELECT @@session.transaction_read_only; +SET @@session.transaction_read_only = OFF; +SELECT @@session.transaction_read_only; +SET @@session.transaction_read_only = 0; +SELECT @@session.transaction_read_only; +SET @@session.transaction_read_only = 1; +SELECT @@session.transaction_read_only; +SET @@session.transaction_read_only = TRUE; +SELECT @@session.transaction_read_only; +SET @@session.transaction_read_only = FALSE; +SELECT @@session.transaction_read_only; + + +--echo ################################################################# +--echo # Change the value of transaction_read_only to an invalid value # +--echo ################################################################# --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.tx_read_only = 'ONN'; +SET @@global.transaction_read_only = 'ONN'; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.tx_read_only = "OFFF"; +SET @@global.transaction_read_only = "OFFF"; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.tx_read_only = TTRUE; +SET @@global.transaction_read_only = TTRUE; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.tx_read_only = FELSE; +SET @@global.transaction_read_only = FELSE; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.tx_read_only = -1024; +SET @@global.transaction_read_only = -1024; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.tx_read_only = 65536; +SET @@global.transaction_read_only = 65536; --Error ER_WRONG_TYPE_FOR_VAR -SET @@global.tx_read_only = 65530.34; +SET @@global.transaction_read_only = 65530.34; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.tx_read_only = test; +SET @@global.transaction_read_only = test; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.tx_read_only = ONN; +SET @@session.transaction_read_only = ONN; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.tx_read_only = ONF; +SET @@session.transaction_read_only = ONF; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.tx_read_only = OF; +SET @@session.transaction_read_only = OF; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.tx_read_only = 'OFN'; +SET @@session.transaction_read_only = 'OFN'; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.tx_read_only = -2; +SET @@session.transaction_read_only = -2; --Error ER_WRONG_TYPE_FOR_VAR -SET @@session.tx_read_only = 65530.34; +SET @@session.transaction_read_only = 65530.34; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.tx_read_only = 65550; +SET @@session.transaction_read_only = 65550; --Error ER_WRONG_VALUE_FOR_VAR -SET @@session.tx_read_only = test; -SELECT @@session.tx_read_only; +SET @@session.transaction_read_only = test; +SELECT @@session.transaction_read_only; --echo #################################################################### @@ -136,26 +136,26 @@ SELECT @@session.tx_read_only; --echo #################################################################### -SELECT IF(@@global.tx_read_only, "ON", "OFF") = VARIABLE_VALUE +SELECT IF(@@global.transaction_read_only, "ON", "OFF") = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES -WHERE VARIABLE_NAME='tx_read_only'; +WHERE VARIABLE_NAME='transaction_read_only'; --echo #################################################################### --echo # Check if the value in SESSION Table matches value in variable # --echo #################################################################### -SELECT IF(@@session.tx_read_only, "ON", "OFF") = VARIABLE_VALUE +SELECT IF(@@session.transaction_read_only, "ON", "OFF") = VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES -WHERE VARIABLE_NAME='tx_read_only'; +WHERE VARIABLE_NAME='transaction_read_only'; --echo ############################################################################### --echo # Check if accessing variable with and without GLOBAL point to same variable # --echo ############################################################################### -SET @@tx_read_only = OFF; -SET @@global.tx_read_only = ON; -SELECT @@tx_read_only = @@global.tx_read_only; +SET @@transaction_read_only = OFF; +SET @@global.transaction_read_only = ON; +SELECT @@transaction_read_only = @@global.transaction_read_only; --echo ############################################################################## @@ -163,37 +163,37 @@ SELECT @@tx_read_only = @@global.tx_read_only; --echo # to same session variable # --echo ############################################################################## -SET @@tx_read_only = ON; -SELECT @@tx_read_only = @@local.tx_read_only; -SELECT @@local.tx_read_only = @@session.tx_read_only; +SET @@transaction_read_only = ON; +SELECT @@transaction_read_only = @@local.transaction_read_only; +SELECT @@local.transaction_read_only = @@session.transaction_read_only; --echo ############################################################################### ---echo # Check if tx_read_only can be accessed with and without @@ sign # +--echo # Check if transaction_read_only can be accessed with and without @@ sign # --echo ############################################################################### --echo # @@session is synonym for SESSION -SET @@session.tx_read_only= 0; +SET @@session.transaction_read_only= 0; --echo # Without modifier, SET changes session variable -SET tx_read_only = 1; -SELECT @@tx_read_only; +SET transaction_read_only = 1; +SELECT @@transaction_read_only; --echo # name1.name2 refers to database_name.table_name --Error ER_UNKNOWN_TABLE -SELECT session.tx_read_only; +SELECT session.transaction_read_only; --echo #################################### --echo # Restore initial value # --echo #################################### -SET @@global.tx_read_only = @start_global_value; -SELECT @@global.tx_read_only; -SET @@session.tx_read_only = @start_session_value; -SELECT @@session.tx_read_only; +SET @@global.transaction_read_only = @start_global_value; +SELECT @@global.transaction_read_only; +SET @@session.transaction_read_only = @start_session_value; +SELECT @@session.transaction_read_only; --echo ######################################################### ---echo # END OF tx_read_only TESTS # +--echo # END OF transaction_read_only TESTS # --echo ######################################################### diff --git a/mysql-test/suite/sys_vars/t/tx_compatibility-master.opt b/mysql-test/suite/sys_vars/t/tx_compatibility-master.opt new file mode 100644 index 00000000000..f22a5ebb640 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/tx_compatibility-master.opt @@ -0,0 +1,2 @@ +--transaction-isolation=SERIALIZABLE +--transaction-read-only diff --git a/mysql-test/suite/sys_vars/t/tx_compatibility.test b/mysql-test/suite/sys_vars/t/tx_compatibility.test new file mode 100644 index 00000000000..2521c366050 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/tx_compatibility.test @@ -0,0 +1,68 @@ +--echo # +--echo # MDEV-21921 Make transaction_isolation and transaction_read_only into +--echo # system variables +--echo # + +SET @saved_global_isolation= @@global.transaction_isolation; +SET @saved_global_read_only= @@global.transaction_read_only; + +--echo # Case 1: Check the influence of --transaction_* on +--echo # @@session.transaction_* and @@global.transaction_*, +--echo # @@session.tx_*, @@global.tx_*. + +SELECT @@session.transaction_isolation, @@global.transaction_isolation, + @@session.tx_isolation, @@global.tx_isolation; +SHOW GLOBAL VARIABLES LIKE '%_isolation'; +SHOW SESSION VARIABLES LIKE '%_isolation'; + +SELECT @@session.transaction_read_only, @@global.transaction_read_only, + @@session.tx_read_only, @@global.tx_read_only; +SHOW GLOBAL VARIABLES LIKE '%_read_only'; +SHOW SESSION VARIABLES LIKE '%_read_only'; + +--echo # Case 2: Check that the change to tx_* is reflected to transaction_*. + +SET tx_isolation= 'REPEATABLE-READ'; +SET @@global.tx_isolation= 'SERIALIZABLE'; +SELECT @@session.tx_isolation, @@global.tx_isolation, +@@session.transaction_isolation, @@global.transaction_isolation; +SHOW GLOBAL VARIABLES LIKE '%_isolation'; +SHOW SESSION VARIABLES LIKE '%_isolation'; + +SET STATEMENT tx_isolation= 'SERIALIZABLE' FOR SHOW SESSION VARIABLES LIKE '%_isolation'; +SHOW SESSION VARIABLES LIKE '%_isolation'; + +SET tx_read_only= OFF; +SET @@global.tx_read_only= ON; +SELECT @@session.tx_read_only, @@global.tx_read_only, +@@session.transaction_read_only, @@global.transaction_read_only; +SHOW GLOBAL VARIABLES LIKE '%_read_only'; +SHOW SESSION VARIABLES LIKE '%_read_only'; + +SET STATEMENT tx_read_only= ON FOR SHOW SESSION VARIABLES LIKE '%_read_only'; +SHOW SESSION VARIABLES LIKE '%_read_only'; + +--echo # Case 3: Check that the change to transaction_* is reflected to tx_*. + +SET transaction_isolation= 'SERIALIZABLE'; +SET @@global.transaction_isolation= 'REPEATABLE-READ'; +SELECT @@session.tx_isolation, @@global.tx_isolation, +@@session.transaction_isolation, @@global.transaction_isolation; +SHOW GLOBAL VARIABLES LIKE '%_isolation'; +SHOW SESSION VARIABLES LIKE '%_isolation'; + +SET STATEMENT transaction_isolation= 'REPEATABLE-READ' FOR SHOW SESSION VARIABLES LIKE '%_isolation'; +SHOW SESSION VARIABLES LIKE '%_isolation'; + +SET transaction_read_only= ON; +SET @@global.transaction_read_only= OFF; +SELECT @@session.tx_read_only, @@global.tx_read_only, +@@session.transaction_read_only, @@global.transaction_read_only; +SHOW GLOBAL VARIABLES LIKE '%_read_only'; +SHOW SESSION VARIABLES LIKE '%_read_only'; + +SET STATEMENT transaction_read_only= OFF FOR SHOW SESSION VARIABLES LIKE '%_read_only'; +SHOW SESSION VARIABLES LIKE '%_read_only'; + +SET @@global.transaction_isolation= @saved_global_isolation; +SET @@global.transaction_read_only= @saved_global_read_only; diff --git a/mysql-test/suite/versioning/r/delete_history.result b/mysql-test/suite/versioning/r/delete_history.result index 9365145e699..a49ec025dff 100644 --- a/mysql-test/suite/versioning/r/delete_history.result +++ b/mysql-test/suite/versioning/r/delete_history.result @@ -169,7 +169,7 @@ explain extended delete history from t1 before system_time '2039-01-01 23:00'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 1 100.00 Using where Warnings: -Note 1003 delete from `test`.`t1` FOR SYSTEM_TIME BEFORE TIMESTAMP '2039-01-01 23:00' where `test`.`t1`.`row_end` < '2039-01-01 23:00' and is_history(`test`.`t1`.`row_end`) +Note 1003 delete from `test`.`t1` FOR SYSTEM_TIME BEFORE TIMESTAMP '2039-01-01 23:00' using dual where `test`.`t1`.`row_end` < '2039-01-01 23:00' and is_history(`test`.`t1`.`row_end`) create or replace procedure p() delete history from t1 before system_time '2039-01-01 23:00'; call p; select * from t1; diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 7f9c92f1cf2..774cdb4acf4 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -34,52 +34,52 @@ IF(NOT CMAKE_CROSSCOMPILING OR DEFINED CMAKE_CROSSCOMPILING_EMULATOR) TARGET_LINK_LIBRARIES(comp_sql) ENDIF() -# Build mysql_fix_privilege_tables.sql (concatenate 3 sql scripts) +# Build mariadb_fix_privilege_tables.sql (concatenate 3 sql scripts) IF(NOT WIN32 OR (CMAKE_CROSSCOMPILING AND NOT DEFINED CMAKE_CROSSCOMPILING_EMULATOR)) FIND_PROGRAM(CAT_EXECUTABLE cat DOC "path to the executable") MARK_AS_ADVANCED(CAT_EXECUTABLE) ENDIF() IF(NOT ("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")) - FOREACH(f fill_help_tables.sql mysql_system_tables_fix.sql mysql_system_tables.sql mysql_system_tables_data.sql mysql_performance_tables.sql) + FOREACH(f fill_help_tables.sql mariadb_system_tables_fix.sql mariadb_system_tables.sql mariadb_system_tables_data.sql mariadb_performance_tables.sql) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${f} ${CMAKE_CURRENT_BINARY_DIR}/${f} COPYONLY) ENDFOREACH() ENDIF() IF(CAT_EXECUTABLE) SET(CAT_COMMAND COMMAND - ${CAT_EXECUTABLE} mysql_system_tables_fix.sql mysql_system_tables.sql mysql_performance_tables.sql mysql_sys_schema.sql> - mysql_fix_privilege_tables.sql + ${CAT_EXECUTABLE} mariadb_system_tables_fix.sql mariadb_system_tables.sql mariadb_performance_tables.sql mariadb_sys_schema.sql> + mariadb_fix_privilege_tables.sql ) ELSEIF(WIN32) SET(CAT_COMMAND COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_CURRENT_BINARY_DIR} - cmd /c copy /b mysql_system_tables_fix.sql + mysql_system_tables.sql + mysql_performance_tables.sql + mysql_sys_schema.sql - mysql_fix_privilege_tables.sql ) + cmd /c copy /b mariadb_system_tables_fix.sql + mariadb_system_tables.sql + mariadb_performance_tables.sql + mariadb_sys_schema.sql + mariadb_fix_privilege_tables.sql ) ELSE() MESSAGE(FATAL_ERROR "Cannot concatenate files") ENDIF() -# Build mysql_fix_privilege_tables.c +# Build mariadb_fix_privilege_tables.c ADD_CUSTOM_COMMAND( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/mysql_fix_privilege_tables_sql.c + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/mariadb_fix_privilege_tables_sql.c ${CAT_COMMAND} COMMAND comp_sql - mysql_fix_privilege_tables - mysql_fix_privilege_tables.sql - mysql_fix_privilege_tables_sql.c + mariadb_fix_privilege_tables + mariadb_fix_privilege_tables.sql + mariadb_fix_privilege_tables_sql.c WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS comp_sql - ${CMAKE_CURRENT_SOURCE_DIR}/mysql_system_tables.sql - ${CMAKE_CURRENT_SOURCE_DIR}/mysql_system_tables_fix.sql - ${CMAKE_CURRENT_SOURCE_DIR}/mysql_performance_tables.sql - ${CMAKE_CURRENT_BINARY_DIR}/mysql_sys_schema.sql + ${CMAKE_CURRENT_SOURCE_DIR}/mariadb_system_tables.sql + ${CMAKE_CURRENT_SOURCE_DIR}/mariadb_system_tables_fix.sql + ${CMAKE_CURRENT_SOURCE_DIR}/mariadb_performance_tables.sql + ${CMAKE_CURRENT_BINARY_DIR}/mariadb_sys_schema.sql ) # Add target for the above to be built ADD_CUSTOM_TARGET(GenFixPrivs ALL - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/mysql_fix_privilege_tables_sql.c + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/mariadb_fix_privilege_tables_sql.c ) IF(UNIX AND NOT WITHOUT_SERVER) @@ -109,15 +109,15 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/maria_add_gis_sp.sql.in IF (NOT WITHOUT_SERVER) INSTALL(FILES - ${CMAKE_CURRENT_SOURCE_DIR}/mysql_system_tables.sql - ${CMAKE_CURRENT_SOURCE_DIR}/mysql_system_tables_data.sql - ${CMAKE_CURRENT_SOURCE_DIR}/mysql_performance_tables.sql - ${CMAKE_CURRENT_SOURCE_DIR}/mysql_test_db.sql + ${CMAKE_CURRENT_SOURCE_DIR}/mariadb_system_tables.sql + ${CMAKE_CURRENT_SOURCE_DIR}/mariadb_system_tables_data.sql + ${CMAKE_CURRENT_SOURCE_DIR}/mariadb_performance_tables.sql + ${CMAKE_CURRENT_SOURCE_DIR}/mariadb_test_db.sql ${CMAKE_CURRENT_SOURCE_DIR}/fill_help_tables.sql - ${CMAKE_CURRENT_SOURCE_DIR}/mysql_test_data_timezone.sql + ${CMAKE_CURRENT_SOURCE_DIR}/mariadb_test_data_timezone.sql ${CMAKE_CURRENT_BINARY_DIR}/maria_add_gis_sp.sql ${CMAKE_CURRENT_BINARY_DIR}/maria_add_gis_sp_bootstrap.sql - ${CMAKE_CURRENT_BINARY_DIR}/mysql_sys_schema.sql + ${CMAKE_CURRENT_BINARY_DIR}/mariadb_sys_schema.sql ${FIX_PRIVILEGES_SQL} DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server ) @@ -208,8 +208,8 @@ ENDIF() SET(resolveip_locations "$basedir/${INSTALL_BINDIR} $basedir/bin") SET(mysqld_locations "$basedir/${INSTALL_SBINDIR} $basedir/libexec $basedir/sbin $basedir/bin") -SET(errmsg_locations "$basedir/${INSTALL_MYSQLSHAREDIR}/english $basedir/share/english $basedir/share/mysql/english") -SET(pkgdata_locations "$basedir/${INSTALL_MYSQLSHAREDIR} $basedir/share $basedir/share/mysql") +SET(errmsg_locations "$basedir/${INSTALL_MYSQLSHAREDIR}/english $basedir/share/english $basedir/share/mariadb/english $basedir/share/mysql/english") +SET(pkgdata_locations "$basedir/${INSTALL_MYSQLSHAREDIR} $basedir/share $basedir/share/mariadb $basedir/share/mysql") # install mysql_install_db.sh at this point since it needs # different values for the above variables that will change diff --git a/scripts/mysql_performance_tables.sql b/scripts/mariadb_performance_tables.sql index 306160355de..306160355de 100644 --- a/scripts/mysql_performance_tables.sql +++ b/scripts/mariadb_performance_tables.sql diff --git a/scripts/mysql_system_tables.sql b/scripts/mariadb_system_tables.sql index 0c33e40cf57..0c33e40cf57 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mariadb_system_tables.sql diff --git a/scripts/mysql_system_tables_data.sql b/scripts/mariadb_system_tables_data.sql index ab3dd704d2e..ab3dd704d2e 100644 --- a/scripts/mysql_system_tables_data.sql +++ b/scripts/mariadb_system_tables_data.sql diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mariadb_system_tables_fix.sql index 7d8fcd9aa0f..7d8fcd9aa0f 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mariadb_system_tables_fix.sql diff --git a/scripts/mysql_test_data_timezone.sql b/scripts/mariadb_test_data_timezone.sql index 8d07d413cef..8d07d413cef 100644 --- a/scripts/mysql_test_data_timezone.sql +++ b/scripts/mariadb_test_data_timezone.sql diff --git a/scripts/mysql_test_db.sql b/scripts/mariadb_test_db.sql index c83f2c44a4f..c83f2c44a4f 100644 --- a/scripts/mysql_test_db.sql +++ b/scripts/mariadb_test_db.sql diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index b28e533ecd8..e9a141af0d6 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -402,12 +402,12 @@ fi # Set up paths to SQL scripts required for bootstrap fill_help_tables="$srcpkgdatadir/fill_help_tables.sql" -create_system_tables="$srcpkgdatadir/mysql_system_tables.sql" -create_system_tables2="$srcpkgdatadir/mysql_performance_tables.sql" -fill_system_tables="$srcpkgdatadir/mysql_system_tables_data.sql" +create_system_tables="$srcpkgdatadir/mariadb_system_tables.sql" +create_system_tables2="$srcpkgdatadir/mariadb_performance_tables.sql" +fill_system_tables="$srcpkgdatadir/mariadb_system_tables_data.sql" maria_add_gis_sp="$buildpkgdatadir/maria_add_gis_sp_bootstrap.sql" -mysql_test_db="$srcpkgdatadir/mysql_test_db.sql" -mysql_sys_schema="$buildpkgdatadir/mysql_sys_schema.sql" +mysql_test_db="$srcpkgdatadir/mariadb_test_db.sql" +mysql_sys_schema="$buildpkgdatadir/mariadb_sys_schema.sql" for f in "$fill_help_tables" "$create_system_tables" "$create_system_tables2" "$fill_system_tables" "$maria_add_gis_sp" "$mysql_test_db" "$mysql_sys_schema" do diff --git a/scripts/sys_schema/CMakeLists.txt b/scripts/sys_schema/CMakeLists.txt index dc023174fc7..9222f9fa7aa 100644 --- a/scripts/sys_schema/CMakeLists.txt +++ b/scripts/sys_schema/CMakeLists.txt @@ -175,4 +175,4 @@ FOREACH(f ${files}) FILE(READ ${f} content) SET(CMAKE_CONFIGURABLE_FILE_CONTENT "${CMAKE_CONFIGURABLE_FILE_CONTENT}${content}\n") ENDFOREACH() -CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/cmake/configurable_file_content.in ${CMAKE_BINARY_DIR}/scripts/mysql_sys_schema.sql) +CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/cmake/configurable_file_content.in ${CMAKE_BINARY_DIR}/scripts/mariadb_sys_schema.sql) diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index d6334052f24..45205204c93 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -102,7 +102,7 @@ if [ -z "$BACKUP_BIN" ]; then fi DATA="$WSREP_SST_OPT_DATA" -INFO_FILE='xtrabackup_galera_info' +INFO_FILE='mariadb_backup_galera_info' IST_FILE='xtrabackup_ist' MAGIC_FILE="$DATA/$INFO_FILE" @@ -1320,9 +1320,9 @@ else # joiner [ -f "$DATA/$IST_FILE" ] && rm -f "$DATA/$IST_FILE" - # May need xtrabackup_checkpoints later on + # May need mariadb_backup_checkpoints later on [ -f "$DATA/xtrabackup_binary" ] && rm -f "$DATA/xtrabackup_binary" - [ -f "$DATA/xtrabackup_galera_info" ] && rm -f "$DATA/xtrabackup_galera_info" + [ -f "$DATA/mariadb_backup_galera_info" ] && rm -f "$DATA/mariadb_backup_galera_info" ADDR="$WSREP_SST_OPT_HOST" @@ -1451,14 +1451,14 @@ else # joiner wsrep_log_info "Waiting for SST streaming to complete!" monitor_process $jpid - if [ ! -s "$DATA/xtrabackup_checkpoints" ]; then - wsrep_log_error "xtrabackup_checkpoints missing," \ + if [ ! -s "$DATA/mariadb_backup_checkpoints" ]; then + wsrep_log_error "mariadb_backup_checkpoints missing," \ "failed mariadb-backup/SST on donor" exit 2 fi # Compact backups are not supported by mariadb-backup - if grep -qw -F 'compact = 1' "$DATA/xtrabackup_checkpoints"; then + if grep -qw -F 'compact = 1' "$DATA/mariadb_backup_checkpoints"; then wsrep_log_info "Index compaction detected" wsrel_log_error "Compact backups are not supported by mariadb-backup" exit 2 @@ -1522,14 +1522,14 @@ else # joiner if [ -n "$WSREP_SST_OPT_BINLOG" ]; then cd "$DATA" binlogs="" - if [ -f 'xtrabackup_binlog_info' ]; then + if [ -f 'mariadb_backup_binlog_info' ]; then NL=$'\n' while read bin_string || [ -n "$bin_string" ]; do bin_file=$(echo "$bin_string" | cut -f1) if [ -f "$bin_file" ]; then binlogs="$binlogs${binlogs:+$NL}$bin_file" fi - done < 'xtrabackup_binlog_info' + done < 'mariadb_backup_binlog_info' else binlogs=$(ls -d -1 "$binlog_base".[0-9]* 2>/dev/null || :) fi diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 4938f8da02b..0284359fbc7 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -111,7 +111,9 @@ SET (SQL_SOURCE mf_iocache.cc my_decimal.cc mysqld.cc net_serv.cc keycaches.cc ../sql-common/client_plugin.c - opt_range.cc opt_sum.cc + opt_range.cc + opt_rewrite_date_cmp.cc + opt_sum.cc ../sql-common/pack.c parse_file.cc password.c procedure.cc protocol.cc records.cc repl_failsafe.cc rpl_filter.cc session_tracker.cc @@ -159,7 +161,7 @@ SET (SQL_SOURCE opt_table_elimination.cc sql_expression_cache.cc gcalc_slicescan.cc gcalc_tools.cc my_apc.cc mf_iocache_encr.cc item_jsonfunc.cc - my_json_writer.cc + my_json_writer.cc json_schema.cc json_schema_helper.cc rpl_gtid.cc rpl_parallel.cc semisync.cc semisync_master.cc semisync_slave.cc semisync_master_ack_receiver.cc @@ -481,14 +483,14 @@ IF(WIN32) ADD_CUSTOM_COMMAND(OUTPUT ${my_bootstrap_sql} COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_BINARY_DIR}/scripts - cmd /c copy mysql_system_tables.sql+mysql_system_tables_data.sql+fill_help_tables.sql+mysql_performance_tables.sql+mysql_test_db.sql+mysql_sys_schema.sql ${native_outfile} + cmd /c copy mariadb_system_tables.sql+mariadb_system_tables_data.sql+fill_help_tables.sql+mariadb_performance_tables.sql+mariadb_test_db.sql+mariadb_sys_schema.sql ${native_outfile} DEPENDS - ${CMAKE_SOURCE_DIR}/scripts/mysql_system_tables.sql - ${CMAKE_SOURCE_DIR}/scripts/mysql_system_tables_data.sql + ${CMAKE_SOURCE_DIR}/scripts/mariadb_system_tables.sql + ${CMAKE_SOURCE_DIR}/scripts/mariadb_system_tables_data.sql ${CMAKE_SOURCE_DIR}/scripts/fill_help_tables.sql - ${CMAKE_SOURCE_DIR}/scripts/mysql_performance_tables.sql - ${CMAKE_SOURCE_DIR}/scripts/mysql_test_db.sql - ${CMAKE_BINARY_DIR}/scripts/mysql_sys_schema.sql + ${CMAKE_SOURCE_DIR}/scripts/mariadb_performance_tables.sql + ${CMAKE_SOURCE_DIR}/scripts/mariadb_test_db.sql + ${CMAKE_BINARY_DIR}/scripts/mariadb_sys_schema.sql ) ADD_CUSTOM_COMMAND( diff --git a/sql/events.cc b/sql/events.cc index 01a11461655..45f99435348 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -119,7 +119,12 @@ bool Events::check_if_system_tables_error() { DBUG_ENTER("Events::check_if_system_tables_error"); - if (!inited) + if (opt_noacl) + { + my_error(ER_EVENTS_NO_ACL, MYF(0)); + DBUG_RETURN(TRUE); + } + else if (!inited) { my_error(ER_EVENTS_DB_ERROR, MYF(0)); DBUG_RETURN(TRUE); @@ -886,9 +891,17 @@ Events::init(THD *thd, bool opt_noacl_or_bootstrap) /* Was disabled explicitly from the command line */ - if (opt_event_scheduler == Events::EVENTS_DISABLED || - opt_noacl_or_bootstrap) + if (opt_event_scheduler == Events::EVENTS_DISABLED) DBUG_RETURN(FALSE); + else if (opt_noacl_or_bootstrap) + { + my_message(ER_STARTUP, + "Event Scheduler will not function when starting " + "with --skip-grant-tables or --bootstrap.", + MYF(ME_ERROR_LOG)); + opt_event_scheduler= EVENTS_DISABLED; + DBUG_RETURN(FALSE); + } /* We need a temporary THD during boot */ if (!thd) @@ -934,10 +947,8 @@ Events::init(THD *thd, bool opt_noacl_or_bootstrap) Since we allow event DDL even if the scheduler is disabled, check the system tables, as we might need them. - If run with --skip-grant-tables or --bootstrap, don't try to do the - check of system tables and don't complain: in these modes the tables - are most likely not there and we're going to disable the event - scheduler anyway. + If run with --skip-grant-tables or --bootstrap, we have already + disabled the event scheduler anyway. */ if (Event_db_repository::check_system_tables(thd)) { diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index de0229e9e2d..f3ead2e831b 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4698,8 +4698,8 @@ exit: part_share->next_auto_inc_val if needed. (not to be used if auto_increment on secondary field in a multi-column index) - mysql_update does not set table->next_number_field, so we use - table->found_next_number_field instead. + Sql_cmd_update::update_single_table() does not set table->next_number_field, + so we use table->found_next_number_field instead. Also checking that the field is marked in the write set. */ if (table->found_next_number_field && @@ -4812,7 +4812,7 @@ int ha_partition::delete_row(const uchar *buf) Called from item_sum.cc by Item_func_group_concat::clear(), Item_sum_count::clear(), and Item_func_group_concat::clear(). - Called from sql_delete.cc by mysql_delete(). + Called from sql_delete.cc by Sql_cmd_delete::delete_single_table(). Called from sql_select.cc by JOIN::reset(). Called from sql_union.cc by st_select_lex_unit::exec(). */ diff --git a/sql/handler.h b/sql/handler.h index 0810d1a503a..464c4a32651 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -248,7 +248,7 @@ enum chf_create_flags { Example: UPDATE a=1 WHERE pk IN (<keys>) - mysql_update() + Sql_cmd_update::update_single_table() { if (<conditions for starting read removal>) start_read_removal() @@ -1807,7 +1807,8 @@ struct THD_TRANS modified non-transactional tables of top-level statements. At the end of the previous statement and at the beginning of the session, it is reset to FALSE. If such functions - as mysql_insert, mysql_update, mysql_delete etc modify a + as mysql_insert(), Sql_cmd_update::update_single_table, + Sql_cmd_delete::delete_single_table modify a non-transactional table, they set this flag to TRUE. At the end of the statement, the value of stmt.modified_non_trans_table is merged with all.modified_non_trans_table and gets reset. diff --git a/sql/item.cc b/sql/item.cc index ebb4512cc49..c55348bcdf3 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6957,7 +6957,8 @@ Item *Item_int::clone_item(THD *thd) } -void Item_datetime::set(longlong packed, enum_mysql_timestamp_type ts_type) +void Item_datetime::set_from_packed(longlong packed, + enum_mysql_timestamp_type ts_type) { unpack_time(packed, <ime, ts_type); } @@ -6973,6 +6974,16 @@ longlong Item_datetime::val_int() return TIME_to_ulonglong(<ime); } +void Item_datetime::print(String *str, enum_query_type query_type) +{ + Datetime dt(current_thd, this); + String dt_str; + dt.to_string(&dt_str, decimals); + str->append('\''); + str->append(dt_str); + str->append('\''); +} + int Item_decimal::save_in_field(Field *field, bool no_conversions) { field->set_notnull(); diff --git a/sql/item.h b/sql/item.h index 9332b369a4f..ae503636116 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2514,6 +2514,8 @@ public: { return this; } virtual Item *multiple_equality_transformer(THD *thd, uchar *arg) { return this; } + virtual Item* date_conds_transformer(THD *thd, uchar *arg) + { return this; } virtual bool expr_cache_is_needed(THD *) { return FALSE; } virtual Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs); bool needs_charset_converter(uint32 length, CHARSET_INFO *tocs) const @@ -4514,12 +4516,14 @@ public: int save_in_field(Field *field, bool no_conversions) override; longlong val_int() override; double val_real() override { return (double)val_int(); } - void set(longlong packed, enum_mysql_timestamp_type ts_type); + void set(const MYSQL_TIME *datetime) { ltime= *datetime; } + void set_from_packed(longlong packed, enum_mysql_timestamp_type ts_type); bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) override { *to= ltime; return false; } + void print(String *str, enum_query_type query_type) override; }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index b8b02093278..8577bc4fb6b 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -7837,3 +7837,4 @@ Item *Item_equal::multiple_equality_transformer(THD *thd, uchar *arg) break; } } + diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 99656e910ba..556374eff6a 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -25,6 +25,7 @@ #include "item_func.h" /* Item_int_func, Item_bool_func */ #include "item.h" +#include "opt_rewrite_date_cmp.h" extern Item_result item_cmp_type(Item_result a,Item_result b); inline Item_result item_cmp_type(const Item *a, const Item *b) @@ -787,6 +788,8 @@ public: friend class Arg_comparator; Item *get_copy(THD *thd) override { return get_item_copy<Item_func_eq>(thd, this); } + Item* date_conds_transformer(THD *thd, uchar *arg) override + { return do_date_conds_transformation(thd, this); } }; class Item_func_equal final :public Item_bool_rowready_func2 @@ -836,6 +839,8 @@ public: Item *negated_item(THD *thd) override; Item *get_copy(THD *thd) override { return get_item_copy<Item_func_ge>(thd, this); } + Item* date_conds_transformer(THD *thd, uchar *arg) override + { return do_date_conds_transformation(thd, this); } }; @@ -856,6 +861,8 @@ public: Item *negated_item(THD *thd) override; Item *get_copy(THD *thd) override { return get_item_copy<Item_func_gt>(thd, this); } + Item* date_conds_transformer(THD *thd, uchar *arg) override + { return do_date_conds_transformation(thd, this); } }; @@ -876,6 +883,8 @@ public: Item *negated_item(THD *thd) override; Item *get_copy(THD *thd) override { return get_item_copy<Item_func_le>(thd, this); } + Item* date_conds_transformer(THD *thd, uchar *arg) override + { return do_date_conds_transformation(thd, this); } }; @@ -896,6 +905,8 @@ public: Item *negated_item(THD *thd) override; Item *get_copy(THD *thd) override { return get_item_copy<Item_func_lt>(thd, this); } + Item* date_conds_transformer(THD *thd, uchar *arg) override + { return do_date_conds_transformation(thd, this); } }; @@ -1582,7 +1593,7 @@ public: { packed_longlong *val= reinterpret_cast<packed_longlong*>(base)+pos; Item_datetime *dt= static_cast<Item_datetime*>(item); - dt->set(val->val, type_handler()->mysql_timestamp_type()); + dt->set_from_packed(val->val, type_handler()->mysql_timestamp_type()); } friend int cmp_longlong(void *cmp_arg, packed_longlong *a,packed_longlong *b); }; @@ -3038,6 +3049,7 @@ public: bool is_const() const { return m_is_const; } void set_const(bool arg) { m_is_const= arg; } CHARSET_INFO * library_charset() const { return m_library_charset; } + void unset_flag(int flag) { m_library_flags&= ~flag; } }; diff --git a/sql/item_create.cc b/sql/item_create.cc index 704d86d0ec3..64cb79da31a 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -1352,6 +1352,18 @@ protected: virtual ~Create_func_json_overlaps() {} }; +class Create_func_json_schema_valid: public Create_func_arg2 +{ +public: + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); + + static Create_func_json_schema_valid s_singleton; + +protected: + Create_func_json_schema_valid() {} + virtual ~Create_func_json_schema_valid() {} +}; + class Create_func_last_day : public Create_func_arg1 { @@ -4413,6 +4425,15 @@ Create_func_last_insert_id::create_native(THD *thd, const LEX_CSTRING *name, return func; } +Create_func_json_schema_valid Create_func_json_schema_valid::s_singleton; + +Item* +Create_func_json_schema_valid::create_2_arg(THD *thd, Item *arg1, Item *arg2) +{ + status_var_increment(thd->status_var.feature_json); + return new (thd->mem_root) Item_func_json_schema_valid(thd, arg1, arg2); +} + Create_func_lcase Create_func_lcase::s_singleton; @@ -5824,6 +5845,7 @@ Native_func_registry func_array[] = { { STRING_WITH_LEN("JSON_OVERLAPS") }, BUILDER(Create_func_json_overlaps)}, { { STRING_WITH_LEN("JSON_REMOVE") }, BUILDER(Create_func_json_remove)}, { { STRING_WITH_LEN("JSON_REPLACE") }, BUILDER(Create_func_json_replace)}, + { { STRING_WITH_LEN("JSON_SCHEMA_VALID") }, BUILDER(Create_func_json_schema_valid)}, { { STRING_WITH_LEN("JSON_SET") }, BUILDER(Create_func_json_set)}, { { STRING_WITH_LEN("JSON_SEARCH") }, BUILDER(Create_func_json_search)}, { { STRING_WITH_LEN("JSON_TYPE") }, BUILDER(Create_func_json_type)}, diff --git a/sql/item_func.cc b/sql/item_func.cc index a94dcefe32f..61b3304a2b6 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -277,7 +277,6 @@ bool Item_func::check_argument_types_scalar(uint start, uint end) const return false; } - /* Resolve references to table column for a function and its argument @@ -362,6 +361,7 @@ Item_func::fix_fields(THD *thd, Item **ref) if (fix_length_and_dec(thd)) return TRUE; base_flags|= item_base_t::FIXED; + return FALSE; } diff --git a/sql/item_func.h b/sql/item_func.h index 6e714814526..dcb04a62727 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -78,6 +78,7 @@ public: JSON_EXTRACT_FUNC, JSON_VALID_FUNC, ROWNUM_FUNC, CASE_SEARCHED_FUNC, // Used by ColumnStore/Spider CASE_SIMPLE_FUNC, // Used by ColumnStore/spider, + DATE_FUNC, YEAR_FUNC }; static scalar_comparison_op functype_to_scalar_comparison_op(Functype type) { diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 590fde88a52..fa0a8cbec7f 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -19,21 +19,7 @@ #include "sql_class.h" #include "item.h" #include "sql_parse.h" // For check_stack_overrun - -/* - Allocating memory and *also* using it (reading and - writing from it) because some build instructions cause - compiler to optimize out stack_used_up. Since alloca() - here depends on stack_used_up, it doesnt get executed - correctly and causes json_debug_nonembedded to fail - ( --error ER_STACK_OVERRUN_NEED_MORE does not occur). -*/ -#define ALLOCATE_MEM_ON_STACK(A) do \ - { \ - uchar *array= (uchar*)alloca(A); \ - bzero(array, A); \ - my_checksum(0, array, A); \ - } while(0) +#include "json_schema_helper.h" /* Compare ASCII string against the string with the specified @@ -4736,3 +4722,128 @@ bool Item_func_json_overlaps::fix_length_and_dec(THD *thd) return Item_bool_func::fix_length_and_dec(thd); } + +longlong Item_func_json_schema_valid::val_int() +{ + json_engine_t ve; + int is_valid= 1; + + if (!schema_parsed) + { + null_value= 1; + return 0; + } + + val= args[1]->val_json(&tmp_val); + + if (!val) + { + null_value= 1; + return 0; + } + null_value= 0; + + if (!val->length()) + return 1; + + json_scan_start(&ve, val->charset(), (const uchar *) val->ptr(), + (const uchar *) val->end()); + + if (json_read_value(&ve)) + goto end; + + if (!keyword_list.is_empty()) + { + List_iterator <Json_schema_keyword> it(keyword_list);; + Json_schema_keyword* curr_keyword= NULL; + while ((curr_keyword=it++)) + { + if (curr_keyword->validate(&ve, NULL, NULL)) + { + is_valid= 0; + break; + } + } + } + + if (is_valid && !ve.s.error && !json_scan_ended(&ve)) + { + while (json_scan_next(&ve) == 0) /* no-op */; + } + +end: + if (unlikely(ve.s.error)) + { + is_valid= 0; + report_json_error(val, &ve, 1); + } + + return is_valid; +} + +/* +Idea behind implementation: +JSON schema basically has same structure as that of json object, consisting of +key-value pairs. So it can be parsed in the same manner as any json object. + +However, none of the keywords are mandatory, so making guess about the json value +type based only on the keywords would be incorrect. Hence we need separate objects +denoting each keyword. + +So during create_object_and_handle_keyword() we create appropriate objects +based on the keywords and validate each of them individually on the json +document by calling respective validate() function if the type matches. +If any of them fails, return false, else return true. +*/ +bool Item_func_json_schema_valid::fix_length_and_dec(THD *thd) +{ + json_engine_t je; + bool res= 0; + + String *js= args[0]->val_json(&tmp_js); + + if ((null_value= args[0]->null_value)) + { + null_value= 1; + return 0; + } + json_scan_start(&je, js->charset(), (const uchar *) js->ptr(), + (const uchar *) js->ptr() + js->length()); + if (!create_object_and_handle_keyword(thd, &je, &keyword_list, + &all_keywords)) + schema_parsed= true; + else + schema_parsed= false; + + /* + create_object_and_handle_keyword fails when either the json value for + keyword is invalid or when there is syntax error. Return NULL in both + these cases. + */ + if (!schema_parsed) + { + if (je.s.error) + report_json_error(js, &je, 0); + set_maybe_null(); + } + + return res || Item_bool_func::fix_length_and_dec(thd); +} + +void Item_func_json_schema_valid::cleanup() +{ + DBUG_ENTER("Item_func_json_schema_valid::cleanup"); + Item_bool_func::cleanup(); + + List_iterator<Json_schema_keyword> it2(all_keywords); + Json_schema_keyword *curr_schema; + while ((curr_schema= it2++)) + { + delete curr_schema; + curr_schema= nullptr; + } + all_keywords.empty(); + keyword_list.empty(); + + DBUG_VOID_RETURN; +} diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h index 6f6b6a7afe8..17ffe943938 100644 --- a/sql/item_jsonfunc.h +++ b/sql/item_jsonfunc.h @@ -25,6 +25,7 @@ #include "item_strfunc.h" // Item_str_func #include "item_sum.h" #include "sql_type_json.h" +#include "json_schema.h" class json_path_with_flags { @@ -784,7 +785,8 @@ class Item_func_json_overlaps: public Item_bool_func String tmp_val, *val; public: Item_func_json_overlaps(THD *thd, Item *a, Item *b): - Item_bool_func(thd, a, b) {} + Item_bool_func(thd, a, b) + {} LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("json_overlaps") }; @@ -796,4 +798,32 @@ public: { return get_item_copy<Item_func_json_overlaps>(thd, this); } }; +class Item_func_json_schema_valid: public Item_bool_func +{ + String tmp_js; + bool schema_parsed; + String tmp_val, *val; + List<Json_schema_keyword> keyword_list; + List<Json_schema_keyword> all_keywords; + +public: + Item_func_json_schema_valid(THD *thd, Item *a, Item *b): + Item_bool_func(thd, a, b) + { + val= NULL; + schema_parsed= false; + set_maybe_null(); + } + LEX_CSTRING func_name_cstring() const override + { + static LEX_CSTRING name= {STRING_WITH_LEN("json_schema_valid") }; + return name; + } + bool fix_length_and_dec(THD *thd) override; + longlong val_int() override; + Item *get_copy(THD *thd) override + { return get_item_copy<Item_func_json_schema_valid>(thd, this); } + void cleanup() override; +}; + #endif /* ITEM_JSONFUNC_INCLUDED */ diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 511f0428a1f..e614421030a 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -2953,7 +2953,9 @@ bool Item_exists_subselect::select_prepare_to_be_in() if (!optimizer && (thd->lex->sql_command == SQLCOM_SELECT || thd->lex->sql_command == SQLCOM_UPDATE_MULTI || - thd->lex->sql_command == SQLCOM_DELETE_MULTI) && + thd->lex->sql_command == SQLCOM_DELETE_MULTI || + thd->lex->sql_command == SQLCOM_UPDATE || + thd->lex->sql_command == SQLCOM_DELETE) && !unit->first_select()->is_part_of_union() && optimizer_flag(thd, OPTIMIZER_SWITCH_EXISTS_TO_IN) && (is_top_level_item() || diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index a5f6d9307c6..953984e4c72 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -462,6 +462,7 @@ public: static LEX_CSTRING name= {STRING_WITH_LEN("year") }; return name; } + enum Functype functype() const override { return YEAR_FUNC; } enum_monotonicity_info get_monotonicity_info() const override; longlong val_int_endpoint(bool left_endp, bool *incl_endp) override; bool fix_length_and_dec(THD *thd) override @@ -1334,6 +1335,7 @@ public: { print_cast_temporal(str, query_type); } + enum Functype functype() const override { return DATE_FUNC; } bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override; bool fix_length_and_dec(THD *thd) override { @@ -2025,6 +2027,4 @@ public: return false; } }; - - #endif /* ITEM_TIMEFUNC_INCLUDED */ diff --git a/sql/json_schema.cc b/sql/json_schema.cc new file mode 100644 index 00000000000..8f818abc9bb --- /dev/null +++ b/sql/json_schema.cc @@ -0,0 +1,2874 @@ +/* Copyright (c) 2016, 2022, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software 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-1301 USA */ + + +#include "mariadb.h" +#include "sql_class.h" +#include "sql_parse.h" // For check_stack_overrun +#include <m_string.h> +#include "json_schema.h" +#include "json_schema_helper.h" +#include "pcre2.h" +static HASH all_keywords_hash; + +static Json_schema_keyword *create_json_schema_keyword(THD *thd) +{ + return new (thd->mem_root) Json_schema_keyword(); +} +static Json_schema_keyword *create_json_schema_type(THD *thd) +{ + return new (thd->mem_root) Json_schema_type(); +} +static Json_schema_keyword *create_json_schema_enum(THD *thd) +{ + return new (thd->mem_root) Json_schema_enum(); +} +static Json_schema_keyword *create_json_schema_const(THD *thd) +{ + return new (thd->mem_root) Json_schema_const(); +} +static Json_schema_keyword *create_json_schema_maximum(THD *thd) +{ + return new (thd->mem_root) Json_schema_maximum(); +} +static Json_schema_keyword *create_json_schema_minimum(THD *thd) +{ + return new (thd->mem_root) Json_schema_minimum(); +} +static Json_schema_keyword *create_json_schema_ex_max(THD *thd) +{ + return new (thd->mem_root) Json_schema_ex_maximum(); +} +static Json_schema_keyword *create_json_schema_ex_min(THD *thd) +{ + return new (thd->mem_root) Json_schema_ex_minimum(); +} +static Json_schema_keyword *create_json_schema_multiple_of(THD *thd) +{ + return new (thd->mem_root) Json_schema_multiple_of(); +} +static Json_schema_keyword *create_json_schema_max_len(THD *thd) +{ + return new (thd->mem_root) Json_schema_max_len(); +} +static Json_schema_keyword *create_json_schema_min_len(THD *thd) +{ + return new (thd->mem_root) Json_schema_min_len(); +} +static Json_schema_keyword *create_json_schema_pattern(THD *thd) +{ + return new (thd->mem_root) Json_schema_pattern(); +} +static Json_schema_keyword *create_json_schema_items(THD *thd) +{ + return new (thd->mem_root) Json_schema_items(); +} +static Json_schema_keyword *create_json_schema_max_items(THD *thd) +{ + return new (thd->mem_root) Json_schema_max_items(); +} +static Json_schema_keyword *create_json_schema_min_items(THD *thd) +{ + return new (thd->mem_root) Json_schema_min_items(); +} +static Json_schema_keyword *create_json_schema_prefix_items(THD *thd) +{ + return new (thd->mem_root) Json_schema_prefix_items(); +} +static Json_schema_keyword *create_json_schema_contains(THD *thd) +{ + return new (thd->mem_root) Json_schema_contains(); +} +static Json_schema_keyword *create_json_schema_max_contains(THD *thd) +{ + return new (thd->mem_root) Json_schema_max_contains(); +} +static Json_schema_keyword *create_json_schema_min_contains(THD *thd) +{ + return new (thd->mem_root) Json_schema_min_contains(); +} +static Json_schema_keyword *create_json_schema_unique_items(THD *thd) +{ + return new (thd->mem_root) Json_schema_unique_items(); +} +static Json_schema_keyword *create_json_schema_additional_items(THD *thd) +{ + return new (thd->mem_root) Json_schema_additional_items(); +} +static Json_schema_keyword *create_json_schema_unevaluated_items(THD *thd) +{ + return new (thd->mem_root) Json_schema_unevaluated_items(); +} +static Json_schema_keyword *create_json_schema_properties(THD *thd) +{ + return new (thd->mem_root) Json_schema_properties(); +} +static Json_schema_keyword *create_json_schema_pattern_properties(THD *thd) +{ + return new (thd->mem_root) Json_schema_pattern_properties(); +} +static Json_schema_keyword *create_json_schema_additional_properties(THD *thd) +{ + return new (thd->mem_root) Json_schema_additional_properties(); +} +static Json_schema_keyword *create_json_schema_unevaluated_properties(THD *thd) +{ + return new (thd->mem_root) Json_schema_unevaluated_properties(); +} +static Json_schema_keyword *create_json_schema_property_names(THD *thd) +{ + return new (thd->mem_root) Json_schema_property_names(); +} +static Json_schema_keyword *create_json_schema_max_prop(THD *thd) +{ + return new (thd->mem_root) Json_schema_max_prop(); +} +static Json_schema_keyword *create_json_schema_min_prop(THD *thd) +{ + return new (thd->mem_root) Json_schema_min_prop(); +} +static Json_schema_keyword *create_json_schema_required(THD *thd) +{ + return new (thd->mem_root) Json_schema_required(); +} +static Json_schema_keyword *create_json_schema_dependent_required(THD *thd) +{ + return new (thd->mem_root) Json_schema_dependent_required(); +} +static Json_schema_keyword *create_json_schema_dependent_schemas(THD *thd) +{ + return new (thd->mem_root) Json_schema_dependent_schemas(); +} +static Json_schema_keyword *create_json_schema_not(THD *thd) +{ + return new (thd->mem_root) Json_schema_not(); +} +static Json_schema_keyword *create_json_schema_all_of(THD *thd) +{ + return new (thd->mem_root) Json_schema_all_of(); +} +static Json_schema_keyword *create_json_schema_any_of(THD *thd) +{ + return new (thd->mem_root) Json_schema_any_of(); +} +static Json_schema_keyword *create_json_schema_one_of(THD *thd) +{ + return new (thd->mem_root) Json_schema_one_of(); +} +static Json_schema_keyword *create_json_schema_if(THD *thd) +{ + return new (thd->mem_root) Json_schema_if(); +} +static Json_schema_keyword *create_json_schema_then(THD *thd) +{ + return new (thd->mem_root) Json_schema_then(); +} +static Json_schema_keyword *create_json_schema_else(THD *thd) +{ + return new (thd->mem_root) Json_schema_else(); +} +static Json_schema_keyword *create_json_schema_annotation(THD *thd) +{ + return new (thd->mem_root) Json_schema_annotation(); +} +static Json_schema_keyword *create_json_schema_format(THD *thd) +{ + return new (thd->mem_root) Json_schema_format(); +} +static Json_schema_keyword *create_json_schema_media_string(THD *thd) +{ + return new (thd->mem_root) Json_schema_media_string(); +} +static Json_schema_keyword *create_json_schema_reference(THD *thd) +{ + return new (thd->mem_root) Json_schema_reference(); +} + + static st_json_schema_keyword_map json_schema_func_array[]= +{ + {{ STRING_WITH_LEN("type") }, create_json_schema_type, JSON_SCHEMA_COMMON_KEYWORD}, + {{ STRING_WITH_LEN("const") }, create_json_schema_const, JSON_SCHEMA_COMMON_KEYWORD}, + {{ STRING_WITH_LEN("enum") }, create_json_schema_enum, JSON_SCHEMA_COMMON_KEYWORD}, + + {{ STRING_WITH_LEN("maximum") }, create_json_schema_maximum, JSON_SCHEMA_NUMBER_KEYWORD}, + {{ STRING_WITH_LEN("minimum") }, create_json_schema_minimum, JSON_SCHEMA_NUMBER_KEYWORD}, + {{ STRING_WITH_LEN("exclusiveMaximum") }, create_json_schema_ex_max, JSON_SCHEMA_NUMBER_KEYWORD}, + {{ STRING_WITH_LEN("exclusiveMinimum") }, create_json_schema_ex_min, JSON_SCHEMA_NUMBER_KEYWORD}, + {{ STRING_WITH_LEN("multipleOf") }, create_json_schema_multiple_of, JSON_SCHEMA_NUMBER_KEYWORD}, + + {{ STRING_WITH_LEN("maxLength") }, create_json_schema_max_len, JSON_SCHEMA_STRING_KEYWORD}, + {{ STRING_WITH_LEN("minLength") }, create_json_schema_min_len, JSON_SCHEMA_STRING_KEYWORD}, + {{ STRING_WITH_LEN("pattern") }, create_json_schema_pattern, JSON_SCHEMA_STRING_KEYWORD}, + + {{ STRING_WITH_LEN("items") }, create_json_schema_items, JSON_SCHEMA_ARRAY_KEYWORD}, + {{ STRING_WITH_LEN("maxItems") }, create_json_schema_max_items, JSON_SCHEMA_ARRAY_KEYWORD}, + {{ STRING_WITH_LEN("minItems") }, create_json_schema_min_items, JSON_SCHEMA_ARRAY_KEYWORD}, + {{ STRING_WITH_LEN("additionalItems") }, create_json_schema_additional_items, JSON_SCHEMA_ARRAY_KEYWORD}, + {{ STRING_WITH_LEN("unevaluatedItems") }, create_json_schema_unevaluated_items, JSON_SCHEMA_ARRAY_KEYWORD}, + {{ STRING_WITH_LEN("prefixItems") }, create_json_schema_prefix_items, JSON_SCHEMA_ARRAY_KEYWORD}, + {{ STRING_WITH_LEN("uniqueItems") }, create_json_schema_unique_items, JSON_SCHEMA_ARRAY_KEYWORD}, + {{ STRING_WITH_LEN("contains") }, create_json_schema_contains, JSON_SCHEMA_ARRAY_KEYWORD}, + {{ STRING_WITH_LEN("maxContains") }, create_json_schema_max_contains, JSON_SCHEMA_ARRAY_KEYWORD}, + {{ STRING_WITH_LEN("minContains") }, create_json_schema_min_contains, JSON_SCHEMA_ARRAY_KEYWORD}, + + {{ STRING_WITH_LEN("properties") }, create_json_schema_properties, JSON_SCHEMA_OBJECT_KEYWORD}, + {{ STRING_WITH_LEN("patternProperties") }, create_json_schema_pattern_properties, JSON_SCHEMA_OBJECT_KEYWORD}, + {{ STRING_WITH_LEN("propertyNames") }, create_json_schema_property_names, JSON_SCHEMA_OBJECT_KEYWORD}, + {{ STRING_WITH_LEN("maxProperties") }, create_json_schema_max_prop, JSON_SCHEMA_OBJECT_KEYWORD}, + {{ STRING_WITH_LEN("minProperties") }, create_json_schema_min_prop, JSON_SCHEMA_OBJECT_KEYWORD}, + {{ STRING_WITH_LEN("dependentRequired") }, create_json_schema_dependent_required, JSON_SCHEMA_OBJECT_KEYWORD}, + {{ STRING_WITH_LEN("dependentSchemas") }, create_json_schema_dependent_schemas, JSON_SCHEMA_OBJECT_KEYWORD}, + {{ STRING_WITH_LEN("required") }, create_json_schema_required, JSON_SCHEMA_OBJECT_KEYWORD}, + {{ STRING_WITH_LEN("additionalProperties") }, create_json_schema_additional_properties, JSON_SCHEMA_OBJECT_KEYWORD}, + {{ STRING_WITH_LEN("unevaluatedProperties") }, create_json_schema_unevaluated_properties, JSON_SCHEMA_OBJECT_KEYWORD}, + + {{ STRING_WITH_LEN("not") }, create_json_schema_not, JSON_SCHEMA_LOGIC_KEYWORD}, + {{ STRING_WITH_LEN("allOf") }, create_json_schema_all_of, JSON_SCHEMA_LOGIC_KEYWORD}, + {{ STRING_WITH_LEN("anyOf") }, create_json_schema_any_of, JSON_SCHEMA_LOGIC_KEYWORD}, + {{ STRING_WITH_LEN("oneOf") }, create_json_schema_one_of, JSON_SCHEMA_LOGIC_KEYWORD}, + + {{ STRING_WITH_LEN("if") }, create_json_schema_if, JSON_SCHEMA_CONDITION_KEYWORD}, + {{ STRING_WITH_LEN("then") }, create_json_schema_then, JSON_SCHEMA_CONDITION_KEYWORD}, + {{ STRING_WITH_LEN("else") }, create_json_schema_else, JSON_SCHEMA_CONDITION_KEYWORD}, + + {{ STRING_WITH_LEN("title") }, create_json_schema_annotation, JSON_SCHEMA_ANNOTATION_KEYWORD}, + {{ STRING_WITH_LEN("description") }, create_json_schema_annotation, JSON_SCHEMA_ANNOTATION_KEYWORD}, + {{ STRING_WITH_LEN("comment") }, create_json_schema_annotation, JSON_SCHEMA_ANNOTATION_KEYWORD}, + {{ STRING_WITH_LEN("$schema") }, create_json_schema_annotation, JSON_SCHEMA_ANNOTATION_KEYWORD}, + {{ STRING_WITH_LEN("deprecated") }, create_json_schema_annotation, JSON_SCHEMA_ANNOTATION_KEYWORD}, + {{ STRING_WITH_LEN("readOnly") }, create_json_schema_annotation, JSON_SCHEMA_ANNOTATION_KEYWORD}, + {{ STRING_WITH_LEN("writeOnly") }, create_json_schema_annotation, JSON_SCHEMA_ANNOTATION_KEYWORD}, + {{ STRING_WITH_LEN("example") }, create_json_schema_annotation, JSON_SCHEMA_ANNOTATION_KEYWORD}, + {{ STRING_WITH_LEN("default") }, create_json_schema_annotation, JSON_SCHEMA_ANNOTATION_KEYWORD}, + {{ STRING_WITH_LEN("$vocabulary") }, create_json_schema_annotation, JSON_SCHEMA_ANNOTATION_KEYWORD}, + + {{ STRING_WITH_LEN("date-time") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("date") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("time") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("duration") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("email") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("idn-email") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("hostname") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("idn-hostname") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("ipv4") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("ipv6") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("uri") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("uri-reference") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("iri") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("iri-reference") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("uuid") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("json-pointer") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("relative-json-pointer") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + {{ STRING_WITH_LEN("regex") }, create_json_schema_format, JSON_SCHEMA_FORMAT_KEYWORD}, + + {{ STRING_WITH_LEN("contentMediaType") }, create_json_schema_media_string, JSON_SCHEMA_MEDIA_KEYWORD}, + {{ STRING_WITH_LEN("conentEncoding") }, create_json_schema_media_string, JSON_SCHEMA_MEDIA_KEYWORD}, + {{ STRING_WITH_LEN("contentSchema") }, create_json_schema_media_string, JSON_SCHEMA_MEDIA_KEYWORD}, + + {{ STRING_WITH_LEN("$ref") }, create_json_schema_reference, JSON_SCHEMA_REFERENCE_KEYWORD}, + {{ STRING_WITH_LEN("$id") }, create_json_schema_reference, JSON_SCHEMA_REFERENCE_KEYWORD}, + {{ STRING_WITH_LEN("$anchor") }, create_json_schema_reference, JSON_SCHEMA_REFERENCE_KEYWORD}, + {{ STRING_WITH_LEN("$defs") }, create_json_schema_reference, JSON_SCHEMA_REFERENCE_KEYWORD}, + {{ STRING_WITH_LEN("$dynamicRef") }, create_json_schema_reference, JSON_SCHEMA_REFERENCE_KEYWORD}, + {{ STRING_WITH_LEN("$dynamicAnchor") }, create_json_schema_reference, JSON_SCHEMA_REFERENCE_KEYWORD}, +}; + +static st_json_schema_keyword_map empty_func_map= + {{ STRING_WITH_LEN("") }, create_json_schema_keyword, JSON_SCHEMA_EMPTY_KEYWORD}; + +/* + When some schemas dont validate, we want to check the annotation + for an alternate schema. Example, when we have "properties" and + "patternProperties", if "properties" does not validate for a certain + keyname, then we want to check if it validates for "patternProperties". + In this case "patterProperties" will be alternate schema for "properties". +*/ +bool Json_schema_keyword::fall_back_on_alternate_schema(const json_engine_t + *je, + const uchar* k_start, + const uchar* k_end) +{ + if (alternate_schema) + { + if (alternate_schema->allowed) + { + if (alternate_schema->validate_as_alternate(je, k_start, k_end)) + return true; + } + else + return true; + } + return false; +} + +bool Json_schema_annotation::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + bool is_invalid_value_type= false, res= false; + + if (this->keyword_map == &(json_schema_func_array[38]) || + this->keyword_map == &(json_schema_func_array[39]) || + this->keyword_map == &(json_schema_func_array[40]) || + this->keyword_map == &(json_schema_func_array[41])) + { + if (je->value_type != JSON_VALUE_STRING) + is_invalid_value_type= true; + } + else if (this->keyword_map == &(json_schema_func_array[42]) || + this->keyword_map == &(json_schema_func_array[43]) || + this->keyword_map == &(json_schema_func_array[44])) + { + if (je->value_type != JSON_VALUE_TRUE && + je->value_type != JSON_VALUE_FALSE) + is_invalid_value_type= true; + } + else if (this->keyword_map == &(json_schema_func_array[45])) + { + if (je->value_type != JSON_VALUE_ARRAY) + is_invalid_value_type= true; + if (json_skip_level(je)) + return true; + } + else if (this->keyword_map == &(json_schema_func_array[46])) + return false; + + if (is_invalid_value_type) + { + res= true; + String keyword(0); + keyword.append((const char*)key_start, (int)(key_end-key_start)); + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), keyword.ptr()); + } + return res; +} + +bool Json_schema_format::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + if (je->value_type != JSON_VALUE_STRING) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "format"); + } + return false; +} + +bool Json_schema_type::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + return !((1 << je->value_type) & type); +} + +bool Json_schema_type::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + if (je->value_type == JSON_VALUE_ARRAY) + { + int level= je->stack_p; + while (json_scan_next(je)==0 && je->stack_p >= level) + { + if (json_read_value(je)) + return true; + json_assign_type(&type, je); + } + return je->s.error ? true : false; + } + else if (je->value_type == JSON_VALUE_STRING) + { + return json_assign_type(&type, je); + } + else + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "type"); + return true; + } +} + +bool Json_schema_const::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + json_engine_t curr_je; + curr_je= *je; + const char *start= (char*)curr_je.value; + const char *end= (char*)curr_je.value+curr_je.value_len; + json_engine_t temp_je= *je; + json_engine_t temp_je_2; + String a_res("", 0, curr_je.s.cs); + int err= 0; + + if (type != curr_je.value_type) + return true; + + if (curr_je.value_type <= JSON_VALUE_NUMBER) + { + if (!json_value_scalar(&temp_je)) + { + if (json_skip_level(&temp_je)) + { + curr_je= temp_je; + return true; + } + end= (char*)temp_je.s.c_str; + } + String val((char*)temp_je.value, end-start, temp_je.s.cs); + + json_scan_start(&temp_je_2, temp_je.s.cs, (const uchar *) val.ptr(), + (const uchar *) val.end()); + + if (temp_je.value_type != JSON_VALUE_STRING) + { + if (json_read_value(&temp_je_2)) + { + curr_je= temp_je; + return true; + } + json_get_normalized_string(&temp_je_2, &a_res, &err); + if (err) + return true; + } + else + a_res.append(val.ptr(), val.length(), temp_je.s.cs); + + if (a_res.length() == strlen(const_json_value) && + !strncmp((const char*)const_json_value, a_res.ptr(), + a_res.length())) + return false; + return true; + } + return false; +} + +bool Json_schema_const::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + const char *start= (char*)je->value, *end= (char*)je->value+je->value_len; + json_engine_t temp_je; + String a_res("", 0, je->s.cs); + int err; + + type= je->value_type; + + if (!json_value_scalar(je)) + { + if (json_skip_level(je)) + return true; + end= (char*)je->s.c_str; + } + + String val((char*)je->value, end-start, je->s.cs); + + json_scan_start(&temp_je, je->s.cs, (const uchar *) val.ptr(), + (const uchar *) val.end()); + if (je->value_type != JSON_VALUE_STRING) + { + if (json_read_value(&temp_je)) + return true; + json_get_normalized_string(&temp_je, &a_res, &err); + if (err) + return true; + } + else + a_res.append(val.ptr(), val.length(), je->s.cs); + + this->const_json_value= (char*)alloc_root(thd->mem_root, + a_res.length()+1); + if (!const_json_value) + return true; + + const_json_value[a_res.length()]= '\0'; + strncpy(const_json_value, (const char*)a_res.ptr(), a_res.length()); + + return false; +} + +bool Json_schema_enum::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + json_engine_t temp_je; + temp_je= *je; + + String norm_str((char*)"",0, je->s.cs); + + String a_res("", 0, je->s.cs); + int err= 1; + + if (temp_je.value_type > JSON_VALUE_NUMBER) + { + if (!(enum_scalar & (1 << temp_je.value_type))) + return true; + else + return false; + } + json_get_normalized_string(&temp_je, &a_res, &err); + if (err) + return true; + + norm_str.append((const char*)a_res.ptr(), a_res.length(), je->s.cs); + + if (my_hash_search(&this->enum_values, (const uchar*)(norm_str.ptr()), + strlen((const char*)(norm_str.ptr())))) + return false; + else + return true; +} + +bool Json_schema_enum::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + int count= 0; + if (my_hash_init(PSI_INSTRUMENT_ME, + &this->enum_values, + je->s.cs, 1024, 0, 0, (my_hash_get_key) get_key_name, + NULL, 0)) + return true; + + if (je->value_type == JSON_VALUE_ARRAY) + { + int curr_level= je->stack_p; + while(json_scan_next(je) == 0 && curr_level <= je->stack_p) + { + if (json_read_value(je)) + return true; + count++; + if (je->value_type > JSON_VALUE_NUMBER) + { + if (!(enum_scalar & (1 << je->value_type))) + enum_scalar|= 1 << je->value_type; + else + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "enum"); + return true; + } + } + else + { + char *norm_str; + int err= 1; + String a_res("", 0, je->s.cs); + + json_get_normalized_string(je, &a_res, &err); + if (err) + return true; + + norm_str= (char*)alloc_root(thd->mem_root, + a_res.length()+1); + if (!norm_str) + return true; + else + { + norm_str[a_res.length()]= '\0'; + strncpy(norm_str, (const char*)a_res.ptr(), a_res.length()); + if (!my_hash_search(&this->enum_values, (uchar*)norm_str, + strlen(norm_str))) + { + if (my_hash_insert(&this->enum_values, (uchar*)norm_str)) + return true; + } + else + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "enum"); + return true; + } + } + } + } + if (!count) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "enum"); + return true; + } + return false; + } + else + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "enum"); + return true; + } +} + +bool Json_schema_maximum::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + return false; + + double val= je->s.cs->strntod((char *) je->value, + je->value_len, &end, &err); + return (val <= value) ? false : true; +} + +bool Json_schema_maximum::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "maximum"); + return true; + } + + double val= je->s.cs->strntod((char *) je->value, + je->value_len, &end, &err); + value= val; + + return false; +} + +bool Json_schema_minimum::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + return false; + + double val= je->s.cs->strntod((char *) je->value, + je->value_len, &end, &err); + return val >= value ? false : true; +} + +bool Json_schema_minimum::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "minimum"); + return true; + } + + double val= je->s.cs->strntod((char *) je->value, + je->value_len, &end, &err); + value= val; + + return false; +} + +bool Json_schema_ex_minimum::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + return false; + + double val= je->s.cs->strntod((char *) je->value, + je->value_len, &end, &err); + return (val > value) ? false : true; +} + +bool Json_schema_ex_minimum::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "exclusiveMinimum"); + return true; + } + + double val= je->s.cs->strntod((char *) je->value, + je->value_len, &end, &err); + value= val; + + return false; +} + +bool Json_schema_ex_maximum::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + return false; + + double val= je->s.cs->strntod((char *) je->value, + je->value_len, &end, &err); + return (val < value) ? false : true; +} + +bool Json_schema_ex_maximum::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "exclusiveMaximum"); + return true; + } + double val= je->s.cs->strntod((char *) je->value, + je->value_len, &end, &err); + value= val; + + return false; +} + +bool Json_schema_multiple_of::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + return false; + if (je->num_flags & JSON_NUM_FRAC_PART) + return true; + + longlong val= je->s.cs->strntoll((char *) je->value, + je->value_len, 10, &end, &err); + + return val % multiple_of; +} + +bool Json_schema_multiple_of::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER || (je->num_flags & JSON_NUM_FRAC_PART)) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "multipleOf"); + return true; + } + + longlong val= je->s.cs->strntoll((char *) je->value, + je->value_len, 10, &end, &err); + if (val <= 0) + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "multipleOf"); + multiple_of= val; + + return false; +} + + +bool Json_schema_max_len::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + if (je->value_type != JSON_VALUE_STRING) + return false; + return (uint)(je->value_len) <= value ? false : true; +} + +bool Json_schema_max_len::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "maxLength"); + return true; + } + double val= je->s.cs->strntod((char *) je->value, + je->value_len, &end, &err); + if (val < 0) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "maxLength"); + return true; + } + value= (int)val; + + return false; +} + +bool Json_schema_min_len::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + if (je->value_type != JSON_VALUE_STRING) + return false; + return (uint)(je->value_len) >= value ? false : true; +} + +bool Json_schema_min_len::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "minLength"); + return true; + } + + double val= je->s.cs->strntod((char *) je->value, + je->value_len, &end, &err); + if (val < 0) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "minLength"); + return true; + } + value= (int)val; + + return false; +} + +bool Json_schema_pattern::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + bool pattern_matches= false; + + /* + We want to match a single pattern against multiple + string when (see below): + 1) with "pattern" when there are different json strings + to be validated against one pattern. + 2) with "propertyNames", where there is one pattern but + multiple property names to be validated against one + pattern + */ + if (!k_start && !k_end) + { + /* 1) */ + if (je->value_type != JSON_VALUE_STRING) + return false; + str->str_value.set_or_copy_aligned((const char*)je->value, + (size_t)je->value_len, je->s.cs); + } + else + { + /* 2) */ + str->str_value.set_or_copy_aligned((const char*)k_start, + (size_t)(k_end-k_start), je->s.cs); + } + if (re.recompile(pattern)) + return true; + if (re.exec(str, 0, 0)) + return true; + pattern_matches= re.match(); + + return pattern_matches ? false : true; +} + +bool Json_schema_pattern::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + if (je->value_type != JSON_VALUE_STRING) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "pattern"); + return true; + } + + my_repertoire_t repertoire= my_charset_repertoire(je->s.cs); + pattern= thd->make_string_literal((const char*)je->value, + je->value_len, repertoire); + str= new (thd->mem_root) Item_string(thd, "", (uint) 0, je->s.cs); + re.init(je->s.cs, 0); + re.unset_flag(PCRE2_CASELESS); + + return false; +} + +bool Json_schema_max_items::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + uint count= 0; + json_engine_t curr_je; + + curr_je= *je; + + if (curr_je.value_type != JSON_VALUE_ARRAY) + return false; + + int level= curr_je.stack_p; + while(json_scan_next(&curr_je)==0 && level <= curr_je.stack_p) + { + if (json_read_value(&curr_je)) + return true; + count++; + if (!json_value_scalar(&curr_je)) + { + if (json_skip_level(&curr_je)) + return true; + } + } + return count > value ? true : false; +} + +bool Json_schema_max_items::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "maxItems"); + return true; + } + + double val= je->s.cs->strntod((char *) je->value, + je->value_len, &end, &err); + if (val < 0) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "maxItems"); + return true; + } + value= (int)val; + + return false; +} + +bool Json_schema_min_items::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + uint count= 0; + json_engine_t curr_je; + + curr_je= *je; + + if (curr_je.value_type != JSON_VALUE_ARRAY) + return false; + + int level= curr_je.stack_p; + while(json_scan_next(&curr_je)==0 && level <= curr_je.stack_p) + { + if (json_read_value(&curr_je)) + return true; + count++; + if (!json_value_scalar(&curr_je)) + { + if (json_skip_level(&curr_je)) + return true; + } + } + return count < value ? true : false; +} + +bool Json_schema_min_items::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "minItems"); + return true; + } + + double val= je->s.cs->strntod((char *) je->value, + je->value_len, &end, &err); + if (val < 0) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "maxLength"); + return true; + } + value= (int)val; + + return false; +} + +bool Json_schema_max_contains::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "maxContains"); + return true; + } + + double val= je->s.cs->strntod((char *) je->value, + je->value_len, &end, &err); + if (val < 0) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "maxContains"); + return true; + } + value= val; + return false; +} + + +bool Json_schema_min_contains::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "minContains"); + return true; + } + + double val= je->s.cs->strntod((char *) je->value, + je->value_len, &end, &err); + value= val; + if (val < 0) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "minContains"); + return true; + } + + return false; +} + + +bool Json_schema_contains::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + uint contains_count=0; + json_engine_t curr_je; curr_je= *je; + int level= je->stack_p; + bool validated= true; + + if (curr_je.value_type != JSON_VALUE_ARRAY) + return false; + + while(json_scan_next(&curr_je)==0 && level <= curr_je.stack_p) + { + if (json_read_value(&curr_je)) + return true; + validated= true; + if (validate_schema_items(&curr_je, &contains)) + validated= false; + if (!json_value_scalar(&curr_je)) + { + if (json_skip_level(&curr_je)) + return true; + } + if (validated) + contains_count++; + } + + if ((max_contains ? contains_count <= max_contains->value : + contains_count>0) && + (min_contains ? contains_count >= min_contains->value : + contains_count>0)) + return false; + + return true; +} + +bool Json_schema_contains::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + if (je->value_type != JSON_VALUE_OBJECT) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "contains"); + return true; + } + return create_object_and_handle_keyword(thd, je, &contains, all_keywords); +} + + +bool Json_schema_items::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + if (je->value_type == JSON_VALUE_FALSE) + { + set_allowed(false); + return false; + } + if (je->value_type == JSON_VALUE_OBJECT) + { + return create_object_and_handle_keyword(thd, je, &items_schema, + all_keywords); + } + else if (je->value_type != JSON_VALUE_TRUE) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "items"); + return true; + } + return false; +} + +bool Json_schema_items::validate_as_alternate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + /* + The indexes in prefix array were less than that in the json array. + So validate remaining using the json schema + */ + return validate_schema_items(je, &items_schema); +} + +bool Json_schema_items::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + + /* + There was no "prefixItesm", so we validate all values in the + array using one schema. + */ + int level= je->stack_p, count=0; + bool is_false= false; + json_engine_t curr_je= *je; + + if (je->value_type != JSON_VALUE_ARRAY) + return false; + + if (!allowed) + is_false= true; + + while (json_scan_next(&curr_je)==0 && level <= curr_je.stack_p) + { + if (json_read_value(&curr_je)) + return true; + count++; + if (validate_schema_items(&curr_je, &items_schema)) + return true; + } + + return is_false ? (!count ? false : true) : false; +} + +bool Json_schema_prefix_items::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + int level= je->stack_p; + json_engine_t curr_je= *je; + List_iterator <List<Json_schema_keyword>> it1 (prefix_items); + List<Json_schema_keyword> *curr_prefix; + + if (curr_je.value_type != JSON_VALUE_ARRAY) + return false; + + while(curr_je.s.c_str < curr_je.s.str_end && json_scan_next(&curr_je)==0 && + curr_je.stack_p >= level) + { + if (json_read_value(&curr_je)) + return true; + if (!(curr_prefix=it1++)) + { + if (fall_back_on_alternate_schema(&curr_je)) + return true; + else + { + if (!json_value_scalar(&curr_je)) + { + if (json_skip_level(&curr_je)) + return true; + } + } + } + else + { + if (validate_schema_items(&curr_je, &(*curr_prefix))) + return true; + if (!json_value_scalar(&curr_je)) + { + if (json_skip_level(&curr_je)) + return true; + } + } + } + return false; +} + +bool Json_schema_prefix_items::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + if (je->value_type != JSON_VALUE_ARRAY) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "prefixItems"); + return true; + } + + int level= je->stack_p; + while(json_scan_next(je)==0 && je->stack_p >= level) + { + json_engine_t temp_je; + char *begin, *end; + int len; + + if (json_read_value(je)) + return true; + if (je->value_type != JSON_VALUE_OBJECT) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "items"); + return true; + } + begin= (char*)je->value; + + if (json_skip_level(je)) + return true; + + end= (char*)je->s.c_str; + len= (int)(end-begin); + + json_scan_start(&temp_je, je->s.cs, (const uchar *) begin, + (const uchar *)begin+len); + List<Json_schema_keyword> *keyword_list= + new (thd->mem_root) List<Json_schema_keyword>; + + if (!keyword_list) + return true; + if (create_object_and_handle_keyword(thd, &temp_je, keyword_list, + all_keywords)) + return true; + + prefix_items.push_back(keyword_list, thd->mem_root); + } + + return false; +} + +bool Json_schema_unique_items::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + HASH unique_items; + List <char> norm_str_list; + json_engine_t curr_je= *je; + int res= true, level= curr_je.stack_p, scalar_val= 0; + + if (curr_je.value_type != JSON_VALUE_ARRAY) + return false; + + if (my_hash_init(PSI_INSTRUMENT_ME, &unique_items, curr_je.s.cs, + 1024, 0, 0, (my_hash_get_key) get_key_name, NULL, 0)) + return true; + + while(json_scan_next(&curr_je)==0 && level <= curr_je.stack_p) + { + int err= 1; + char *norm_str; + String a_res("", 0, curr_je.s.cs); + + if (json_read_value(&curr_je)) + goto end; + + json_get_normalized_string(&curr_je, &a_res, &err); + + if (err) + goto end; + + norm_str= (char*)malloc(a_res.length()+1); + if (!norm_str) + goto end; + + norm_str[a_res.length()]= '\0'; + strncpy(norm_str, (const char*)a_res.ptr(), a_res.length()); + norm_str_list.push_back(norm_str); + + if (curr_je.value_type > JSON_VALUE_NUMBER) + { + if (scalar_val & 1 << curr_je.value_type) + goto end; + scalar_val|= 1 << curr_je.value_type; + } + else + { + if (!my_hash_search(&unique_items, (uchar*)norm_str, + strlen(((const char*)norm_str)))) + { + if (my_hash_insert(&unique_items, (uchar*)norm_str)) + goto end; + } + else + goto end; + } + a_res.set("", 0, curr_je.s.cs); + } + + res= false; + + end: + if (!norm_str_list.is_empty()) + { + List_iterator<char> it(norm_str_list); + char *curr_norm_str; + while ((curr_norm_str= it++)) + free(curr_norm_str); + norm_str_list.empty(); + } + my_hash_free(&unique_items); + return res; +} + +bool Json_schema_unique_items::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + if (je->value_type == JSON_VALUE_TRUE) + is_unique= true; + else if (je->value_type == JSON_VALUE_FALSE) + is_unique= false; + else + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "uniqueItems"); + return true; + } + return false; +} + + +bool Json_schema_max_prop::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + uint properties_count= 0; + json_engine_t curr_je= *je; + int curr_level= je->stack_p; + + if (curr_je.value_type != JSON_VALUE_OBJECT) + return false; + + while (json_scan_next(&curr_je)== 0 && je->stack_p >= curr_level) + { + switch (curr_je.state) + { + case JST_KEY: + { + if (json_read_value(&curr_je)) + return true; + properties_count++; + + if (!json_value_scalar(&curr_je)) + { + if (json_skip_level(&curr_je)) + return true; + } + } + } + } + return properties_count > value ? true : false; +} + +bool Json_schema_max_prop::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "maxProperties"); + return true; + } + + double val= je->s.cs->strntod((char *) je->value, + je->value_len, &end, &err); + if (val < 0) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "maxProperties"); + return true; + } + value= (int)val; + + return false; +} + +bool Json_schema_min_prop::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + uint properties_count= 0; + int curr_level= je->stack_p; + json_engine_t curr_je= *je; + + if (curr_je.value_type != JSON_VALUE_OBJECT) + return false; + + while (json_scan_next(&curr_je)== 0 && je->stack_p >= curr_level) + { + switch (curr_je.state) + { + case JST_KEY: + { + if (json_read_value(&curr_je)) + return true; + properties_count++; + + if (!json_value_scalar(&curr_je)) + { + if (json_skip_level(&curr_je)) + return true; + } + } + } + } + return properties_count < value ? true : false; +} + +bool Json_schema_min_prop::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + int err= 0; + char *end; + + if (je->value_type != JSON_VALUE_NUMBER) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "minProperties"); + return true; + } + + double val= je->s.cs->strntod((char *) je->value, + je->value_len, &end, &err); + if (val < 0) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "minProperties"); + return true; + } + value= (int)val; + + return false; +} + +bool Json_schema_required::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + json_engine_t curr_je= *je; + List<char> malloc_mem_list; + HASH required; + int res= true, curr_level= curr_je.stack_p; + List_iterator<String> it(required_properties); + String *curr_str; + + if (curr_je.value_type != JSON_VALUE_OBJECT) + return false; + + if(my_hash_init(PSI_INSTRUMENT_ME, &required, + curr_je.s.cs, 1024, 0, 0, (my_hash_get_key) get_key_name, + NULL, 0)) + return true; + while (json_scan_next(&curr_je)== 0 && curr_je.stack_p >= curr_level) + { + switch (curr_je.state) + { + case JST_KEY: + { + const uchar *key_end, *key_start; + int key_len; + char *str; + + key_start= curr_je.s.c_str; + do + { + key_end= curr_je.s.c_str; + } while (json_read_keyname_chr(&curr_je) == 0); + + key_len= (int)(key_end-key_start); + str= (char*)malloc((size_t)(key_len)+1); + strncpy(str, (const char*)key_start, key_len); + str[key_len]='\0'; + + if (my_hash_insert(&required, (const uchar*)str)) + goto error; + malloc_mem_list.push_back(str); + } + } + } + while ((curr_str= it++)) + { + if (!my_hash_search(&required, (const uchar*)curr_str->ptr(), + curr_str->length())) + goto error; + } + res= false; + error: + if (!malloc_mem_list.is_empty()) + { + List_iterator<char> it(malloc_mem_list); + char *curr_ptr; + while ((curr_ptr= it++)) + free(curr_ptr); + malloc_mem_list.empty(); + } + my_hash_free(&required); + return res; +} + +bool Json_schema_required::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + int level= je->stack_p; + + if (je->value_type != JSON_VALUE_ARRAY) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "required"); + return true; + } + while(json_scan_next(je)==0 && level <= je->stack_p) + { + if (json_read_value(je)) + return true; + if (je->value_type != JSON_VALUE_STRING) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "required"); + return true; + } + else + { + String *str= new (thd->mem_root)String((char*)je->value, + je->value_len, je->s.cs); + this->required_properties.push_back(str, thd->mem_root); + } + } + return je->s.error ? true : false; +} + +bool Json_schema_dependent_required::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + json_engine_t curr_je= *je; + HASH properties; + bool res= true; + int curr_level= curr_je.stack_p; + List <char> malloc_mem_list; + List_iterator<st_dependent_keywords> it(dependent_required); + st_dependent_keywords *curr_keyword= NULL; + + if (curr_je.value_type != JSON_VALUE_OBJECT) + return false; + + if (my_hash_init(PSI_INSTRUMENT_ME, &properties, + curr_je.s.cs, 1024, 0, 0, (my_hash_get_key) get_key_name, + NULL, 0)) + return true; + + while (json_scan_next(&curr_je)== 0 && curr_je.stack_p >= curr_level) + { + switch (curr_je.state) + { + case JST_KEY: + { + const uchar *key_end, *key_start; + int key_len; + char *str; + + key_start= curr_je.s.c_str; + do + { + key_end= curr_je.s.c_str; + } while (json_read_keyname_chr(&curr_je) == 0); + + key_len= (int)(key_end-key_start); + str= (char*)malloc((size_t)(key_len)+1); + strncpy(str, (const char*)key_start, key_len); + str[(int)(key_end-key_start)]='\0'; + + if (my_hash_insert(&properties, (const uchar*)str)) + goto error; + malloc_mem_list.push_back(str); + } + } + } + while ((curr_keyword= it++)) + { + if (my_hash_search(&properties, + (const uchar*)curr_keyword->property->ptr(), + curr_keyword->property->length())) + { + List_iterator<String> it2(curr_keyword->dependents); + String *curr_depended_keyword; + while ((curr_depended_keyword= it2++)) + { + if (!my_hash_search(&properties, + (const uchar*)curr_depended_keyword->ptr(), + curr_depended_keyword->length())) + { + goto error; + } + } + } + } + res= false; + + error: + my_hash_free(&properties); + if (!malloc_mem_list.is_empty()) + { + List_iterator<char> it(malloc_mem_list); + char *curr_ptr; + while ((curr_ptr= it++)) + free(curr_ptr); + malloc_mem_list.empty(); + } + return res; +} + +bool Json_schema_dependent_required::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + if (je->value_type == JSON_VALUE_OBJECT) + { + int level1= je->stack_p; + while (json_scan_next(je)==0 && level1 <= je->stack_p) + { + switch(je->state) + { + case JST_KEY: + { + const uchar *k_end, *k_start; + int k_len; + + k_start= je->s.c_str; + do + { + k_end= je->s.c_str; + } while (json_read_keyname_chr(je) == 0); + + k_len= (int)(k_end-k_start); + if (json_read_value(je)) + return true; + + if (je->value_type == JSON_VALUE_ARRAY) + { + st_dependent_keywords *curr_dependent_keywords= + (st_dependent_keywords *) alloc_root(thd->mem_root, + sizeof(st_dependent_keywords)); + + if (curr_dependent_keywords) + { + curr_dependent_keywords->property= + new (thd->mem_root)String((char*)k_start, + k_len, je->s.cs); + curr_dependent_keywords->dependents.empty(); + int level2= je->stack_p; + while (json_scan_next(je)==0 && level2 <= je->stack_p) + { + if (json_read_value(je) || je->value_type != JSON_VALUE_STRING) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), + "dependentRequired"); + return true; + } + else + { + String *str= + new (thd->mem_root)String((char*)je->value, + je->value_len, je->s.cs); + curr_dependent_keywords->dependents.push_back(str, thd->mem_root); + } + } + dependent_required.push_back(curr_dependent_keywords, thd->mem_root); + } + else + { + return true; + } + } + else + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), + "dependentRequired"); + return true; + } + } + } + } + } + else + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "dependentRequired"); + return true; + } + return je->s.error ? true : false; +} + +bool Json_schema_property_names::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + json_engine_t curr_je= *je; + int level= curr_je.stack_p; + + if (je->value_type != JSON_VALUE_OBJECT) + return false; + + while (json_scan_next(&curr_je)==0 && level <= curr_je.stack_p) + { + switch(curr_je.state) + { + case JST_KEY: + { + const uchar *k_end, *k_start; + k_start= curr_je.s.c_str; + do + { + k_end= curr_je.s.c_str; + } while (json_read_keyname_chr(&curr_je) == 0); + + if (json_read_value(&curr_je)) + return true; + if (!json_value_scalar(&curr_je)) + { + if (json_skip_level(&curr_je)) + return true; + } + + List_iterator <Json_schema_keyword> it1 (property_names); + Json_schema_keyword *curr_schema= NULL; + while((curr_schema= it1++)) + { + if (curr_schema->validate(&curr_je, k_start, k_end)) + return true; + } + } + } + } + + return false; +} + +bool Json_schema_property_names::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + if (je->value_type != JSON_VALUE_OBJECT) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "propertyNames"); + return true; + } + if (create_object_and_handle_keyword(thd, je, &property_names, + all_keywords)) + return true; + + return false; +} + +/* + additiona_items, additional_properties, unevaluated_items, + unevaluated_properties are all going to be schemas + (basically of object type). So they all can be handled + just like any other schema. +*/ +bool +Json_schema_additional_and_unevaluated::handle_keyword(THD *thd, + json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + if (je->value_type == JSON_VALUE_FALSE) + { + set_allowed(false); + return false; + } + else if (je->value_type == JSON_VALUE_OBJECT) + { + return create_object_and_handle_keyword(thd, je, &schema_list, + all_keywords); + } + if (je->value_type != JSON_VALUE_TRUE) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), keyword_map->func_name.str); + return true; + } + return false; +} + +/* + Validating properties as an alternate shcema happens only when we have + logic keywords. Example we have allOf, and one key is not + validated against allOf but it is present in "properties" and validates + against it. Then the validation result should be true. So we would want that + key to be validated against "properties", with "properties" begin + alternate schema. +*/ +bool Json_schema_properties::validate_as_alternate(const json_engine_t *je, + const uchar* k_start, + const uchar* k_end) +{ + st_property *curr_property= NULL; + json_engine_t curr_je= *je; + if ((curr_property= + (st_property*)my_hash_search(&properties, + (const uchar*)k_start, + (size_t)(k_end-k_start)))) + { + if (validate_schema_items(&curr_je, curr_property->curr_schema)) + return true; + if (!json_value_scalar(&curr_je)) + { + if (json_skip_level(&curr_je)) + return true; + } + } + else + { + if (alternate_schema && alternate_schema->validate_as_alternate(je, k_start, k_end)) + { + return true; + } + } + return false; +} + +bool +Json_schema_additional_and_unevaluated:: + validate_as_alternate(const json_engine_t *je, + const uchar* k_start, + const uchar* k_end) +{ + if (!allowed) + return true; + return validate_schema_items(je, &schema_list); +} + + +/* + Makes sense on its own, without existence of additionalProperties, + properties, patternProperties. +*/ +bool Json_schema_unevaluated_properties::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + json_engine_t curr_je= *je; + int level= curr_je.stack_p, count= 0; + bool has_false= false; + + if (je->value_type != JSON_VALUE_OBJECT) + return false; + + if (!allowed) + has_false= true; + + while (json_scan_next(&curr_je)==0 && level <= curr_je.stack_p) + { + if (json_read_value(&curr_je)) + return true; + count++; + if (validate_schema_items(&curr_je, &schema_list)) + return true; + } + return has_false ? (!count ? false: true) : false; +} + +/* + Unlike additionalItems, additionalProperties makes sense on its own + without existence of properties and patternProperties, +*/ +bool Json_schema_additional_properties::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + json_engine_t curr_je= *je; + int level= curr_je.stack_p; + + if (je->value_type != JSON_VALUE_OBJECT) + return false; + + while (json_scan_next(&curr_je)==0 && level <= curr_je.stack_p) + { + switch(curr_je.state) + { + case JST_KEY: + if (json_read_value(&curr_je)) + return true; + if (validate_schema_items(&curr_je, &schema_list)) + return true; + } + } + + return false; +} + +/* + When items/prefix Items is present and if a key is not validated + against it, then additionalItems is validated as an "alternate validation". + It will be present/linked as alternate keyword and will not be present + in the schema list for that level. This function called when + "items"/"prefixItems" is absent, i.e when additionalItems appears + in the schema list for that level. + So additional Properties on its own will not make sense. +*/ +bool Json_schema_additional_items::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + return false; +} +bool Json_schema_unevaluated_items::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + /* + Makes sense on its own without adjacent keywords. + */ + int level= je->stack_p, count=0; + bool is_false= false; + json_engine_t curr_je= *je; + + if (je->value_type != JSON_VALUE_ARRAY) + return false; + + if (!allowed) + is_false= true; + + while (json_scan_next(&curr_je)==0 && level <= curr_je.stack_p) + { + if (json_read_value(&curr_je)) + return true; + count++; + if (validate_schema_items(&curr_je, &schema_list)) + return true; + } + + return is_false ? (!count ? false : true) : false; +} + +bool Json_schema_properties::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + json_engine_t curr_je= *je; + + if (curr_je.value_type != JSON_VALUE_OBJECT) + return false; + + int level= curr_je.stack_p; + while (json_scan_next(&curr_je)==0 && level <= curr_je.stack_p) + { + switch(curr_je.state) + { + case JST_KEY: + { + const uchar *k_end, *k_start= curr_je.s.c_str; + do + { + k_end= curr_je.s.c_str; + } while (json_read_keyname_chr(&curr_je) == 0); + + if (json_read_value(&curr_je)) + return true; + + st_property *curr_property= NULL; + if ((curr_property= + (st_property*)my_hash_search(&properties, + (const uchar*)k_start, + (size_t)(k_end-k_start)))) + { + if (validate_schema_items(&curr_je, curr_property->curr_schema)) + return true; + } + else + { + if (fall_back_on_alternate_schema(&curr_je, k_start, k_end)) + return true; + } + if (!json_value_scalar(&curr_je)) + { + if (json_skip_level(&curr_je)) + return true; + } + } + } + } + + return false; +} + +bool Json_schema_properties::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + + if (je->value_type != JSON_VALUE_OBJECT) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "properties"); + return true; + } + + if (my_hash_init(PSI_INSTRUMENT_ME, + &this->properties, + je->s.cs, 1024, 0, 0, + (my_hash_get_key) get_key_name_for_property, + NULL, 0)) + return true; + is_hash_inited= true; + + int level= je->stack_p; + while (json_scan_next(je)==0 && level <= je->stack_p) + { + switch(je->state) + { + case JST_KEY: + { + const uchar *k_end, *k_start= je->s.c_str; + do + { + k_end= je->s.c_str; + } while (json_read_keyname_chr(je) == 0); + + if (json_read_value(je)) + return true; + + st_property *curr_property= + (st_property*)alloc_root(thd->mem_root, + sizeof(st_property)); + if (curr_property) + { + curr_property->key_name= (char*)alloc_root(thd->mem_root, + (size_t)(k_end-k_start)+1); + curr_property->curr_schema= + new (thd->mem_root) List<Json_schema_keyword>; + if (curr_property->key_name) + { + curr_property->key_name[(int)(k_end-k_start)]= '\0'; + strncpy((char*)curr_property->key_name, (const char*)k_start, + (size_t)(k_end-k_start)); + if (create_object_and_handle_keyword(thd, je, + curr_property->curr_schema, + all_keywords)) + return true; + if (my_hash_insert(&properties, (const uchar*)curr_property)) + return true; + } + } + } + } + } + return je->s.error ? true : false; +} + +bool Json_schema_pattern_properties:: + validate_as_alternate(const json_engine_t *curr_je, + const uchar *k_start, + const uchar* k_end) +{ + bool match_found= false; + List_iterator <st_pattern_to_property> it1 (pattern_properties); + st_pattern_to_property *curr_pattern_property= NULL; + + str->str_value.set_or_copy_aligned((const char*)k_start, + (size_t)(k_end-k_start), curr_je->s.cs); + + while ((curr_pattern_property= it1++)) + { + if (curr_pattern_property->re.recompile(curr_pattern_property->pattern)) + return true; + if (curr_pattern_property->re.exec(str, 0, 0)) + return true; + if (curr_pattern_property->re.match()) + { + match_found= true; + if (validate_schema_items(curr_je, curr_pattern_property->curr_schema)) + return true; + break; + } + } + if (!match_found) + { + if (fall_back_on_alternate_schema(curr_je)) + return true; + } + return false; +} + + +bool Json_schema_pattern_properties::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + json_engine_t curr_je= *je; + int level= je->stack_p; + bool match_found= false; + + if (je->value_type != JSON_VALUE_OBJECT) + return false; + + while (json_scan_next(&curr_je)==0 && level <= curr_je.stack_p) + { + switch(curr_je.state) + { + case JST_KEY: + { + const uchar *k_end, *k_start= curr_je.s.c_str; + do + { + k_end= curr_je.s.c_str; + } while (json_read_keyname_chr(&curr_je) == 0); + + str->str_value.set_or_copy_aligned((const char*)k_start, + (size_t)(k_end-k_start), curr_je.s.cs); + + if (json_read_value(&curr_je)) + return true; + + List_iterator <st_pattern_to_property> it1 (pattern_properties); + st_pattern_to_property *curr_pattern_property= NULL; + + while ((curr_pattern_property= it1++)) + { + if (curr_pattern_property->re.recompile(curr_pattern_property->pattern)) + return true; + if (curr_pattern_property->re.exec(str, 0, 0)) + return true; + if (curr_pattern_property->re.match()) + { + match_found= true; + if (validate_schema_items(&curr_je, curr_pattern_property->curr_schema)) + return true; + } + } + if (!match_found) + { + if (fall_back_on_alternate_schema(&curr_je, k_start, k_end)) + return true; + } + } + } + } + return false; +} + + + +bool Json_schema_pattern_properties::handle_keyword(THD *thd, + json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + if (je->value_type != JSON_VALUE_OBJECT) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "patternProperties"); + return true; + } + + str= new (thd->mem_root) Item_string(thd, "", (uint) 0, je->s.cs); + + int level= je->stack_p; + while (json_scan_next(je)==0 && level <= je->stack_p) + { + switch(je->state) + { + case JST_KEY: + { + const uchar *k_end, *k_start= je->s.c_str; + do + { + k_end= je->s.c_str; + } while (json_read_keyname_chr(je) == 0); + + if (json_read_value(je)) + return true; + + st_pattern_to_property *curr_pattern_to_property= NULL; + + curr_pattern_to_property= new (thd->mem_root) pattern_to_property(); + if (curr_pattern_to_property) + { + my_repertoire_t repertoire= my_charset_repertoire(je->s.cs); + curr_pattern_to_property->pattern= + thd->make_string_literal((const char*)k_start, + (size_t)(k_end-k_start), + repertoire); + curr_pattern_to_property->re.init(je->s.cs, 0); + curr_pattern_to_property->re.unset_flag(PCRE2_CASELESS); + curr_pattern_to_property->curr_schema= + new (thd->mem_root) List<Json_schema_keyword>; + + if (curr_pattern_to_property->curr_schema) + { + if (create_object_and_handle_keyword(thd, je, + curr_pattern_to_property->curr_schema, + all_keywords)) + return true; + } + + pattern_properties.push_back(curr_pattern_to_property, thd->mem_root); + } + } + } + } + return false; +} + +bool Json_schema_logic::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + if (je->value_type != JSON_VALUE_ARRAY) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), keyword_map->func_name.str); + return true; + } + + int level= je->stack_p; + while(json_scan_next(je)==0 && je->stack_p >= level) + { + json_engine_t temp_je; + char *begin, *end; + int len; + + if (json_read_value(je)) + return true; + begin= (char*)je->value; + + if (json_skip_level(je)) + return true; + + end= (char*)je->s.c_str; + len= (int)(end-begin); + + json_scan_start(&temp_je, je->s.cs, (const uchar *) begin, + (const uchar *)begin+len); + List<Json_schema_keyword> *keyword_list= + new (thd->mem_root) List<Json_schema_keyword>; + + if (!keyword_list) + return true; + if (create_object_and_handle_keyword(thd, &temp_je, keyword_list, + all_keywords)) + return true; + + schema_items.push_back(keyword_list, thd->mem_root); + } + + return false; +} + +bool Json_schema_logic::check_validation(const json_engine_t *je, + const uchar *k_start, + const uchar *k_end) +{ + List_iterator <List<Json_schema_keyword>> it1 (schema_items); + List<Json_schema_keyword> *curr_schema= NULL; + Json_schema_keyword *curr_alternate_schema= NULL; + uint count_validations= 0; + bool validated= true; + + if (je->value_type == JSON_VALUE_ARRAY) + curr_alternate_schema= alternate_choice1; + else if (je->value_type == JSON_VALUE_OBJECT) + curr_alternate_schema= alternate_choice2; + + while ((curr_schema= it1++)) + { + List_iterator<Json_schema_keyword> it2(*curr_schema); + Json_schema_keyword *curr_keyword= NULL; + validated= true; + + while ((curr_keyword=it2++)) + { + if (!curr_keyword->alternate_schema) + curr_keyword->alternate_schema= curr_alternate_schema; + if (curr_keyword->validate(je)) + { + validated= false; + break; + } + } + if (validated) + { + count_validations++; + if (logic_flag & HAS_NOT) + return true; + } + } + + if (validate_count(&count_validations, &schema_items.elements)) + return true; + + return false; +} +bool Json_schema_logic::validate(const json_engine_t *je, + const uchar *k_start, + const uchar* k_end) +{ + return check_validation(je, k_start, k_end); +} + +bool Json_schema_not::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + bool res= false; + + if (je->value_type != JSON_VALUE_OBJECT) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), keyword_map->func_name.str); + return true; + } + + res= create_object_and_handle_keyword(thd, je, &schema_list, all_keywords); + + schema_items.push_back(&schema_list, thd->mem_root); + + return res; +} + + +bool Json_schema_keyword::validate_schema_items(const json_engine_t *je, + List<Json_schema_keyword> + *schema_items) +{ + json_engine_t curr_je= *je; + List_iterator<Json_schema_keyword> it1(*schema_items); + Json_schema_keyword *curr_schema= NULL; + + while((curr_schema= it1++)) + { + if (curr_schema->validate(&curr_je)) + return true; + } + + return false; +} + +bool Json_schema_conditional::validate(const json_engine_t *je, + const uchar *k_start, + const uchar *k_end) +{ + if (if_cond) + { + if (!if_cond->validate_schema_items(je, + if_cond->get_validation_keywords())) + { + if (then_cond) + { + if (then_cond->validate_schema_items(je, + then_cond->get_validation_keywords())) + return true; + } + } + else + { + if (else_cond) + { + if (else_cond->validate_schema_items(je, + else_cond->get_validation_keywords())) + return true; + } + } + } + return false; +} + + +bool Json_schema_conditional::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + if (je->value_type != JSON_VALUE_OBJECT) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), keyword_map->func_name.str); + return true; + } + return create_object_and_handle_keyword(thd, je, &conditions_schema, + all_keywords); +} + +bool Json_schema_dependent_schemas::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + if (je->value_type != JSON_VALUE_OBJECT) + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "properties"); + return true; + } + + if (my_hash_init(PSI_INSTRUMENT_ME, + &this->properties, + je->s.cs, 1024, 0, 0, + (my_hash_get_key) get_key_name_for_property, + NULL, 0)) + return true; + is_hash_inited= true; + + int level= je->stack_p; + while (json_scan_next(je)==0 && level <= je->stack_p) + { + switch(je->state) + { + case JST_KEY: + { + const uchar *k_end, *k_start= je->s.c_str; + do + { + k_end= je->s.c_str; + } while (json_read_keyname_chr(je) == 0); + + if (json_read_value(je)) + return true; + + st_property *curr_property= + (st_property*)alloc_root(thd->mem_root, + sizeof(st_property)); + if (curr_property) + { + curr_property->key_name= (char*)alloc_root(thd->mem_root, + (size_t)(k_end-k_start)+1); + curr_property->curr_schema= + new (thd->mem_root) List<Json_schema_keyword>; + if (curr_property->key_name) + { + curr_property->key_name[(int)(k_end-k_start)]= '\0'; + strncpy((char*)curr_property->key_name, (const char*)k_start, + (size_t)(k_end-k_start)); + if (create_object_and_handle_keyword(thd, je, + curr_property->curr_schema, + all_keywords)) + return true; + if (my_hash_insert(&properties, (const uchar*)curr_property)) + return true; + } + } + } + } + } + return false; +} + +bool Json_schema_dependent_schemas::validate(const json_engine_t *je, + const uchar *k_start, + const uchar *k_end) +{ + json_engine_t curr_je= *je; + + if (curr_je.value_type != JSON_VALUE_OBJECT) + return false; + + int level= curr_je.stack_p; + while (json_scan_next(&curr_je)==0 && level <= curr_je.stack_p) + { + switch(curr_je.state) + { + case JST_KEY: + { + const uchar *k_end, *k_start= curr_je.s.c_str; + do + { + k_end= curr_je.s.c_str; + } while (json_read_keyname_chr(&curr_je) == 0); + + if (json_read_value(&curr_je)) + return true; + + st_property *curr_property= NULL; + if ((curr_property= + (st_property*)my_hash_search(&properties, + (const uchar*)k_start, + (size_t)(k_end-k_start)))) + { + if (validate_schema_items(je, curr_property->curr_schema)) + return true; + if (!json_value_scalar(&curr_je)) + { + if (json_skip_level(&curr_je)) + return true; + } + } + } + } + } + + return false; +} + +bool Json_schema_media_string::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + if (je->value_type != JSON_VALUE_STRING) + { + String curr_keyword((char*)key_start, key_end-key_start, je->s.cs); + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), curr_keyword.ptr()); + return true; + } + + return false; +} + +bool Json_schema_reference::handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> + *all_keywords) +{ + String keyword(0); + keyword.append((const char*)key_start, (int)(key_end-key_start)); + my_error(ER_JSON_SCHEMA_KEYWORD_UNSUPPORTED, MYF(0), keyword.ptr()); + return true; +} + +Json_schema_keyword* create_object(THD *thd, + Json_schema_keyword *curr_keyword, + const uchar* key_start, + const uchar* key_end) +{ + st_json_schema_keyword_map *curr_keyword_map= NULL; + curr_keyword_map= + (st_json_schema_keyword_map*) + my_hash_search(&all_keywords_hash, + key_start, + (size_t)(key_end-key_start)); + if (!curr_keyword_map) + { + curr_keyword_map= &empty_func_map; + } + curr_keyword= (curr_keyword_map->func)(thd); + curr_keyword->keyword_map= curr_keyword_map; + + return curr_keyword; +} + +static int sort_by_priority(Json_schema_keyword* el1, Json_schema_keyword* el2, + void *arg) +{ + return el1->priority > el2->priority; +} + +void fix_keyword_list(List <Json_schema_keyword> *keyword_list) +{ + bubble_sort<Json_schema_keyword>(keyword_list, sort_by_priority, NULL); + + if (keyword_list && !keyword_list->is_empty()) + { + int count= 1; + + List_iterator<Json_schema_keyword> it2(*keyword_list); + Json_schema_keyword *curr_schema= NULL; + + while((curr_schema=it2++)) + { + curr_schema->set_alternate_schema(keyword_list->elem(count)); + count++; + } + } + return; +} + +/* + Some schemas are interdependent: they are evaluated only if their + adjacent schemas fail to evaluate. So the need to be linked + in a way that if one fails to evaluate a value, we can try + an alternate schema. + Hence push such keywords in a temporary list, adjust the interdependence + and then add them to main schema list. +*/ +bool +add_schema_interdependence(THD *thd, List<Json_schema_keyword> *temporary, + List<Json_schema_keyword> *keyword_list) +{ + List_iterator<Json_schema_keyword> temp_it(*temporary); + List<Json_schema_keyword> array_prop, object_prop, logic_prop, conditional_prop; + Json_schema_keyword *temp_keyword= NULL, *contains= NULL, + *max_contains= NULL, *min_contains= NULL, + *if_cond= NULL, *then_cond= NULL, *else_cond= NULL; + + while((temp_keyword= temp_it++)) + { + size_t len= strlen(temp_keyword->keyword_map->func_name.str); + st_json_schema_keyword_map *curr_element= NULL; + if ((curr_element= (st_json_schema_keyword_map*) my_hash_search(&all_keywords_hash, + (uchar*)(temp_keyword->keyword_map->func_name.str), len))) + { + if (temp_keyword->priority > 0) + { + if (curr_element->flag == JSON_SCHEMA_ARRAY_KEYWORD) + array_prop.push_back(temp_keyword); + else if (curr_element->flag == JSON_SCHEMA_OBJECT_KEYWORD) + object_prop.push_back(temp_keyword); + else if (curr_element->flag == JSON_SCHEMA_LOGIC_KEYWORD) + logic_prop.push_back(temp_keyword); + } + else if (temp_keyword->keyword_map == &(json_schema_func_array[35])) + if_cond= temp_keyword; + else if (temp_keyword->keyword_map == &(json_schema_func_array[36])) + then_cond= temp_keyword; + else if (temp_keyword->keyword_map == &(json_schema_func_array[37])) + else_cond= temp_keyword; + else if (temp_keyword->keyword_map == &(json_schema_func_array[18])) + contains= temp_keyword; + else if (temp_keyword->keyword_map == &(json_schema_func_array[20])) + min_contains= temp_keyword; + else if (temp_keyword->keyword_map == &(json_schema_func_array[19])) + max_contains= temp_keyword; + else + keyword_list->push_back(temp_keyword, thd->mem_root); + } + } + + if (if_cond) + { + Json_schema_conditional *cond_schema= + new (current_thd->mem_root) Json_schema_conditional(); + if (cond_schema) + cond_schema->set_conditions(if_cond, then_cond, else_cond); + keyword_list->push_back(cond_schema, thd->mem_root); + } + if (contains) + { + contains->set_dependents(min_contains, max_contains); + keyword_list->push_back(contains, thd->mem_root); + } + + fix_keyword_list(&array_prop); + fix_keyword_list(&object_prop); + + /* + We want to check for alternate schema + When a key is not validated by logic keywords, we would want to also check + schema like properties, items etc to make sure the key is not validated by + any schema in order to return correct result. So "link" other schemas as + alternate when logic properties is present and only push logic keywords + to the schema list. + */ + if (!logic_prop.is_empty()) + { + List_iterator<Json_schema_keyword> it(logic_prop); + Json_schema_keyword *curr_schema= NULL; + while((curr_schema= it++)) + { + curr_schema->set_alternate_schema_choice(array_prop.elem(0), + object_prop.elem(0)); + keyword_list->push_back(curr_schema, thd->mem_root); + } + array_prop.empty(); + object_prop.empty(); + } + else + { + if (array_prop.elem(0)) + keyword_list->push_back(array_prop.elem(0), thd->mem_root); + if (object_prop.elem(0)) + keyword_list->push_back(object_prop.elem(0), thd->mem_root); + } + return false; +} + + +/* + Scan all keywords on the current level and put them in a temporary + list. Once scanning is done, adjust the dependency if needed, and + add the keywords in keyword_list +*/ +bool create_object_and_handle_keyword(THD *thd, json_engine_t *je, + List<Json_schema_keyword> *keyword_list, + List<Json_schema_keyword> *all_keywords) +{ + int level= je->stack_p; + List<Json_schema_keyword> temporary_list; + + DBUG_EXECUTE_IF("json_check_min_stack_requirement", + { + long arbitrary_var; + long stack_used_up= + (available_stack_size(thd->thread_stack, + &arbitrary_var)); + ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE); + }); + if (check_stack_overrun(thd, STACK_MIN_SIZE , NULL)) + return 1; + + while (json_scan_next(je)== 0 && je->stack_p >= level) + { + switch(je->state) + { + case JST_KEY: + { + const uchar *key_end, *key_start; + + key_start= je->s.c_str; + do + { + key_end= je->s.c_str; + } while (json_read_keyname_chr(je) == 0); + + if (json_read_value(je)) + return true; + + Json_schema_keyword *curr_keyword= NULL; + curr_keyword= create_object(thd, curr_keyword, + key_start, key_end); + if (all_keywords) + all_keywords->push_back(curr_keyword, thd->mem_root); + if (curr_keyword->handle_keyword(thd, je, + (const char*)key_start, + (const char*)key_end, all_keywords)) + { + return true; + } + temporary_list.push_back(curr_keyword, thd->mem_root); + break; + } + } + } + + if (add_schema_interdependence(thd, &temporary_list, keyword_list)) + return true; + + return je->s.error ? true : false; +} + +uchar* get_key_name_for_property(const char *key_name, size_t *length, + my_bool /* unused */) +{ + st_property * curr_property= (st_property*)(key_name); + + *length= strlen(curr_property->key_name); + return (uchar*) curr_property->key_name; +} + +uchar* get_key_name_for_func(const char *key_name, size_t *length, + my_bool /* unused */) +{ + st_json_schema_keyword_map * curr_keyword= + (st_json_schema_keyword_map*)(key_name); + + *length= curr_keyword->func_name.length; + return (uchar*)curr_keyword->func_name.str; +} + +bool setup_json_schema_keyword_hash() +{ + if (my_hash_init(PSI_INSTRUMENT_ME, + &all_keywords_hash, + system_charset_info, 1024, 0, 0, + (my_hash_get_key) get_key_name_for_func, + NULL, 0)) + return true; + + int size= sizeof(json_schema_func_array)/sizeof(json_schema_func_array[0]); + for (int i= 0; i < size; i++) + { + if (my_hash_insert(&all_keywords_hash, (uchar*)(&json_schema_func_array[i]))) + return true; + } + return false; +} + +void cleanup_json_schema_keyword_hash() +{ + my_hash_free(&all_keywords_hash); + + return; +} diff --git a/sql/json_schema.h b/sql/json_schema.h new file mode 100644 index 00000000000..96e5f8f6719 --- /dev/null +++ b/sql/json_schema.h @@ -0,0 +1,827 @@ +#ifndef JSON_SCHEMA_INCLUDED +#define JSON_SCHEMA_INCLUDED + +/* Copyright (c) 2016, 2021, MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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-1301 USA */ + + +/* This file defines all json schema classes. */ + +#include "sql_class.h" +#include "sql_type_json.h" +#include "json_schema_helper.h" + +struct st_json_schema_keyword_map; + +class Json_schema_keyword : public Sql_alloc +{ + public: + Json_schema_keyword *alternate_schema; + st_json_schema_keyword_map *keyword_map; + double value; + uint priority; + bool allowed; + + Json_schema_keyword() : alternate_schema(NULL), keyword_map(NULL), + value(0), priority(0), allowed(true) + { + } + virtual ~Json_schema_keyword() = default; + + /* + Called for each keyword on the current level. + */ + virtual bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) + { return false; } + virtual bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) + { + return false; + } + virtual List<Json_schema_keyword>* get_validation_keywords() + { + return NULL; + } + void set_alternate_schema(Json_schema_keyword *schema) + { + alternate_schema= schema; + } + virtual bool fall_back_on_alternate_schema(const json_engine_t *je, + const uchar* k_start= NULL, + const uchar* k_end= NULL); + virtual bool validate_as_alternate(const json_engine_t *je, + const uchar* k_start= NULL, + const uchar* k_end= NULL) + { + return false; + } + virtual bool validate_schema_items(const json_engine_t *je, + List<Json_schema_keyword>*schema_items); + virtual void set_alternate_schema_choice(Json_schema_keyword *schema1, + Json_schema_keyword *schema2) + { + return; + } + virtual void set_dependents(Json_schema_keyword *schema1, + Json_schema_keyword *schema2) + { + return; + } +}; + +/* + Additional and unvaluated keywords and items handle + keywords and validate schema in same way, so it makes sense + to have a base class for them. +*/ +class Json_schema_additional_and_unevaluated : public Json_schema_keyword +{ + public: + List<Json_schema_keyword> schema_list; + Json_schema_additional_and_unevaluated() + { + allowed= true; + } + void set_allowed(bool allowed_val) + { + allowed= allowed_val; + } + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; + bool validate(const json_engine_t *je, + const uchar *k_start= NULL, + const uchar *k_end= NULL) override + { + return false; + } + bool validate_as_alternate(const json_engine_t *je, const uchar *k_start, + const uchar *k_end) override; +}; + + +class Json_schema_annotation : public Json_schema_keyword +{ + public: + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +class Json_schema_format : public Json_schema_keyword +{ + public: + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +typedef List<Json_schema_keyword> List_schema_keyword; + +class Json_schema_type : public Json_schema_keyword +{ + private: + uint type; + + public: + bool validate(const json_engine_t *je, + const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, + json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; + Json_schema_type() + { + type= 0; + } +}; + +class Json_schema_const : public Json_schema_keyword +{ + private: + char *const_json_value; + + public: + enum json_value_types type; + bool validate(const json_engine_t *je, + const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; + Json_schema_const() + { + const_json_value= NULL; + } +}; + + +class Json_schema_enum : public Json_schema_keyword +{ + private: + HASH enum_values; + uint enum_scalar; + + public: + bool validate(const json_engine_t *je, + const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; + Json_schema_enum() + { + enum_scalar= 0; + } + ~Json_schema_enum() + { + my_hash_free(&enum_values); + } +}; + +class Json_schema_maximum : public Json_schema_keyword +{ + public: + bool validate(const json_engine_t *je, + const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +class Json_schema_minimum : public Json_schema_keyword +{ + public: + bool validate(const json_engine_t *je, + const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +class Json_schema_multiple_of : public Json_schema_keyword +{ + private: + longlong multiple_of; + + public: + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +class Json_schema_ex_maximum : public Json_schema_keyword +{ + public: + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +class Json_schema_ex_minimum : public Json_schema_keyword +{ + public: + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +class Json_schema_max_len : public Json_schema_keyword +{ + public: + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +class Json_schema_min_len : public Json_schema_keyword +{ + public: + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +class Json_schema_pattern : public Json_schema_keyword +{ + private: + Regexp_processor_pcre re; + Item *pattern; + Item_string *str; + + public: + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; + Json_schema_pattern() + { + str= NULL; + pattern= NULL; + } + ~Json_schema_pattern() { re.cleanup(); } +}; + +class Json_schema_max_items : public Json_schema_keyword +{ + public: + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +class Json_schema_min_items : public Json_schema_keyword +{ + public: + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +class Json_schema_max_contains : public Json_schema_keyword +{ + public: + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +class Json_schema_min_contains : public Json_schema_keyword +{ + public: + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; +/* + The value of max_contains and min_contains is only + relevant when contains keyword is present. + Hence the pointers to access them directly. +*/ +class Json_schema_contains : public Json_schema_keyword +{ + public: + List <Json_schema_keyword> contains; + Json_schema_keyword *max_contains; + Json_schema_keyword *min_contains; + + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; + void set_dependents(Json_schema_keyword *min, Json_schema_keyword *max) override + { + min_contains= min; + max_contains= max; + } +}; + +class Json_schema_unique_items : public Json_schema_keyword +{ + private: + bool is_unique; + + public: + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + + +class Json_schema_prefix_items : public Json_schema_keyword +{ + public: + List <List_schema_keyword> prefix_items; + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; + Json_schema_prefix_items() + { + priority= 1; + } +}; + +class Json_schema_unevaluated_items : + public Json_schema_additional_and_unevaluated +{ + public: + Json_schema_unevaluated_items() + { + priority= 4; + } + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; +}; + +class Json_schema_additional_items : + public Json_schema_additional_and_unevaluated +{ + public: + Json_schema_additional_items() + { + priority= 3; + } + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; +}; + +class Json_schema_items : public Json_schema_keyword +{ + private: + List<Json_schema_keyword> items_schema; + public: + Json_schema_items() + { + priority= 2; + } + void set_allowed(bool allowed_val) { allowed= allowed_val; } + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; + bool validate_as_alternate(const json_engine_t *je, const uchar *k_start, + const uchar *k_end) override; +}; + + +class Json_schema_property_names : public Json_schema_keyword +{ + protected: + List <Json_schema_keyword> property_names; + + public: + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +typedef struct property +{ + List<Json_schema_keyword> *curr_schema; + char *key_name; +} st_property; + +class Json_schema_properties : public Json_schema_keyword +{ + private: + HASH properties; + bool is_hash_inited; + + public: + Json_schema_properties() + { + priority= 1; + } + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; + ~Json_schema_properties() + { + if (is_hash_inited) + my_hash_free(&properties); + } + bool validate_as_alternate(const json_engine_t *je, const uchar *k_start, + const uchar *k_end) override; + }; + +class Json_schema_dependent_schemas : public Json_schema_keyword +{ + private: + HASH properties; + bool is_hash_inited; + + public: + ~Json_schema_dependent_schemas() + { + if (is_hash_inited) + my_hash_free(&properties); + } + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + + +class Json_schema_additional_properties : + public Json_schema_additional_and_unevaluated +{ + public: + Json_schema_additional_properties() + { + priority= 3; + } + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; +}; + +class Json_schema_unevaluated_properties : + public Json_schema_additional_and_unevaluated +{ + public: + Json_schema_unevaluated_properties() + { + priority= 4; + } + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; +}; + +typedef struct pattern_to_property : public Sql_alloc +{ + Regexp_processor_pcre re; + Item *pattern; + List<Json_schema_keyword> *curr_schema; +}st_pattern_to_property; + +class Json_schema_pattern_properties : public Json_schema_keyword +{ + private: + Item_string *str; + List<st_pattern_to_property> pattern_properties; + + public: + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; + Json_schema_pattern_properties() + { + priority= 2; + } + ~Json_schema_pattern_properties() + { + str= NULL; + if (!pattern_properties.is_empty()) + { + st_pattern_to_property *curr_pattern_to_property= NULL; + List_iterator<st_pattern_to_property> it(pattern_properties); + while((curr_pattern_to_property= it++)) + { + curr_pattern_to_property->re.cleanup(); + curr_pattern_to_property->pattern= NULL; + delete curr_pattern_to_property; + curr_pattern_to_property= nullptr; + } + } + } + bool validate_as_alternate(const json_engine_t *je, const uchar *k_start, + const uchar *k_end) override; +}; + + +class Json_schema_max_prop : public Json_schema_keyword +{ + public: + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +class Json_schema_min_prop : public Json_schema_keyword +{ + public: + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +class Json_schema_required : public Json_schema_keyword +{ + private: + List <String> required_properties; + + public: + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +typedef struct dependent_keyowrds +{ + String *property; + List <String> dependents; +} st_dependent_keywords; + +class Json_schema_dependent_required : public Json_schema_keyword +{ + private: + List<st_dependent_keywords> dependent_required; + + public: + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +enum logic_enum { HAS_ALL_OF= 2, HAS_ANY_OF= 4, HAS_ONE_OF= 8, HAS_NOT= 16}; +class Json_schema_logic : public Json_schema_keyword +{ + protected: + uint logic_flag; + List <List_schema_keyword> schema_items; + Json_schema_keyword *alternate_choice1, *alternate_choice2; + public: + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; + Json_schema_logic() + { + logic_flag= 0; + alternate_choice1= alternate_choice2= NULL; + priority= 1; + } + virtual bool validate_count(uint* count, uint* total) { return false; } + void set_alternate_schema_choice(Json_schema_keyword *schema1, + Json_schema_keyword* schema2) override + { + alternate_choice1= schema1; + alternate_choice2= schema2; + } + bool check_validation(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL); +}; + +class Json_schema_not : public Json_schema_logic +{ + private: + List <Json_schema_keyword> schema_list; + public: + Json_schema_not() + { + logic_flag= HAS_NOT; + } + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; + bool validate_count(uint *count, uint *total) override + { + return *count !=0; + } +}; + +class Json_schema_one_of : public Json_schema_logic +{ + public: + Json_schema_one_of() + { + logic_flag= HAS_ONE_OF; + } + bool validate_count(uint *count, uint *total) override + { + return !(*count == 1); + } +}; + +class Json_schema_any_of : public Json_schema_logic +{ + public: + Json_schema_any_of() + { + logic_flag= HAS_ANY_OF; + } + bool validate_count(uint *count, uint *total) override + { + return *count == 0; + } +}; + +class Json_schema_all_of : public Json_schema_logic +{ + public: + Json_schema_all_of() + { + logic_flag= HAS_ALL_OF; + } + bool validate_count(uint *count, uint *total) override + { + return *count != *total; + } +}; + +class Json_schema_conditional : public Json_schema_keyword +{ + private: + Json_schema_keyword *if_cond, *else_cond, *then_cond; + + public: + List<Json_schema_keyword> conditions_schema; + Json_schema_conditional() + { + if_cond= NULL; + then_cond= NULL; + else_cond= NULL; + } + bool validate(const json_engine_t *je, const uchar *k_start= NULL, + const uchar *k_end= NULL) override; + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; + void set_conditions(Json_schema_keyword *if_val, + Json_schema_keyword* then_val, + Json_schema_keyword *else_val) + { + if_cond= if_val; + then_cond= then_val; + else_cond= else_val; + } + List<Json_schema_keyword>* get_validation_keywords() override + { + return &conditions_schema; + } + +}; + +class Json_schema_if : public Json_schema_conditional +{ +}; + +class Json_schema_else : public Json_schema_conditional +{ +}; + +class Json_schema_then : public Json_schema_conditional +{ +}; + +class Json_schema_media_string : public Json_schema_keyword +{ + public: + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +class Json_schema_reference : public Json_schema_keyword +{ + public: + bool handle_keyword(THD *thd, json_engine_t *je, + const char* key_start, + const char* key_end, + List<Json_schema_keyword> *all_keywords) override; +}; + +bool create_object_and_handle_keyword(THD *thd, json_engine_t *je, + List<Json_schema_keyword> *keyword_list, + List<Json_schema_keyword> *all_keywords); +uchar* get_key_name_for_property(const char *key_name, size_t *length, + my_bool /* unused */); +uchar* get_key_name_for_func(const char *key_name, size_t *length, + my_bool /* unused */); + +enum keyword_flag +{ + JSON_SCHEMA_COMMON_KEYWORD= 0, + JSON_SCHEMA_NUMBER_KEYWORD= 1, + JSON_SCHEMA_STRING_KEYWORD= 2, + JSON_SCHEMA_ARRAY_KEYWORD= 3, + JSON_SCHEMA_OBJECT_KEYWORD= 4, + JSON_SCHEMA_LOGIC_KEYWORD= 5, + JSON_SCHEMA_CONDITION_KEYWORD= 6, + JSON_SCHEMA_ANNOTATION_KEYWORD= 7, + JSON_SCHEMA_FORMAT_KEYWORD= 8, + JSON_SCHEMA_MEDIA_KEYWORD= 9, + JSON_SCHEMA_REFERENCE_KEYWORD= 10, + JSON_SCHEMA_EMPTY_KEYWORD= 11 +}; + +typedef struct st_json_schema_keyword_map +{ + LEX_CSTRING func_name; + Json_schema_keyword*(*func)(THD*); + enum keyword_flag flag; +} json_schema_keyword_map; + +bool setup_json_schema_keyword_hash(); +void cleanup_json_schema_keyword_hash(); + +#endif diff --git a/sql/json_schema_helper.cc b/sql/json_schema_helper.cc new file mode 100644 index 00000000000..1b75b15699b --- /dev/null +++ b/sql/json_schema_helper.cc @@ -0,0 +1,102 @@ +/* Copyright (c) 2016, 2022, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software 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-1301 USA */ + + +#include "mariadb.h" +#include "sql_class.h" +#include "sql_parse.h" // For check_stack_overrun +#include <m_string.h> +#include "json_schema_helper.h" + + +bool json_key_equals(const char* key, LEX_CSTRING val, int key_len) +{ + return (size_t)key_len == val.length && !strncmp(key, val.str, key_len); +} + +bool json_assign_type(uint *curr_type, json_engine_t *je) +{ + const char* curr_value= (const char*)je->value; + int len= je->value_len; + + if (json_key_equals(curr_value, { STRING_WITH_LEN("number") }, len)) + *curr_type|= (1 << JSON_VALUE_NUMBER); + else if(json_key_equals(curr_value, { STRING_WITH_LEN("string") }, len)) + *curr_type|= (1 << JSON_VALUE_STRING); + else if(json_key_equals(curr_value, { STRING_WITH_LEN("array") }, len)) + *curr_type|= (1 << JSON_VALUE_ARRAY); + else if(json_key_equals(curr_value, { STRING_WITH_LEN("object") }, len)) + *curr_type|= (1 << JSON_VALUE_OBJECT); + else if (json_key_equals(curr_value, { STRING_WITH_LEN("boolean") }, len)) + *curr_type|= ((1 << JSON_VALUE_TRUE) | (1 << JSON_VALUE_FALSE)); + else if (json_key_equals(curr_value, { STRING_WITH_LEN("null") }, len)) + *curr_type|= (1 << JSON_VALUE_NULL); + else + { + my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "type"); + return true; + } + return false; +} + +uchar* get_key_name(const char *key_name, size_t *length, + my_bool /* unused */) +{ + *length= strlen(key_name); + return (uchar*) key_name; +} + +void json_get_normalized_string(json_engine_t *je, String *res, + int *error) +{ + char *val_begin= (char*)je->value, *val_end= NULL; + String val("",0,je->s.cs); + DYNAMIC_STRING a_res; + + if (init_dynamic_string(&a_res, NULL, 0, 0)) + goto error; + + if (!json_value_scalar(je)) + { + if (json_skip_level(je)) + goto error; + } + + val_end= json_value_scalar(je) ? val_begin+je->value_len : + (char *)je->s.c_str; + val.set((const char*)val_begin, val_end-val_begin, je->s.cs); + + if (je->value_type == JSON_VALUE_NUMBER || + je->value_type == JSON_VALUE_ARRAY || + je->value_type == JSON_VALUE_OBJECT) + { + if (json_normalize(&a_res, (const char*)val.ptr(), + val_end-val_begin, je->s.cs)) + goto error; + } + else if(je->value_type == JSON_VALUE_STRING) + { + strncpy((char*)a_res.str, val.ptr(), je->value_len); + a_res.length= je->value_len; + } + + res->append(a_res.str, a_res.length, je->s.cs); + *error= 0; + + error: + dynstr_free(&a_res); + + return; +} diff --git a/sql/json_schema_helper.h b/sql/json_schema_helper.h new file mode 100644 index 00000000000..4a596b0b40d --- /dev/null +++ b/sql/json_schema_helper.h @@ -0,0 +1,30 @@ +#ifndef JSON_SCHEMA_HELPER +#define JSON_SCHEMA_HELPER + +/* Copyright (c) 2016, 2021, MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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-1301 USA */ + +#include "sql_type_json.h" +#include <m_string.h> +#include "json_schema.h" + +bool json_key_equals(const char* key, LEX_CSTRING val, int key_len); + +bool json_assign_type(uint *curr_type, json_engine_t *je); +uchar* get_key_name(const char *key_name, size_t *length, + my_bool /* unused */); +void json_get_normalized_string(json_engine_t *je, String *res, + int *error); +#endif diff --git a/sql/json_table.cc b/sql/json_table.cc index ded221269ad..88167f112b0 100644 --- a/sql/json_table.cc +++ b/sql/json_table.cc @@ -29,22 +29,6 @@ #define HA_ERR_JSON_TABLE (HA_ERR_LAST+1) -/* - Allocating memory and *also* using it (reading and - writing from it) because some build instructions cause - compiler to optimize out stack_used_up. Since alloca() - here depends on stack_used_up, it doesnt get executed - correctly and causes json_debug_nonembedded to fail - ( --error ER_STACK_OVERRUN_NEED_MORE does not occur). -*/ -#define ALLOCATE_MEM_ON_STACK(A) do \ - { \ - uchar *array= (uchar*)alloca(A); \ - array[0]= 1; \ - array[0]++; \ - array[0] ? array[0]++ : array[0]--; \ - } while(0) - class table_function_handlerton { public: diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b254e76d14d..8ee4b0408ef 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -44,6 +44,7 @@ #include "sql_base.h" #include "sql_test.h" // mysql_print_status #include "item_create.h" // item_create_cleanup, item_create_init +#include "json_schema.h" #include "sql_servers.h" // servers_free, servers_init #include "init.h" // unireg_init #include "derror.h" // init_errmessage @@ -1992,6 +1993,7 @@ static void clean_up(bool print_message) item_func_sleep_free(); lex_free(); /* Free some memory */ item_create_cleanup(); + cleanup_json_schema_keyword_hash(); tdc_start_shutdown(); #ifdef HAVE_REPLICATION semi_sync_master_deinit(); @@ -4265,6 +4267,7 @@ static int init_common_variables() if (item_create_init()) return 1; item_init(); + setup_json_schema_keyword_hash(); /* Process a comma-separated character set list and choose the first available character set. This is mostly for @@ -5306,6 +5309,12 @@ static int init_server_components() #if defined(__linux__) MARIADB_REMOVED_OPTION("super-large-pages"), #endif + MARIADB_REMOVED_OPTION("innodb-defragment"), + MARIADB_REMOVED_OPTION("innodb-defragment-n-pages"), + MARIADB_REMOVED_OPTION("innodb-defragment-stats-accuracy"), + MARIADB_REMOVED_OPTION("innodb-defragment-fill-factor"), + MARIADB_REMOVED_OPTION("innodb-defragment-fill-factor-n-recs"), + MARIADB_REMOVED_OPTION("innodb-defragment-frequency"), MARIADB_REMOVED_OPTION("innodb-idle-flush-pct"), MARIADB_REMOVED_OPTION("innodb-locks-unsafe-for-binlog"), MARIADB_REMOVED_OPTION("innodb-rollback-segments"), diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 4cbf618e045..1bf9c84bae2 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -11930,7 +11930,7 @@ ha_rows check_quick_select(PARAM *param, uint idx, ha_rows limit, Skip materialized derived table/view result table from MRR check as they aren't contain any data yet. */ - if (param->table->pos_in_table_list->is_non_derived()) + if (!param->table->pos_in_table_list->is_materialized_derived()) rows= file->multi_range_read_info_const(keynr, &seq_if, (void*)&seq, 0, bufsize, mrr_flags, limit, cost); param->quick_rows[keynr]= rows; diff --git a/sql/opt_rewrite_date_cmp.cc b/sql/opt_rewrite_date_cmp.cc new file mode 100644 index 00000000000..5a6410414da --- /dev/null +++ b/sql/opt_rewrite_date_cmp.cc @@ -0,0 +1,361 @@ +/* + Copyright (c) 2023, MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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 */ + + +/** + @file + + @brief + Rewrites that make non-sargable date[time] comparisons sargable. +*/ + +#ifdef USE_PRAGMA_IMPLEMENTATION +#pragma implementation // gcc: Class implementation +#endif + +#include "mariadb.h" +#include "sql_priv.h" +#include "my_json_writer.h" +#include "opt_rewrite_date_cmp.h" + +Date_cmp_func_rewriter::Date_cmp_func_rewriter(THD* thd, + Item_func_eq *item_func) : + thd(thd), + result(item_func) +{ + if (!check_cond_match_and_prepare(item_func)) + return; + + /* + This is an equality. Do a rewrite like this: + "YEAR(col) = val" -> col BETWEEN year_start(val) AND year_end(val) + "DATE(col) = val" -> col BETWEEN day_start(val) AND day_end(val) + */ + Item *start_bound, *end_bound; + if (!(start_bound= create_start_bound()) || !(end_bound= create_end_bound())) + return; + Item *new_cond; + if (!(new_cond= new (thd->mem_root) Item_func_between(thd, field_ref, + start_bound, end_bound))) + return; + if (!new_cond->fix_fields(thd, &new_cond)) + result= new_cond; +} + + +Date_cmp_func_rewriter::Date_cmp_func_rewriter(THD* thd, + Item_func_ge *item_func) : + thd(thd), + result(item_func) +{ + if (!check_cond_match_and_prepare(item_func)) + return; + rewrite_le_gt_lt_ge(); +} + + +Date_cmp_func_rewriter::Date_cmp_func_rewriter(THD* thd, + Item_func_lt *item_func) : + thd(thd), + result(item_func) +{ + if (!check_cond_match_and_prepare(item_func)) + return; + rewrite_le_gt_lt_ge(); +} + + +Date_cmp_func_rewriter::Date_cmp_func_rewriter(THD* thd, + Item_func_gt *item_func) : + thd(thd), + result(item_func) +{ + if (!check_cond_match_and_prepare(item_func)) + return; + rewrite_le_gt_lt_ge(); +} + + +Date_cmp_func_rewriter::Date_cmp_func_rewriter(THD* thd, + Item_func_le*item_func) : + thd(thd), + result(item_func) +{ + if (!check_cond_match_and_prepare(item_func)) + return; + rewrite_le_gt_lt_ge(); +} + + +bool Date_cmp_func_rewriter::check_cond_match_and_prepare( + Item_bool_rowready_func2 *item_func) +{ + if (thd->lex->is_ps_or_view_context_analysis()) + { + DBUG_ASSERT(0); + return false; + } + + Item **args= item_func->arguments(); + rewrite_func_type= item_func->functype(); + bool condition_matches= false; + const Type_handler *comparison_type= item_func->get_comparator()-> + compare_type_handler(); + + /* + Check if this is "YEAR(indexed_col) CMP const_item" or + "DATE(indexed_col) CMP const_item" + */ + if ((field_ref= is_date_rounded_field(args[0], comparison_type, + &argument_func_type)) && + args[1]->basic_const_item()) + { + const_arg_value= args[1]; + condition_matches= true; + } + else + /* + Check if this is "const_item CMP YEAR(indexed_col)" or + "const_item CMP DATE(indexed_col)" + */ + if ((field_ref= is_date_rounded_field(args[1], comparison_type, + &argument_func_type)) && + args[0]->basic_const_item()) + { + /* + Ok, the condition has form like "const<YEAR(col)"/"const<DATE(col)". + Turn it around to be "YEAR(col)>const"/"DATE(col)>const" + */ + const_arg_value= args[0]; + + rewrite_func_type= item_func->rev_functype(); + condition_matches= true; + } + return condition_matches; +} + +/* + Check if the passed item is YEAR(key_col) or DATE(key_col). + + Also + - key_col must be covered by an index usable by the current query + - key_col must have a DATE[TIME] or TIMESTAMP type + - The value of the YEAR(..) or DATE(..) function must be compared using an a + appropriate comparison_type. + + @param item IN Item to check + @param comparison_type IN Which datatype is used to compare the item value + @param out_func_type OUT Function (is it YEAR or DATE) + + @return + key_col if the check suceeded + NULL otherwise +*/ +Item_field *Date_cmp_func_rewriter::is_date_rounded_field(Item* item, + const Type_handler *comparison_type, + Item_func::Functype *out_func_type) const +{ + if (item->type() != Item::FUNC_ITEM) + return nullptr; + + Item_func::Functype func_type= ((Item_func*)item)->functype(); + bool function_ok= false; + switch (func_type) { + case Item_func::YEAR_FUNC: + // The value of YEAR(x) must be compared as integer + if (comparison_type == &type_handler_slonglong) + function_ok= true; + break; + case Item_func::DATE_FUNC: + // The value of DATE(x) must be compared as dates. + if (comparison_type == &type_handler_newdate) + function_ok= true; + break; + default: + ;// do nothing + } + + if (function_ok) + { + Item* arg= ((Item_func*)item)->arguments()[0]; + // Check if the argument is a column that's covered by some index + if (arg->real_item()->type() == Item::FIELD_ITEM) + { + Item_field *item_field= (Item_field*)(arg->real_item()); + enum_field_types field_type= item_field->field_type(); + if ((field_type == MYSQL_TYPE_DATE || + field_type == MYSQL_TYPE_DATETIME || + field_type == MYSQL_TYPE_NEWDATE || + field_type == MYSQL_TYPE_TIMESTAMP) && + item_field->field->flags & PART_KEY_FLAG) + { + *out_func_type= func_type; + return item_field; + } + } + } + return nullptr; +} + + +void Date_cmp_func_rewriter::rewrite_le_gt_lt_ge() +{ + if (rewrite_func_type == Item_func::LE_FUNC || + rewrite_func_type == Item_func::GT_FUNC) + { + const_arg_value= create_end_bound(); + } + else if (rewrite_func_type == Item_func::LT_FUNC || + rewrite_func_type == Item_func::GE_FUNC) + { + const_arg_value= create_start_bound(); + } + if (!const_arg_value) + return; + Item *repl= create_cmp_func(rewrite_func_type, field_ref, const_arg_value); + if (!repl) + return; + if (!repl->fix_fields(thd, &repl)) + result= repl; +} + + +Item *Date_cmp_func_rewriter::create_start_bound() +{ + Item_datetime *res; + MYSQL_TIME const_arg_ts; + memset(&const_arg_ts, 0, sizeof(const_arg_ts)); + const_arg_ts.time_type= MYSQL_TIMESTAMP_DATETIME; + switch (argument_func_type) { + case Item_func::YEAR_FUNC: + const_arg_ts.year= static_cast<unsigned int>(const_arg_value->val_int()); + const_arg_ts.month= 1; + const_arg_ts.day= 1; + if (check_datetime_range(&const_arg_ts)) + return nullptr; + res= new (thd->mem_root) Item_datetime(thd); + res->set(&const_arg_ts); + break; + case Item_func::DATE_FUNC: + if (field_ref->field->type() == MYSQL_TYPE_DATE) + return const_arg_value; + else + { + Datetime const_arg_dt(current_thd, const_arg_value); + if (!const_arg_dt.is_valid_datetime()) + return nullptr; + res= new (thd->mem_root) Item_datetime(thd); + const_arg_dt.copy_to_mysql_time(&const_arg_ts); + const_arg_ts.second_part= const_arg_ts.second= + const_arg_ts.minute= const_arg_ts.hour= 0; + const_arg_ts.time_type= MYSQL_TIMESTAMP_DATETIME; + res->set(&const_arg_ts); + } + break; + default: + DBUG_ASSERT(0); + res= nullptr; + break; + } + return res; +} + + +Item *Date_cmp_func_rewriter::create_end_bound() +{ + Item_datetime *res; + MYSQL_TIME const_arg_ts; + memset(&const_arg_ts, 0, sizeof(const_arg_ts)); + const_arg_ts.time_type= MYSQL_TIMESTAMP_DATETIME; + switch (argument_func_type) { + case Item_func::YEAR_FUNC: + const_arg_ts.year= static_cast<unsigned int>(const_arg_value->val_int()); + const_arg_ts.month= 12; + const_arg_ts.day= 31; + const_arg_ts.hour= 23; + const_arg_ts.minute= TIME_MAX_MINUTE; + const_arg_ts.second= TIME_MAX_SECOND; + const_arg_ts.second_part= TIME_MAX_SECOND_PART; + if (check_datetime_range(&const_arg_ts)) + return nullptr; + res= new (thd->mem_root) Item_datetime(thd); + res->set(&const_arg_ts); + break; + case Item_func::DATE_FUNC: + if (field_ref->field->type() == MYSQL_TYPE_DATE) + return const_arg_value; + else + { + res= new (thd->mem_root) Item_datetime(thd); + Datetime const_arg_dt(current_thd, const_arg_value); + if (!const_arg_dt.is_valid_datetime()) + return nullptr; + const_arg_dt.copy_to_mysql_time(&const_arg_ts); + const_arg_ts.hour= 23; + const_arg_ts.minute= TIME_MAX_MINUTE; + const_arg_ts.second= TIME_MAX_SECOND; + const_arg_ts.second_part=TIME_MAX_SECOND_PART; + const_arg_ts.time_type= MYSQL_TIMESTAMP_DATETIME; + res->set(&const_arg_ts); + } + break; + default: + DBUG_ASSERT(0); + res= nullptr; + break; + } + return res; +} + + +/* + Create an Item for "arg1 $CMP arg2", where $CMP is specified by func_type. +*/ +Item *Date_cmp_func_rewriter::create_cmp_func(Item_func::Functype func_type, + Item *arg1, Item *arg2) +{ + Item *res; + switch (func_type) { + case Item_func::GE_FUNC: + res= new (thd->mem_root) Item_func_ge(thd, arg1, arg2); + break; + case Item_func::GT_FUNC: + res= new (thd->mem_root) Item_func_gt(thd, arg1, arg2); + break; + case Item_func::LE_FUNC: + res= new (thd->mem_root) Item_func_le(thd, arg1, arg2); + break; + case Item_func::LT_FUNC: + res= new (thd->mem_root) Item_func_lt(thd, arg1, arg2); + break; + default: + DBUG_ASSERT(0); + res= NULL; + } + return res; +} + +void trace_date_item_rewrite(THD *thd, Item *new_item, Item *old_item) +{ + if (new_item != old_item) + { + Json_writer_object trace_wrapper(thd); + trace_wrapper.add("transformation", "date_conds_into_sargable") + .add("before", old_item) + .add("after", new_item); + } +} + diff --git a/sql/opt_rewrite_date_cmp.h b/sql/opt_rewrite_date_cmp.h new file mode 100644 index 00000000000..9f6e1d74ffa --- /dev/null +++ b/sql/opt_rewrite_date_cmp.h @@ -0,0 +1,111 @@ +/* + Copyright (c) 2023, MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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 */ + +#ifndef OPT_REWRITE_DATE_CMP_INCLUDED +#define OPT_REWRITE_DATE_CMP_INCLUDED + +class Item_func_eq; +class Item_func_ge; +class Item_func_gt; +class Item_func_le; +class Item_func_lt; +class Item_bool_rowready_func2; + +/* + @brief Class responsible for rewriting datetime comparison condition. + It rewrites non-sargable conditions into sargable. + + @detail + The intent of this class is to do equivalent rewrites as follows: + + YEAR(col) <= val -> col <= year_end(val) + YEAR(col) < val -> col < year_start(val) + YEAR(col) >= val -> col >= year_start(val) + YEAR(col) > val -> col > year_end(val) + YEAR(col) = val -> col >= year_start(val) AND col<=year_end(val) + + Also the same is done for comparisons with DATE(col): + + DATE(col) <= val -> col <= day_end(val) + + if col has a DATE type (not DATETIME), then the rewrite becomes: + + DATE(col) <= val -> col <= val + + @usage + Date_cmp_func_rewriter rwr(thd, item_func); + Item *new_item= rwr.get_rewrite_result(); + + Returned new_item points to an item that item_func was rewritten to. + new_item already has fixed fields (fix_fields() was called). + If no rewrite happened, new_item points to the initial item_func parameter + + @todo + Also handle conditions in form "YEAR(date_col) BETWEEN 2014 AND 2017" + and "YEAR(col) = c1 AND MONTH(col) = c2" +*/ +class Date_cmp_func_rewriter +{ +public: + Date_cmp_func_rewriter(THD* thd, Item_func_eq *item_func); + + Date_cmp_func_rewriter(THD* thd, Item_func_ge *item_func); + + Date_cmp_func_rewriter(THD* thd, Item_func_gt *item_func); + + Date_cmp_func_rewriter(THD* thd, Item_func_le *item_func); + + Date_cmp_func_rewriter(THD* thd, Item_func_lt *item_func); + + Item* get_rewrite_result() const { return result; } + + Date_cmp_func_rewriter() = delete; + Date_cmp_func_rewriter(const Date_cmp_func_rewriter&) = delete; + Date_cmp_func_rewriter(Date_cmp_func_rewriter&&) = delete; + +private: + bool check_cond_match_and_prepare(Item_bool_rowready_func2 *item_func); + Item_field *is_date_rounded_field(Item* item, + const Type_handler *comparison_type, + Item_func::Functype *out_func_type) const; + void rewrite_le_gt_lt_ge(); + Item *create_start_bound(); + Item *create_end_bound(); + Item *create_cmp_func(Item_func::Functype func_type, Item *arg1, Item *arg2); + + THD *thd= nullptr; + Item *const_arg_value= nullptr; + Item_func::Functype rewrite_func_type= Item_func::UNKNOWN_FUNC; + Item_func::Functype argument_func_type= Item_func::UNKNOWN_FUNC; + Item_field *field_ref= nullptr; + Item *result= nullptr; +}; + + +void trace_date_item_rewrite(THD *thd,Item *new_item, Item *old_item); + +template<typename T> +Item* do_date_conds_transformation(THD *thd, T *item) +{ + Date_cmp_func_rewriter rwr(thd, item); + /* If the rewrite failed for some reason, we get the original item */ + Item *new_item= rwr.get_rewrite_result(); + trace_date_item_rewrite(thd, new_item, item); + return new_item; +} + + +#endif diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 75ec8fb6665..1bdbcf0deb9 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -30,6 +30,8 @@ #include "sql_base.h" #include "sql_const.h" #include "sql_select.h" +#include "sql_update.h" // class Sql_cmd_update +#include "sql_delete.h" // class Sql_cmd_delete #include "filesort.h" #include "opt_subselect.h" #include "sql_test.h" @@ -534,6 +536,48 @@ bool is_materialization_applicable(THD *thd, Item_in_subselect *in_subs, return FALSE; } +/** + @brief Check whether an IN subquery must be excluded from conversion to SJ + + @param thd global context the processed statement + @returns true if the IN subquery must be excluded from conversion to SJ + + @note + Currently a top level IN subquery of an delete statement is not converted + to SJ if the statement contains ORDER BY ... LIMIT or contains RETURNING. + + @todo + The disjunctive members + !((Sql_cmd_update *) cmd)->is_multitable() + !((Sql_cmd_delete *) cmd)->is_multitable() + will be removed when conversions of IN predicands to semi-joins are + fully supported for single-table UPDATE/DELETE statements. +*/ + +bool SELECT_LEX::is_sj_conversion_prohibited(THD *thd) +{ + DBUG_ASSERT(master_unit()->item->substype() == Item_subselect::IN_SUBS); + + SELECT_LEX *outer_sl= outer_select(); + if (outer_sl->outer_select()) + return false; + + Sql_cmd *cmd= thd->lex->m_sql_cmd; + + switch (thd->lex->sql_command) { + case SQLCOM_UPDATE: + return + !((Sql_cmd_update *) cmd)->is_multitable() && + ((Sql_cmd_update *) cmd)->processing_as_multitable_update_prohibited(thd); + case SQLCOM_DELETE: + return + !((Sql_cmd_delete *) cmd)->is_multitable() && + ((Sql_cmd_delete *) cmd)->processing_as_multitable_delete_prohibited(thd); + default: + return false; + } +} + /* Check if we need JOIN::prepare()-phase subquery rewrites and if yes, do them @@ -677,9 +721,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join) 3. Subquery does not have GROUP BY or ORDER BY 4. Subquery does not use aggregate functions or HAVING 5. Subquery predicate is at the AND-top-level of ON/WHERE clause - 6. We are not in a subquery of a single table UPDATE/DELETE that - doesn't have a JOIN (TODO: We should handle this at some - point by switching to multi-table UPDATE/DELETE) + 6. We are not in a subquery of a single-table UPDATE/DELETE that + does not allow conversion to multi-table UPDATE/DELETE 7. We're not in a table-less subquery like "SELECT 1" 8. No execution method was already chosen (by a prepared statement) 9. Parent select is not a table-less select @@ -698,7 +741,7 @@ int check_and_do_in_subquery_rewrites(JOIN *join) !select_lex->group_list.elements && !join->order && // 3 !join->having && !select_lex->with_sum_func && // 4 in_subs->emb_on_expr_nest && // 5 - select_lex->outer_select()->join && // 6 + !select_lex->is_sj_conversion_prohibited(thd) && // 6 parent_unit->first_select()->leaf_tables.elements && // 7 !in_subs->has_strategy() && // 8 select_lex->outer_select()->table_list.first && // 9 @@ -758,7 +801,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join) */ if (in_subs && !in_subs->has_strategy()) { - if (is_materialization_applicable(thd, in_subs, select_lex)) + if (!select_lex->is_sj_conversion_prohibited(thd) && + is_materialization_applicable(thd, in_subs, select_lex)) { in_subs->add_strategy(SUBS_MATERIALIZATION); diff --git a/sql/privilege.h b/sql/privilege.h index a34d3f4a172..2a4a5cec519 100644 --- a/sql/privilege.h +++ b/sql/privilege.h @@ -80,7 +80,7 @@ enum privilege_t: unsigned long long In other files: - static struct show_privileges_st sys_privileges[] - static const char *command_array[] and static uint command_lengths[] - - mysql_system_tables.sql and mysql_system_tables_fix.sql + - mariadb_system_tables.sql and mariadb_system_tables_fix.sql - acl_init() or whatever - to define behaviour for old privilege tables - Update User_table_json::get_access() - sql_yacc.yy - for GRANT/REVOKE to work diff --git a/sql/session_tracker.h b/sql/session_tracker.h index 5715b5837b5..811368fb340 100644 --- a/sql/session_tracker.h +++ b/sql/session_tracker.h @@ -290,9 +290,9 @@ enum enum_tx_state { Transaction access mode */ enum enum_tx_read_flags { - TX_READ_INHERIT = 0, ///< not explicitly set, inherit session.tx_read_only - TX_READ_ONLY = 1, ///< START TRANSACTION READ ONLY, or tx_read_only=1 - TX_READ_WRITE = 2, ///< START TRANSACTION READ WRITE, or tx_read_only=0 + TX_READ_INHERIT = 0, ///< not explicitly set, inherit session.transaction_read_only + TX_READ_ONLY = 1, ///< START TRANSACTION READ ONLY, or transaction_read_only=1 + TX_READ_WRITE = 2, ///< START TRANSACTION READ WRITE, or transaction_read_only=0 }; @@ -300,7 +300,7 @@ enum enum_tx_read_flags { Transaction isolation level */ enum enum_tx_isol_level { - TX_ISOL_INHERIT = 0, ///< not explicitly set, inherit session.tx_isolation + TX_ISOL_INHERIT = 0, ///< not explicitly set, inherit session.transaction_isolation TX_ISOL_UNCOMMITTED = 1, TX_ISOL_COMMITTED = 2, TX_ISOL_REPEATABLE = 3, diff --git a/sql/set_var.cc b/sql/set_var.cc index b49040b8ec3..9fd5aa318c9 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -214,8 +214,9 @@ bool sys_var::update(THD *thd, set_var *var) /* Make sure we don't session-track variables that are not actually - part of the session. tx_isolation and and tx_read_only for example - exist as GLOBAL, SESSION, and one-shot ("for next transaction only"). + part of the session. transaction_isolation and transaction_read_only for + example exist as GLOBAL, SESSION, and one-shot ("for next transaction + only"). */ if ((var->type == OPT_SESSION) && (!ret)) { diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 34a5dad6d3f..8bd961ee140 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -10780,3 +10780,9 @@ ER_CM_OPTION_MISSING_REQUIREMENT eng "CHANGE MASTER TO option '%s=%s' is missing requirement %s" ER_SLAVE_STATEMENT_TIMEOUT 70100 eng "Slave log event execution was interrupted (slave_max_statement_time exceeded)" +ER_JSON_INVALID_VALUE_FOR_KEYWORD + eng "Invalid value for keyword %s" +ER_JSON_SCHEMA_KEYWORD_UNSUPPORTED + eng "%s keyword is not supported" +ER_EVENTS_NO_ACL + eng "Event scheduler cannot function with --skip-grant-tables, --bootstrap, or embedded build" diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 79adaa882ef..8acee122e07 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -47,6 +47,8 @@ #include "sql_prepare.h" #include "sql_statistics.h" #include "sql_cte.h" +#include "sql_update.h" // class Sql_cmd_update +#include "sql_delete.h" // class Sql_cmd_delete #include <m_ctype.h> #include <my_dir.h> #include <hash.h> @@ -1106,7 +1108,11 @@ TABLE_LIST* find_dup_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, (table->table equal to 0) and right names is in current TABLE_LIST object. */ - if (table->table) + if (table->table && + thd->lex->sql_command != SQLCOM_UPDATE && + thd->lex->sql_command != SQLCOM_UPDATE_MULTI && + thd->lex->sql_command != SQLCOM_DELETE && + thd->lex->sql_command != SQLCOM_DELETE_MULTI) { /* All MyISAMMRG children are plain MyISAM tables. */ DBUG_ASSERT(table->table->file->ht->db_type != DB_TYPE_MRG_MYISAM); @@ -1190,16 +1196,42 @@ retry: We come here for queries of type: INSERT INTO t1 (SELECT tmp.a FROM (select * FROM t1) as tmp); - Try to fix by materializing the derived table + Try to fix by materializing the derived table if one can't do without it. */ TABLE_LIST *derived= res->belong_to_derived; if (derived->is_merged_derived() && !derived->derived->is_excluded()) { - DBUG_PRINT("info", + bool materialize= true; + if (thd->lex->sql_command == SQLCOM_UPDATE) + { + Sql_cmd_update *cmd= (Sql_cmd_update *) (thd->lex->m_sql_cmd); + if (cmd->is_multitable() || derived->derived->outer_select()) + materialize= false; + else if (!cmd->processing_as_multitable_update_prohibited(thd)) + { + cmd->set_as_multitable(); + materialize= false; + } + } + else if (thd->lex->sql_command == SQLCOM_DELETE) + { + Sql_cmd_delete *cmd= (Sql_cmd_delete *) (thd->lex->m_sql_cmd); + if (cmd->is_multitable() || derived->derived->outer_select()) + materialize= false; + else if (!cmd->processing_as_multitable_delete_prohibited(thd)) + { + cmd->set_as_multitable(); + materialize= false; + } + } + if (materialize) + { + DBUG_PRINT("info", ("convert merged to materialization to resolve the conflict")); - derived->change_refs_to_fields(); - derived->set_materialized_derived(); - goto retry; + derived->change_refs_to_fields(); + derived->set_materialized_derived(); + goto retry; + } } } DBUG_RETURN(res); @@ -4733,7 +4765,6 @@ restart: if (tbl->file->ha_table_flags() & HA_CAN_MULTISTEP_MERGE) { /* MERGE tables need to access parent and child TABLE_LISTs. */ - DBUG_ASSERT(tbl->pos_in_table_list == tables); if (tbl->file->extra(HA_EXTRA_ATTACH_CHILDREN)) { error= TRUE; @@ -5698,6 +5729,28 @@ bool open_tables_only_view_structure(THD *thd, TABLE_LIST *table_list, } +bool open_tables_for_query(THD *thd, TABLE_LIST *tables, + uint *table_count, uint flags, + DML_prelocking_strategy *prelocking_strategy) +{ + MDL_savepoint mdl_savepoint = thd->mdl_context.mdl_savepoint(); + + DBUG_ASSERT(tables == thd->lex->query_tables); + + if (open_tables(thd, &tables, table_count, + thd->stmt_arena->is_stmt_prepare() ? MYSQL_OPEN_FORCE_SHARED_MDL : 0, + prelocking_strategy)) + { + close_thread_tables(thd); + /* Don't keep locks for a failed statement. */ + thd->mdl_context.rollback_to_savepoint(mdl_savepoint); + return true; + } + + return false; +} + + /* Mark all real tables in the list as free for reuse. @@ -7863,6 +7916,9 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, if (!(*with_wild)) DBUG_RETURN(0); + if (!fields.elements) + DBUG_RETURN(0); + /* Don't use arena if we are not in prepared statements or stored procedures For PS/SP we have to use arena to remember the changes @@ -8133,7 +8189,7 @@ bool setup_table_attributes(THD *thd, TABLE_LIST *table_list, uint &tablenr) { TABLE *table= table_list->table; - if (table) + if (table && !table->pos_in_table_list) table->pos_in_table_list= table_list; if (first_select_table && table_list->top_table() == first_select_table) { @@ -8148,7 +8204,6 @@ bool setup_table_attributes(THD *thd, TABLE_LIST *table_list, } else if (table) { - table->pos_in_table_list= table_list; setup_table_map(table, table_list, tablenr); if (table_list->process_index_hints(table)) diff --git a/sql/sql_base.h b/sql/sql_base.h index 6e17d8214ad..f4a49d99125 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -28,6 +28,7 @@ struct Name_resolution_context; class Open_table_context; class Open_tables_state; class Prelocking_strategy; +class DML_prelocking_strategy; struct TABLE_LIST; class THD; struct handlerton; @@ -288,6 +289,9 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags, bool open_tables_only_view_structure(THD *thd, TABLE_LIST *tables, bool can_deadlock); bool open_and_lock_internal_tables(TABLE *table, bool lock); +bool open_tables_for_query(THD *thd, TABLE_LIST *tables, + uint *table_count, uint flags, + DML_prelocking_strategy *prelocking_strategy); bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags); int decide_logging_format(THD *thd, TABLE_LIST *tables); void close_thread_table(THD *thd, TABLE **table_ptr); @@ -430,6 +434,17 @@ public: }; + +class Multiupdate_prelocking_strategy : public DML_prelocking_strategy +{ + bool done; + bool has_prelocking_list; +public: + void reset(THD *thd); + bool handle_end(THD *thd); +}; + + /** A strategy for prelocking algorithm to be used for LOCK TABLES statement. diff --git a/sql/sql_class.h b/sql/sql_class.h index 75e86bab415..0661eb9014e 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -3505,15 +3505,15 @@ public: /* Current or next transaction isolation level. When a connection is established, the value is taken from - @@session.tx_isolation (default transaction isolation for - the session), which is in turn taken from @@global.tx_isolation - (the global value). + @@session.transaction_isolation (default transaction isolation + for the session), which is in turn taken from + @@global.transaction_isolation (the global value). If there is no transaction started, this variable holds the value of the next transaction's isolation level. When a transaction starts, the value stored in this variable becomes "actual". At transaction commit or rollback, we assign this variable - again from @@session.tx_isolation. + again from @@session.transaction_isolation. The only statement that can otherwise change the value of this variable is SET TRANSACTION ISOLATION LEVEL. Its purpose is to effect the isolation level of the next @@ -3523,13 +3523,13 @@ public: transaction, this assignment (naturally) only affects the upcoming transaction. At the end of the current active transaction the value is - be reset again from @@session.tx_isolation, as described + be reset again from @@session.transaction_isolation, as described above. */ enum_tx_isolation tx_isolation; /* Current or next transaction access mode. - See comment above regarding tx_isolation. + See comment above regarding transaction_isolation. */ bool tx_read_only; enum_check_fields count_cuted_fields; @@ -7133,6 +7133,7 @@ public: enum_duplicates handle_duplicates, bool ignore); ~multi_update(); bool init(THD *thd); + bool init_for_single_table(THD *thd); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); int send_data(List<Item> &items); bool initialize_tables (JOIN *join); @@ -7141,6 +7142,8 @@ public: bool send_eof(); inline ha_rows num_found() const { return found; } inline ha_rows num_updated() const { return updated; } + inline void set_found (ha_rows n) { found= n; } + inline void set_updated (ha_rows n) { updated= n; } virtual void abort_result_set(); void update_used_tables(); void prepare_to_read_rows(); diff --git a/sql/sql_cmd.h b/sql/sql_cmd.h index 2623b3703d3..985be776713 100644 --- a/sql/sql_cmd.h +++ b/sql/sql_cmd.h @@ -118,6 +118,7 @@ enum enum_sql_command { SQLCOM_END }; +struct TABLE_LIST; class Storage_engine_name { @@ -144,6 +145,8 @@ public: }; +class Prepared_statement; + /** @class Sql_cmd - Representation of an SQL command. @@ -180,10 +183,28 @@ public: virtual enum_sql_command sql_command_code() const = 0; /** - Execute this SQL statement. - @param thd the current thread. - @retval false on success. - @retval true on error + @brief Check whether the statement has been prepared + @returns true if this statement is prepared, false otherwise + */ + bool is_prepared() const { return m_prepared; } + + /** + @brief Prepare this SQL statement + @param thd global context the processed statement + @returns false if success, true if error + */ + virtual bool prepare(THD *thd) + { + /* Default behavior for a statement is to have no preparation code. */ + DBUG_ASSERT(!is_prepared()); + set_prepared(); + return false; + } + + /** + @brief Execute this SQL statement + @param thd global context the processed statement + @returns false if success, true if error */ virtual bool execute(THD *thd) = 0; @@ -192,8 +213,40 @@ public: return NULL; } + /** + @brief Set the owning prepared statement + */ + void set_owner(Prepared_statement *stmt) { m_owner = stmt; } + + /** + @breaf Get the owning prepared statement + */ + Prepared_statement *get_owner() { return m_owner; } + + /** + @brief Check whether this command is a DML statement + @return true if SQL command is a DML statement, false otherwise + */ + virtual bool is_dml() const { return false; } + + /** + @brief Unprepare prepared statement for the command + @param thd global context of the processed statement + + @notes + Temporary function used to "unprepare" a prepared statement after + preparation, so that a subsequent execute statement will reprepare it. + This is done because UNIT::cleanup() will un-resolve all resolved QBs. + */ + virtual void unprepare(THD *thd) + { + DBUG_ASSERT(is_prepared()); + m_prepared = false; + } + protected: - Sql_cmd() = default; + Sql_cmd() : m_prepared(false), m_owner(nullptr) + {} virtual ~Sql_cmd() { @@ -203,10 +256,152 @@ protected: simply destroyed instead. Do not rely on the destructor for any cleanup. */ - DBUG_ASSERT(FALSE); + DBUG_ASSERT(false); } + + /** + @brief Set this statement as prepared + */ + void set_prepared() { m_prepared = true; } + + private: + /* True when statement has been prepared */ + bool m_prepared; + /* Owning prepared statement, nullptr if not prepared */ + Prepared_statement *m_owner; + }; +struct LEX; +class select_result; +class Prelocking_strategy; +class DML_prelocking_strategy; +class Protocol; + +/** + @class Sql_cmd_dml - derivative abstract class used for DML statements + + This class is a class derived from Sql_cmd used when processing such + data manipulation commands as SELECT, INSERT, UPDATE, DELETE and others + that operate over some tables. + After the parser phase all these commands are supposed to be processed + by the same schema: + - precheck of the access rights is performed for the used tables + - the used tables are opened + - context analysis phase is performed for the statement + - the used tables are locked + - the statement is optimized and executed + - clean-up is performed for the statement. + This schema is reflected in the function Sql_cmd_dml::execute() that + uses Sql_cmd_dml::prepare is the statement has not been prepared yet. + Precheck of the access right, context analysis are specific for statements + of a certain type. That's why the methods implementing this operations are + declared as abstract in this class. + + @note + Currently this class is used only for UPDATE and DELETE commands. +*/ +class Sql_cmd_dml : public Sql_cmd +{ +public: + + /** + @brief Check whether the statement changes the contents of used tables + @return true if this is data change statement, false otherwise + */ + virtual bool is_data_change_stmt() const { return true; } + + /** + @brief Perform context analysis of the statement + @param thd global context the processed statement + @returns false on success, true on error + */ + virtual bool prepare(THD *thd); + + /** + Execute the processed statement once + @param thd global context the processed statement + @returns false on success, true on error + */ + virtual bool execute(THD *thd); + + virtual bool is_dml() const { return true; } + + select_result *get_result() { return result; } + +protected: + Sql_cmd_dml() + : Sql_cmd(), lex(nullptr), result(nullptr), + m_empty_query(false) + {} + + /** + @brief Check whether query is guaranteed to return no data + @return true if query is guaranteed to return no data, false otherwise + + @todo Also check this for the following cases: + - Empty source for multi-table UPDATE and DELETE. + - Check empty query expression for INSERT + */ + bool is_empty_query() const + { + DBUG_ASSERT(is_prepared()); + return m_empty_query; + } + + /** + @brief Set statement as returning no data + */ + void set_empty_query() { m_empty_query = true; } + + /** + @brief Perform precheck of table privileges for the specific command + @param thd global context the processed statement + @returns false if success, true if false + + @details + Check that user has some relevant privileges for all tables involved in + the statement, e.g. SELECT privileges for tables selected from, INSERT + privileges for tables inserted into, etc. This function will also populate + TABLE_LIST::grant with all privileges the user has for each table, which + is later used during checking of column privileges. + Note that at preparation time, views are not expanded yet. Privilege + checking is thus rudimentary and must be complemented with later calls to + SELECT_LEX::check_view_privileges(). + The reason to call this function at such an early stage is to be able to + quickly reject statements for which the user obviously has insufficient + privileges. + */ + virtual bool precheck(THD *thd) = 0; + + /** + @brief Perform the command-specific actions of the context analysis + @param thd global context the processed statement + @returns false if success, true if error + + @note + This function is called from prepare() + */ + virtual bool prepare_inner(THD *thd) = 0; + + /** + @brief Perform the command-specific actions of optimization and excution + @param thd global context the processed statement + @returns false on success, true on error + */ + virtual bool execute_inner(THD *thd); + + virtual DML_prelocking_strategy *get_dml_prelocking_strategy() = 0; + + uint table_count; + + protected: + LEX *lex; /**< Pointer to LEX for this statement */ + select_result *result; /**< Pointer to object for handling of the result */ + bool m_empty_query; /**< True if query will produce no rows */ +}; + + class Sql_cmd_show_slave_status: public Sql_cmd { protected: diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index ea43b7bbe78..9598a1c58f1 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -44,6 +44,9 @@ // end_read_record #include "sql_insert.h" // fix_rownum_pointers #include "sql_partition.h" // make_used_partitions_str +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif #define MEM_STRIP_BUF_SIZE ((size_t) thd->variables.sortbuff_size) @@ -103,7 +106,7 @@ bool Update_plan::save_explain_data_intern(MEM_ROOT *mem_root, bool is_analyze) { explain->select_type= "SIMPLE"; - explain->table_name.append(&table->pos_in_table_list->alias); + explain->table_name.append(table->alias); explain->impossible_where= false; explain->no_partitions= false; @@ -295,123 +298,85 @@ int TABLE::delete_row() /** - Implement DELETE SQL word. + @brief Special handling of single-table deletes after prepare phase - @note Like implementations of other DDL/DML in MySQL, this function - relies on the caller to close the thread tables. This is done in the - end of dispatch_command(). + @param thd global context the processed statement + @returns false on success, true on error */ -bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, - SQL_I_List<ORDER> *order_list, ha_rows limit, - ulonglong options, select_result *result) +bool Sql_cmd_delete::delete_from_single_table(THD *thd) { - bool will_batch= FALSE; - int error, loc_error; - TABLE *table; - SQL_SELECT *select=0; - SORT_INFO *file_sort= 0; - READ_RECORD info; - bool using_limit=limit != HA_POS_ERROR; - bool transactional_table, safe_update, const_cond; - bool const_cond_result; - bool return_error= 0; - ha_rows deleted= 0; - bool reverse= FALSE; - bool has_triggers= false; - ORDER *order= (ORDER *) ((order_list && order_list->elements) ? - order_list->first : NULL); - SELECT_LEX *select_lex= thd->lex->first_select_lex(); - SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0; + int error; + int loc_error; + bool transactional_table; + bool const_cond; + bool safe_update; + bool const_cond_result; + bool return_error= 0; + TABLE *table; + SQL_SELECT *select= 0; + SORT_INFO *file_sort= 0; + READ_RECORD info; + ha_rows deleted= 0; + bool reverse= FALSE; + bool binlog_is_row; killed_state killed_status= NOT_KILLED; THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE; - bool binlog_is_row; - Explain_delete *explain; + bool will_batch= FALSE; + + bool has_triggers= false; + SELECT_LEX_UNIT *unit = &lex->unit; + SELECT_LEX *select_lex= unit->first_select(); + SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0; + TABLE_LIST *const table_list = select_lex->get_table_list(); + ulonglong options= select_lex->options; + ORDER *order= select_lex->order_list.first; + COND *conds= select_lex->join->conds; + ha_rows limit= unit->lim.get_select_limit(); + bool using_limit= limit != HA_POS_ERROR; + Delete_plan query_plan(thd->mem_root); + Explain_delete *explain; Unique * deltempfile= NULL; bool delete_record= false; - bool delete_while_scanning; + bool delete_while_scanning= table_list->delete_while_scanning; bool portion_of_time_through_update; - DBUG_ENTER("mysql_delete"); + + DBUG_ENTER("Sql_cmd_delete::delete_single_table"); query_plan.index= MAX_KEY; query_plan.using_filesort= FALSE; - create_explain_query(thd->lex, thd->mem_root); - if (open_and_lock_tables(thd, table_list, TRUE, 0)) - DBUG_RETURN(TRUE); - THD_STAGE_INFO(thd, stage_init_update); const bool delete_history= table_list->vers_conditions.delete_history; DBUG_ASSERT(!(delete_history && table_list->period_conditions.is_set())); - if (thd->lex->handle_list_of_derived(table_list, DT_MERGE_FOR_INSERT)) - DBUG_RETURN(TRUE); - if (thd->lex->handle_list_of_derived(table_list, DT_PREPARE)) - DBUG_RETURN(TRUE); + if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT)) + DBUG_RETURN(1); + if (table_list->handle_derived(thd->lex, DT_PREPARE)) + DBUG_RETURN(1); + + table= table_list->table; if (!table_list->single_table_updatable()) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE"); DBUG_RETURN(TRUE); } - if (!(table= table_list->table) || !table->is_created()) + + if (!table || !table->is_created()) { my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), table_list->view_db.str, table_list->view_name.str); DBUG_RETURN(TRUE); } - table->map=1; + query_plan.select_lex= thd->lex->first_select_lex(); query_plan.table= table; thd->lex->promote_select_describe_flag_if_needed(); - if (mysql_prepare_delete(thd, table_list, &conds, &delete_while_scanning)) - DBUG_RETURN(TRUE); - - if (table_list->has_period()) - { - if (!table_list->period_conditions.start.item->const_item() - || !table_list->period_conditions.end.item->const_item()) - { - my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF"); - DBUG_RETURN(true); - } - } - - if (delete_history) - table->vers_write= false; - - if (returning) - (void) result->prepare(returning->item_list, NULL); - - if (thd->lex->current_select->first_cond_optimization) - { - thd->lex->current_select->save_leaf_tables(thd); - thd->lex->current_select->first_cond_optimization= 0; - } - /* check ORDER BY even if it can be ignored */ - if (order) - { - TABLE_LIST tables; - List<Item> fields; - List<Item> all_fields; - - bzero((char*) &tables,sizeof(tables)); - tables.table = table; - tables.alias = table_list->alias; - - if (select_lex->setup_ref_array(thd, order_list->elements) || - setup_order(thd, select_lex->ref_pointer_array, &tables, - fields, all_fields, order)) - { - free_underlaid_joins(thd, thd->lex->first_select_lex()); - DBUG_RETURN(TRUE); - } - } - /* Apply the IN=>EXISTS transformation to all subqueries and optimize them. */ if (select_lex->optimize_unflattened_subqueries(false)) DBUG_RETURN(TRUE); @@ -499,6 +464,12 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, goto produce_explain_and_leave; } } + if (conds && thd->lex->are_date_funcs_used()) + { + /* Rewrite datetime comparison conditions into sargable */ + conds= conds->top_level_transform(thd, &Item::date_conds_transformer, + (uchar *) 0); + } #ifdef WITH_PARTITION_STORAGE_ENGINE if (prune_partitions(thd, table, conds)) @@ -1017,92 +988,6 @@ got_error: } -/* - Prepare items in DELETE statement - - SYNOPSIS - mysql_prepare_delete() - thd - thread handler - table_list - global/local table list - conds - conditions - - RETURN VALUE - FALSE OK - TRUE error -*/ -int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds, - bool *delete_while_scanning) -{ - Item *fake_conds= 0; - SELECT_LEX *select_lex= thd->lex->first_select_lex(); - DBUG_ENTER("mysql_prepare_delete"); - List<Item> all_fields; - - *delete_while_scanning= true; - thd->lex->allow_sum_func.clear_all(); - if (setup_tables_and_check_access(thd, &select_lex->context, - &select_lex->top_join_list, table_list, - select_lex->leaf_tables, FALSE, - DELETE_ACL, SELECT_ACL, TRUE)) - DBUG_RETURN(TRUE); - - if (table_list->vers_conditions.is_set() && table_list->is_view_or_derived()) - { - my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str); - DBUG_RETURN(true); - } - - if (table_list->has_period()) - { - if (table_list->is_view_or_derived()) - { - my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str); - DBUG_RETURN(true); - } - - if (select_lex->period_setup_conds(thd, table_list)) - DBUG_RETURN(true); - } - - DBUG_ASSERT(table_list->table); - // conds could be cached from previous SP call - DBUG_ASSERT(!table_list->vers_conditions.need_setup() || - !*conds || thd->stmt_arena->is_stmt_execute()); - if (select_lex->vers_setup_conds(thd, table_list)) - DBUG_RETURN(TRUE); - - *conds= select_lex->where; - - if (setup_returning_fields(thd, table_list) || - setup_conds(thd, table_list, select_lex->leaf_tables, conds) || - setup_ftfuncs(select_lex)) - DBUG_RETURN(TRUE); - if (!table_list->single_table_updatable() || - check_key_in_view(thd, table_list)) - { - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE"); - DBUG_RETURN(TRUE); - } - - /* - Application-time periods: if FOR PORTION OF ... syntax used, DELETE - statement could issue delete_row's mixed with write_row's. This causes - problems for myisam and corrupts table, if deleting while scanning. - */ - if (table_list->has_period() - || unique_table(thd, table_list, table_list->next_global, 0)) - *delete_while_scanning= false; - - if (select_lex->inner_refs_list.elements && - fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array)) - DBUG_RETURN(TRUE); - - select_lex->fix_prepare_information(thd, conds, &fake_conds); - if (!thd->lex->upd_del_where) - thd->lex->upd_del_where= *conds; - DBUG_RETURN(FALSE); -} - /*************************************************************************** Delete multiple tables from join @@ -1115,106 +1000,6 @@ extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b) return file->cmp_ref((const uchar*)a, (const uchar*)b); } -/* - make delete specific preparation and checks after opening tables - - SYNOPSIS - mysql_multi_delete_prepare() - thd thread handler - - RETURN - FALSE OK - TRUE Error -*/ - -int mysql_multi_delete_prepare(THD *thd) -{ - LEX *lex= thd->lex; - TABLE_LIST *aux_tables= lex->auxiliary_table_list.first; - TABLE_LIST *target_tbl; - DBUG_ENTER("mysql_multi_delete_prepare"); - - if (mysql_handle_derived(lex, DT_INIT)) - DBUG_RETURN(TRUE); - if (mysql_handle_derived(lex, DT_MERGE_FOR_INSERT)) - DBUG_RETURN(TRUE); - if (mysql_handle_derived(lex, DT_PREPARE)) - DBUG_RETURN(TRUE); - /* - setup_tables() need for VIEWs. JOIN::prepare() will not do it second - time. - - lex->query_tables also point on local list of DELETE SELECT_LEX - */ - if (setup_tables_and_check_access(thd, - &thd->lex->first_select_lex()->context, - &thd->lex->first_select_lex()-> - top_join_list, - lex->query_tables, - lex->first_select_lex()->leaf_tables, - FALSE, DELETE_ACL, SELECT_ACL, FALSE)) - DBUG_RETURN(TRUE); - - /* - Multi-delete can't be constructed over-union => we always have - single SELECT on top and have to check underlying SELECTs of it - */ - lex->first_select_lex()->set_unique_exclude(); - /* Fix tables-to-be-deleted-from list to point at opened tables */ - for (target_tbl= (TABLE_LIST*) aux_tables; - target_tbl; - target_tbl= target_tbl->next_local) - { - - target_tbl->table= target_tbl->correspondent_table->table; - if (target_tbl->correspondent_table->is_multitable()) - { - my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), - target_tbl->correspondent_table->view_db.str, - target_tbl->correspondent_table->view_name.str); - DBUG_RETURN(TRUE); - } - - if (!target_tbl->correspondent_table->single_table_updatable() || - check_key_in_view(thd, target_tbl->correspondent_table)) - { - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), - target_tbl->table_name.str, "DELETE"); - DBUG_RETURN(TRUE); - } - } - - for (target_tbl= (TABLE_LIST*) aux_tables; - target_tbl; - target_tbl= target_tbl->next_local) - { - /* - Check that table from which we delete is not used somewhere - inside subqueries/view. - */ - { - TABLE_LIST *duplicate; - if ((duplicate= unique_table(thd, target_tbl->correspondent_table, - lex->query_tables, 0))) - { - update_non_unique_table_error(target_tbl->correspondent_table, - "DELETE", duplicate); - DBUG_RETURN(TRUE); - } - } - } - /* - Reset the exclude flag to false so it doesn't interfare - with further calls to unique_table - */ - lex->first_select_lex()->exclude_from_table_unique_test= FALSE; - - if (lex->save_prep_leaf_tables()) - DBUG_RETURN(TRUE); - - DBUG_RETURN(FALSE); -} - multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables_arg): select_result_interceptor(thd_arg), delete_tables(dt), deleted(0), found(0), @@ -1340,6 +1125,8 @@ multi_delete::~multi_delete() table_being_deleted= table_being_deleted->next_local) { TABLE *table= table_being_deleted->table; + if (!table) + continue; table->no_keyread=0; table->no_cache= 0; } @@ -1669,3 +1456,367 @@ bool multi_delete::send_eof() } return 0; } + + +/** + @brief Remove ORDER BY from DELETE if it's used without limit clause +*/ + +void Sql_cmd_delete::remove_order_by_without_limit(THD *thd) +{ + SELECT_LEX *const select_lex = thd->lex->first_select_lex(); + if (select_lex->order_list.elements && + !select_lex->limit_params.select_limit) + select_lex->order_list.empty(); +} + + +/** + @brief Check whether processing to multi-table delete is prohibited + + @param thd global context the processed statement + @returns true if processing as multitable is prohibited, false otherwise + + @todo + Introduce handler level flag for storage engines that would prohibit + such conversion for any single-table delete. +*/ + +bool Sql_cmd_delete::processing_as_multitable_delete_prohibited(THD *thd) +{ + SELECT_LEX *const select_lex = thd->lex->first_select_lex(); + return + ((select_lex->order_list.elements && + select_lex->limit_params.select_limit) || + thd->lex->has_returning()); +} + + +/** + @brief Perform precheck of table privileges for delete statements + + @param thd global context the processed statement + @returns false on success, true on error +*/ + +bool Sql_cmd_delete::precheck(THD *thd) +{ + if (!multitable) + { + if (delete_precheck(thd, lex->query_tables)) + return true; + } + else + { + if (multi_delete_precheck(thd, lex->query_tables)) + return true; + } + +#ifdef WITH_WSREP + WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE); +#endif + + return false; + +#ifdef WITH_WSREP +wsrep_error_label: +#endif + return true; +} + + +/** + @brief Perform context analysis for delete statements + + @param thd global context the processed statement + @returns false on success, true on error + + @note + The main bulk of the context analysis actions for a delete statement + is performed by a call of JOIN::prepare(). +*/ + +bool Sql_cmd_delete::prepare_inner(THD *thd) +{ + int err= 0; + TABLE_LIST *target_tbl; + JOIN *join; + SELECT_LEX *const select_lex = thd->lex->first_select_lex(); + TABLE_LIST *const table_list = select_lex->get_table_list(); + TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first; + ulonglong select_options= select_lex->options; + bool free_join= 1; + SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0; + const bool delete_history= table_list->vers_conditions.delete_history; + DBUG_ASSERT(!(delete_history && table_list->period_conditions.is_set())); + + DBUG_ENTER("Sql_cmd_delete::prepare_inner"); + + (void) read_statistics_for_tables_if_needed(thd, table_list); + + THD_STAGE_INFO(thd, stage_init_update); + + { + if (mysql_handle_derived(lex, DT_INIT)) + DBUG_RETURN(TRUE); + if (mysql_handle_derived(lex, DT_MERGE_FOR_INSERT)) + DBUG_RETURN(TRUE); + if (mysql_handle_derived(lex, DT_PREPARE)) + DBUG_RETURN(TRUE); + } + + if (!(result= new (thd->mem_root) multi_delete(thd, aux_tables, + lex->table_count_update))) + { + DBUG_RETURN(TRUE); + } + + table_list->delete_while_scanning= true; + + if (!multitable && !table_list->single_table_updatable()) + { + my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE"); + DBUG_RETURN(TRUE); + } + + if (!multitable && (!table_list->table || !table_list->table->is_created())) + { + my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), + table_list->view_db.str, table_list->view_name.str); + DBUG_RETURN(TRUE); + } + + if (setup_tables_and_check_access(thd, &select_lex->context, + &select_lex->top_join_list, + table_list, select_lex->leaf_tables, + false, DELETE_ACL, SELECT_ACL, true)) + DBUG_RETURN(TRUE); + + if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list, + table_list, select_lex->leaf_tables, false, false)) + DBUG_RETURN(TRUE); + + if (!multitable) + { + if (table_list->vers_conditions.is_set() && table_list->is_view_or_derived()) + { + my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str); + DBUG_RETURN(true); + } + + if (!multitable) + { + TABLE_LIST *update_source_table= 0; + if (((update_source_table=unique_table(thd, table_list, + table_list->next_global, 0)) || + table_list->is_multitable())) + { + DBUG_ASSERT(update_source_table || table_list->view != 0); + if (!table_list->is_multitable() && + !processing_as_multitable_delete_prohibited(thd)) + { + multitable= true; + remove_order_by_without_limit(thd); + } + } + } + + if (table_list->has_period()) + { + if (table_list->is_view_or_derived()) + { + my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str); + DBUG_RETURN(true); + } + + if (select_lex->period_setup_conds(thd, table_list)) + DBUG_RETURN(true); + } + + if (select_lex->vers_setup_conds(thd, table_list)) + DBUG_RETURN(TRUE); + /* + Application-time periods: if FOR PORTION OF ... syntax used, DELETE + statement could issue delete_row's mixed with write_row's. This causes + problems for myisam and corrupts table, if deleting while scanning. + */ + if (table_list->has_period() + || unique_table(thd, table_list, table_list->next_global, 0)) + table_list->delete_while_scanning= false; + } + + { + if (thd->lex->describe) + select_options|= SELECT_DESCRIBE; + + /* + When in EXPLAIN, delay deleting the joins so that they are still + available when we're producing EXPLAIN EXTENDED warning text. + */ + if (select_options & SELECT_DESCRIBE) + free_join= 0; + select_options|= + SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | OPTION_SETUP_TABLES_DONE; + + if (!(join= new (thd->mem_root) JOIN(thd, empty_list, + select_options, result))) + DBUG_RETURN(TRUE); + THD_STAGE_INFO(thd, stage_init); + select_lex->join= join; + thd->lex->used_tables=0; + if ((err= join->prepare(table_list, select_lex->where, + select_lex->order_list.elements, + select_lex->order_list.first, + false, NULL, NULL, NULL, + select_lex, &lex->unit))) + + { + goto err; + } + + if (!multitable && + select_lex->sj_subselects.elements) + multitable= true; + } + + if (multitable) + { + /* + Multi-delete can't be constructed over-union => we always have + single SELECT on top and have to check underlying SELECTs of it + */ + lex->first_select_lex()->set_unique_exclude(); + /* Fix tables-to-be-deleted-from list to point at opened tables */ + for (target_tbl= (TABLE_LIST*) aux_tables; + target_tbl; + target_tbl= target_tbl->next_local) + { + target_tbl->table= target_tbl->correspondent_table->table; + if (target_tbl->correspondent_table->is_multitable()) + { + my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), + target_tbl->correspondent_table->view_db.str, + target_tbl->correspondent_table->view_name.str); + DBUG_RETURN(TRUE); + } + + if (!target_tbl->correspondent_table->single_table_updatable() || + check_key_in_view(thd, target_tbl->correspondent_table)) + { + my_error(ER_NON_UPDATABLE_TABLE, MYF(0), + target_tbl->table_name.str, "DELETE"); + DBUG_RETURN(TRUE); + } + } + + /* + Reset the exclude flag to false so it doesn't interfare + with further calls to unique_table + */ + lex->first_select_lex()->exclude_from_table_unique_test= FALSE; + } + + if (!multitable && table_list->has_period()) + { + if (!table_list->period_conditions.start.item->const_item() + || !table_list->period_conditions.end.item->const_item()) + { + my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF"); + DBUG_RETURN(true); + } + } + + if (delete_history) + table_list->table->vers_write= false; + + if (setup_returning_fields(thd, table_list) || + setup_ftfuncs(select_lex)) + goto err; + + free_join= false; + + if (returning) + (void) result->prepare(returning->item_list, NULL); + +err: + + if (free_join) + { + THD_STAGE_INFO(thd, stage_end); + err|= (int)(select_lex->cleanup()); + DBUG_RETURN(err || thd->is_error()); + } + DBUG_RETURN(err); + +} + + +/** + @brief Perform optimization and execution actions needed for deletes + + @param thd global context the processed statement + @returns false on success, true on error +*/ + +bool Sql_cmd_delete::execute_inner(THD *thd) +{ + if (!multitable) + { + if (lex->has_returning()) + { + select_result *sel_result= NULL; + delete result; + /* This is DELETE ... RETURNING. It will return output to the client */ + if (thd->lex->analyze_stmt) + { + /* + Actually, it is ANALYZE .. DELETE .. RETURNING. We need to produce + output and then discard it. + */ + sel_result= new (thd->mem_root) select_send_analyze(thd); + save_protocol= thd->protocol; + thd->protocol= new Protocol_discard(thd); + } + else + { + if (!lex->result && !(sel_result= new (thd->mem_root) select_send(thd))) + return true; + } + result= lex->result ? lex->result : sel_result; + } + } + + bool res= multitable ? Sql_cmd_dml::execute_inner(thd) + : delete_from_single_table(thd); + + res|= thd->is_error(); + + if (save_protocol) + { + delete thd->protocol; + thd->protocol= save_protocol; + } + { + if (unlikely(res)) + { + if (multitable) + result->abort_result_set(); + } + else + { + if (thd->lex->describe || thd->lex->analyze_stmt) + { + bool extended= thd->lex->describe & DESCRIBE_EXTENDED; + res= thd->lex->explain->send_explain(thd, extended); + } + } + } + + if (result) + { + res= false; + delete result; + } + + return res; +} diff --git a/sql/sql_delete.h b/sql/sql_delete.h index 520524c72cc..1842c5c04c7 100644 --- a/sql/sql_delete.h +++ b/sql/sql_delete.h @@ -17,6 +17,9 @@ #define SQL_DELETE_INCLUDED #include "my_base.h" /* ha_rows */ +#include "sql_class.h" /* enum_duplicates */ +#include "sql_cmd.h" // Sql_cmd_dml +#include "sql_base.h" class THD; struct TABLE_LIST; @@ -26,10 +29,79 @@ class select_result; typedef class Item COND; template <typename T> class SQL_I_List; -int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds, - bool *delete_while_scanning); -bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, - SQL_I_List<ORDER> *order, ha_rows rows, - ulonglong options, select_result *result); +/** + @class Sql_cmd_delete - class used for any DELETE statements + This class is derived from Sql_cmd_dml and contains implementations + for abstract virtual function of the latter such as precheck() and + prepare_inner(). It also overrides the implementation of execute_inner() + providing a special handling for single-table delete statements that + are not converted to multi-table delete. + The class provides an object of the DML_prelocking_strategy class + for the virtual function get_dml_prelocking_strategy(). +*/ +class Sql_cmd_delete final : public Sql_cmd_dml +{ +public: + Sql_cmd_delete(bool multitable_arg) + : orig_multitable(multitable_arg), multitable(multitable_arg), + save_protocol(NULL) + {} + + enum_sql_command sql_command_code() const override + { + return orig_multitable ? SQLCOM_DELETE_MULTI : SQLCOM_DELETE; + } + + DML_prelocking_strategy *get_dml_prelocking_strategy() override + { + return &dml_prelocking_strategy; + } + + bool processing_as_multitable_delete_prohibited(THD *thd); + + bool is_multitable() const { return multitable; } + + void set_as_multitable() { multitable= true; } + + void remove_order_by_without_limit(THD *thd); + +protected: + /** + @brief Perform precheck of table privileges for delete statements + */ + bool precheck(THD *thd) override; + + /** + @brief Perform context analysis for delete statements + */ + bool prepare_inner(THD *thd) override; + + /** + @brief Perform optimization and execution actions needed for deletes + */ + bool execute_inner(THD *thd) override; + + private: + /** + @biefSpecial handling of single-table deletes after prepare phase + */ + bool delete_from_single_table(THD *thd); + + /* Original value of the 'multitable' flag set by constructor */ + const bool orig_multitable; + + /* + True if the statement is a multitable delete or converted to such. + For a single-table delete this flag is set to true if the statement + is supposed to be converted to multi-table delete. + */ + bool multitable; + + /* The prelocking strategy used when opening the used tables */ + DML_prelocking_strategy dml_prelocking_strategy; + + List<Item> empty_list; /**< auxiliary empty list used by prepare_inner() */ + Protocol *save_protocol; /**< needed for ANALYZE .. DELETE .. RETURNING */ +}; #endif /* SQL_DELETE_INCLUDED */ diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 0c2fc0f691a..5206a43f5eb 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -441,7 +441,7 @@ bool sp_create_assignment_instr(THD *thd, bool no_lookahead, - This query: SET TRANSACTION READ ONLY, ISOLATION LEVEL SERIALIZABLE; in translated to: - SET tx_read_only=1, tx_isolation=ISO_SERIALIZABLE; + SET transaction_read_only=1, transaction_isolation=ISO_SERIALIZABLE; but produces a single sp_create_assignment_instr() call which includes the query fragment covering both options. */ @@ -1305,6 +1305,8 @@ void LEX::start(THD *thd_arg) wild= 0; exchange= 0; + table_count_update= 0; + DBUG_VOID_RETURN; } @@ -3034,6 +3036,7 @@ void st_select_lex::init_select() versioned_tables= 0; is_tvc_wrapper= false; nest_flags= 0; + item_list_usage= MARK_COLUMNS_READ; } /* @@ -3291,34 +3294,6 @@ void st_select_lex_unit::exclude_level() } -#if 0 -/* - Exclude subtree of current unit from tree of SELECTs - - SYNOPSYS - st_select_lex_unit::exclude_tree() -*/ -void st_select_lex_unit::exclude_tree() -{ - for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) - { - // unlink current level from global SELECTs list - if (sl->link_prev && (*sl->link_prev= sl->link_next)) - sl->link_next->link_prev= sl->link_prev; - - // unlink underlay levels - for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit()) - { - u->exclude_level(); - } - } - // exclude currect unit from list of nodes - (*prev)= next; - if (next) - next->prev= prev; -} -#endif - /* st_select_lex_node::mark_as_dependent mark all st_select_lex struct from @@ -3540,7 +3515,7 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) select_n_where_fields + order_group_num + hidden_bit_fields + - fields_in_window_functions) * (size_t) 5; + fields_in_window_functions + 1) * (size_t) 5; DBUG_ASSERT(n_elems % 5 == 0); if (!ref_pointer_array.is_null()) { @@ -4051,10 +4026,6 @@ bool LEX::can_use_merged() SYNOPSIS LEX::can_not_use_merged() - @param no_update_or_delete Set to 1 if we can't use merge with multiple-table - updates, like when used from - TALE_LIST::init_derived() - DESCRIPTION Temporary table algorithm will be used on all SELECT levels for queries listed here (see also LEX::can_use_merged()). diff --git a/sql/sql_lex.h b/sql/sql_lex.h index a7231b92cd6..adb887be380 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -37,6 +37,7 @@ #include "json_table.h" // Json_table_column #include "sql_schema.h" #include "table.h" +#include "sql_class.h" // enum enum_column_usage /* Used for flags of nesting constructs */ #define SELECT_NESTING_MAP_SIZE 64 @@ -875,6 +876,8 @@ public: { } + void set_query_result(select_result *res) { result= res; } + TABLE *table; /* temporary table using for appending UNION results */ select_result *result; st_select_lex *pre_last_parse; @@ -1007,6 +1010,7 @@ public: bool add_fake_select_lex(THD *thd); void init_prepare_fake_select_lex(THD *thd, bool first_execution); + void set_prepared() { prepared = true; } inline bool is_prepared() { return prepared; } bool change_result(select_result_interceptor *result, select_result_interceptor *old_result); @@ -1114,6 +1118,7 @@ public: Item *prep_having;/* saved HAVING clause for prepared statement processing */ Item *cond_pushed_into_where; /* condition pushed into WHERE */ Item *cond_pushed_into_having; /* condition pushed into HAVING */ + Item *where_cond_after_prepare; /* nest_levels are local to the query or VIEW, @@ -1224,6 +1229,7 @@ public: List<List_item> save_many_values; List<Item> *save_insert_list; + enum_column_usage item_list_usage; bool is_item_list_lookup:1; /* Needed to correctly generate 'PRIMARY' or 'SIMPLE' for select_type column @@ -1655,6 +1661,7 @@ public: void lex_start(LEX *plex); bool is_unit_nest() { return (nest_flags & UNIT_NEST_FL); } void mark_as_unit_nest() { nest_flags= UNIT_NEST_FL; } + bool is_sj_conversion_prohibited(THD *thd); }; typedef class st_select_lex SELECT_LEX; @@ -1763,12 +1770,31 @@ public: Sroutine_hash_entry **sroutines_list_own_last; uint sroutines_list_own_elements; + /** + Locking state of tables in this particular statement. + + If we under LOCK TABLES or in prelocked mode we consider tables + for the statement to be "locked" if there was a call to lock_tables() + (which called handler::start_stmt()) for tables of this statement + and there was no matching close_thread_tables() call. + + As result this state may differ significantly from one represented + by Open_tables_state::lock/locked_tables_mode more, which are always + "on" under LOCK TABLES or in prelocked mode. + */ + enum enum_lock_tables_state { LTS_NOT_LOCKED = 0, LTS_LOCKED }; + enum_lock_tables_state lock_tables_state; + bool is_query_tables_locked() const + { + return (lock_tables_state == LTS_LOCKED); + } + /* These constructor and destructor serve for creation/destruction of Query_tables_list instances which are used as backup storage. */ - Query_tables_list() = default; - ~Query_tables_list() = default; + Query_tables_list() : lock_tables_state(LTS_NOT_LOCKED) {} + ~Query_tables_list() {} /* Initializes (or resets) Query_tables_list object for "real" use. */ void reset_query_tables_list(bool init); @@ -2331,6 +2357,20 @@ public: bool uses_stored_routines() const { return sroutines_list.elements != 0; } + void set_date_funcs_used_flag() + { + date_funcs_used_flag= true; + } + + /* + Returns TRUE if date functions such as YEAR(), MONTH() or DATE() + are used in this LEX + */ + bool are_date_funcs_used() const + { + return date_funcs_used_flag; + } + private: /** @@ -2371,6 +2411,12 @@ private: be accessed while executing a statement. */ uint32 stmt_accessed_table_flag; + + /* + Flag indicating that date functions such as YEAR(), MONTH() or DATE() are + used in this LEX + */ + bool date_funcs_used_flag= false; }; @@ -3397,6 +3443,7 @@ public: bool default_used:1; /* using default() function */ bool with_rownum:1; /* Using rownum() function */ bool is_lex_started:1; /* If lex_start() did run. For debugging. */ + /* This variable is used in post-parse stage to declare that sum-functions, or functions which have sense only if GROUP BY is present, are allowed. diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 80621685ea2..5dccd3c12ae 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -34,9 +34,7 @@ #include "sql_locale.h" // my_locale_en_US #include "log.h" // flush_error_log #include "sql_view.h" // mysql_create_view, mysql_drop_view -#include "sql_delete.h" // mysql_delete #include "sql_insert.h" // mysql_insert -#include "sql_update.h" // mysql_update, mysql_multi_update #include "sql_partition.h" // struct partition_info #include "sql_db.h" // mysql_change_db, mysql_create_db, // mysql_rm_db, mysql_upgrade_db, @@ -3445,7 +3443,6 @@ int mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt) { int res= 0; - int up_result= 0; LEX *lex= thd->lex; /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */ SELECT_LEX *select_lex= lex->first_select_lex(); @@ -3457,7 +3454,6 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt) SELECT_LEX_UNIT *unit= &lex->unit; #ifdef HAVE_REPLICATION /* have table map for update for multi-update statement (BUG#37051) */ - bool have_table_map_for_update= FALSE; /* */ Rpl_filter *rpl_filter; #endif @@ -3579,7 +3575,6 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt) if (lex->sql_command == SQLCOM_UPDATE_MULTI && thd->table_map_for_update) { - have_table_map_for_update= TRUE; table_map table_map_for_update= thd->table_map_for_update; uint nr= 0; TABLE_LIST *table; @@ -4388,130 +4383,15 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt) break; } case SQLCOM_UPDATE: - { - WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE); - ha_rows found= 0, updated= 0; - DBUG_ASSERT(first_table == all_tables && first_table != 0); - WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE); - - if (update_precheck(thd, all_tables)) - break; - - /* - UPDATE IGNORE can be unsafe. We therefore use row based - logging if mixed or row based logging is available. - TODO: Check if the order of the output of the select statement is - deterministic. Waiting for BUG#42415 - */ - if (lex->ignore) - lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_UPDATE_IGNORE); - - DBUG_ASSERT(select_lex->limit_params.offset_limit == 0); - unit->set_limit(select_lex); - MYSQL_UPDATE_START(thd->query()); - res= up_result= mysql_update(thd, all_tables, - select_lex->item_list, - lex->value_list, - select_lex->where, - select_lex->order_list.elements, - select_lex->order_list.first, - unit->lim.get_select_limit(), - lex->ignore, &found, &updated); - MYSQL_UPDATE_DONE(res, found, updated); - /* mysql_update return 2 if we need to switch to multi-update */ - if (up_result != 2) - break; - if (thd->lex->period_conditions.is_set()) - { - DBUG_ASSERT(0); // Should never happen - goto error; - } - } - /* fall through */ case SQLCOM_UPDATE_MULTI: + case SQLCOM_DELETE: + case SQLCOM_DELETE_MULTI: { DBUG_ASSERT(first_table == all_tables && first_table != 0); - /* if we switched from normal update, rights are checked */ - if (up_result != 2) - { - WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE); - if ((res= multi_update_precheck(thd, all_tables))) - break; - } - else - res= 0; - - unit->set_limit(select_lex); - /* - We can not use mysql_explain_union() because of parameters of - mysql_select in mysql_multi_update so just set the option if needed - */ - if (thd->lex->describe) - { - select_lex->set_explain_type(FALSE); - select_lex->options|= SELECT_DESCRIBE; - } - - res= mysql_multi_update_prepare(thd); + DBUG_ASSERT(lex->m_sql_cmd != NULL); -#ifdef HAVE_REPLICATION - /* Check slave filtering rules */ - if (unlikely(thd->slave_thread && !have_table_map_for_update)) - { - if (all_tables_not_ok(thd, all_tables)) - { - if (res!= 0) - { - res= 0; /* don't care of prev failure */ - thd->clear_error(); /* filters are of highest prior */ - } - /* we warn the slave SQL thread */ - my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); - break; - } - if (res) - break; - } - else - { -#endif /* HAVE_REPLICATION */ - if (res) - break; - if (opt_readonly && - !(thd->security_ctx->master_access & PRIV_IGNORE_READ_ONLY) && - some_non_temp_table_to_be_updated(thd, all_tables)) - { - my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); - break; - } -#ifdef HAVE_REPLICATION - } /* unlikely */ -#endif - { - multi_update *result_obj; - MYSQL_MULTI_UPDATE_START(thd->query()); - res= mysql_multi_update(thd, all_tables, - &select_lex->item_list, - &lex->value_list, - select_lex->where, - select_lex->options, - lex->duplicates, - lex->ignore, - unit, - select_lex, - &result_obj); - if (result_obj) - { - MYSQL_MULTI_UPDATE_DONE(res, result_obj->num_found(), - result_obj->num_updated()); - res= FALSE; /* Ignore errors here */ - delete result_obj; - } - else - { - MYSQL_MULTI_UPDATE_DONE(1, 0, 0); - } - } + res = lex->m_sql_cmd->execute(thd); + thd->abort_on_warning= 0; break; } case SQLCOM_REPLACE: @@ -4779,135 +4659,6 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt) break; } - case SQLCOM_DELETE: - { - WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE); - select_result *sel_result= NULL; - DBUG_ASSERT(first_table == all_tables && first_table != 0); - WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE); - - if ((res= delete_precheck(thd, all_tables))) - break; - DBUG_ASSERT(select_lex->limit_params.offset_limit == 0); - unit->set_limit(select_lex); - - MYSQL_DELETE_START(thd->query()); - Protocol *save_protocol= NULL; - - if (lex->has_returning()) - { - /* This is DELETE ... RETURNING. It will return output to the client */ - if (thd->lex->analyze_stmt) - { - /* - Actually, it is ANALYZE .. DELETE .. RETURNING. We need to produce - output and then discard it. - */ - sel_result= new (thd->mem_root) select_send_analyze(thd); - save_protocol= thd->protocol; - thd->protocol= new Protocol_discard(thd); - } - else - { - if (!lex->result && !(sel_result= new (thd->mem_root) select_send(thd))) - goto error; - } - } - - res = mysql_delete(thd, all_tables, - select_lex->where, &select_lex->order_list, - unit->lim.get_select_limit(), select_lex->options, - lex->result ? lex->result : sel_result); - - if (save_protocol) - { - delete thd->protocol; - thd->protocol= save_protocol; - } - - if (thd->lex->analyze_stmt || thd->lex->describe) - { - if (!res) - { - bool extended= thd->lex->describe & DESCRIBE_EXTENDED; - res= thd->lex->explain->send_explain(thd, extended); - } - } - - delete sel_result; - MYSQL_DELETE_DONE(res, (ulong) thd->get_row_count_func()); - break; - } - case SQLCOM_DELETE_MULTI: - { - WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE); - DBUG_ASSERT(first_table == all_tables && first_table != 0); - TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first; - multi_delete *result; - WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE); - - if ((res= multi_delete_precheck(thd, all_tables))) - break; - - /* condition will be TRUE on SP re-excuting */ - if (select_lex->item_list.elements != 0) - select_lex->item_list.empty(); - if (add_item_to_list(thd, new (thd->mem_root) Item_null(thd))) - goto error; - - THD_STAGE_INFO(thd, stage_init); - if ((res= open_and_lock_tables(thd, all_tables, TRUE, 0))) - break; - - MYSQL_MULTI_DELETE_START(thd->query()); - if (unlikely(res= mysql_multi_delete_prepare(thd))) - { - MYSQL_MULTI_DELETE_DONE(1, 0); - goto error; - } - - if (likely(!thd->is_fatal_error)) - { - result= new (thd->mem_root) multi_delete(thd, aux_tables, - lex->table_count_update); - if (likely(result)) - { - if (unlikely(select_lex->vers_setup_conds(thd, aux_tables))) - goto multi_delete_error; - res= mysql_select(thd, - select_lex->get_table_list(), - select_lex->item_list, - select_lex->where, - 0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL, - (ORDER *)NULL, - (select_lex->options | thd->variables.option_bits | - SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | - OPTION_SETUP_TABLES_DONE) & ~OPTION_BUFFER_RESULT, - result, unit, select_lex); - res|= (int)(thd->is_error()); - - MYSQL_MULTI_DELETE_DONE(res, result->num_deleted()); - if (res) - result->abort_result_set(); /* for both DELETE and EXPLAIN DELETE */ - else - { - if (lex->describe || lex->analyze_stmt) - { - bool extended= thd->lex->describe & DESCRIBE_EXTENDED; - res= thd->lex->explain->send_explain(thd, extended); - } - } - multi_delete_error: - delete result; - } - } - else - { - res= TRUE; // Error - MYSQL_MULTI_DELETE_DONE(1, 0); - } - break; - } case SQLCOM_DROP_SEQUENCE: case SQLCOM_DROP_TABLE: { @@ -7748,12 +7499,16 @@ void create_select_for_variable(THD *thd, LEX_CSTRING *var_name) } -void mysql_init_multi_delete(LEX *lex) +void mysql_init_delete(LEX *lex) { - lex->sql_command= SQLCOM_DELETE_MULTI; lex->init_select(); lex->first_select_lex()->limit_params.clear(); lex->unit.lim.clear(); +} + +void mysql_init_multi_delete(LEX *lex) +{ + lex->sql_command= SQLCOM_DELETE_MULTI; lex->first_select_lex()->table_list. save_and_clear(&lex->auxiliary_table_list); lex->query_tables= 0; diff --git a/sql/sql_parse.h b/sql/sql_parse.h index eeb7f832adb..872c67c2d1b 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -92,6 +92,7 @@ void mysql_parse(THD *thd, char *rawbuf, uint length, bool mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *sel); void create_select_for_variable(THD *thd, LEX_CSTRING *var_name); void create_table_set_open_action_and_adjust_tables(LEX *lex); +void mysql_init_delete(LEX *lex); void mysql_init_multi_delete(LEX *lex); bool multi_delete_set_locks_and_link_aux_tables(LEX *lex); void create_table_set_open_action_and_adjust_tables(LEX *lex); @@ -188,4 +189,20 @@ check_table_access(THD *thd, privilege_t requirements,TABLE_LIST *tables, { return false; } #endif /*NO_EMBEDDED_ACCESS_CHECKS*/ + +/* + Allocating memory and *also* using it (reading and + writing from it) because some build instructions cause + compiler to optimize out stack_used_up. Since alloca() + here depends on stack_used_up, it doesnt get executed + correctly and causes json_debug_nonembedded to fail + ( --error ER_STACK_OVERRUN_NEED_MORE does not occur). +*/ +#define ALLOCATE_MEM_ON_STACK(A) do \ + { \ + uchar *array= (uchar*)alloca(A); \ + bzero(array, A); \ + my_checksum(0, array, A); \ + } while(0) + #endif /* SQL_PARSE_INCLUDED */ diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 1e84471eef2..22780c894f8 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -95,10 +95,8 @@ When one supplies long data for a placeholder: #include "sql_base.h" // open_normal_and_derived_tables #include "sql_cache.h" // query_cache_* #include "sql_view.h" // create_view_precheck -#include "sql_delete.h" // mysql_prepare_delete #include "sql_select.h" // for JOIN #include "sql_insert.h" // upgrade_lock_type_for_insert, mysql_prepare_insert -#include "sql_update.h" // mysql_prepare_update #include "sql_db.h" // mysql_opt_change_db, mysql_change_db #include "sql_derived.h" // mysql_derived_prepare, // mysql_handle_derived @@ -1402,162 +1400,6 @@ static bool mysql_test_insert(Prepared_statement *stmt, /** - Validate UPDATE statement. - - @param stmt prepared statement - @param tables list of tables used in this query - - @todo - - here we should send types of placeholders to the client. - - @retval - 0 success - @retval - 1 error, error message is set in THD - @retval - 2 convert to multi_update -*/ - -static int mysql_test_update(Prepared_statement *stmt, - TABLE_LIST *table_list) -{ - int res; - THD *thd= stmt->thd; - uint table_count= 0; - TABLE_LIST *update_source_table; - SELECT_LEX *select= stmt->lex->first_select_lex(); -#ifndef NO_EMBEDDED_ACCESS_CHECKS - privilege_t want_privilege(NO_ACL); -#endif - DBUG_ENTER("mysql_test_update"); - - if (update_precheck(thd, table_list) || - open_tables(thd, &table_list, &table_count, MYSQL_OPEN_FORCE_SHARED_MDL)) - goto error; - - if (mysql_handle_derived(thd->lex, DT_INIT)) - goto error; - - if (((update_source_table= unique_table(thd, table_list, - table_list->next_global, 0)) || - table_list->is_multitable())) - { - DBUG_ASSERT(update_source_table || table_list->view != 0); - DBUG_PRINT("info", ("Switch to multi-update")); - /* pass counter value */ - thd->lex->table_count_update= table_count; - /* convert to multiupdate */ - DBUG_RETURN(2); - } - - /* - thd->fill_derived_tables() is false here for sure (because it is - preparation of PS, so we even do not check it). - */ - if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT)) - goto error; - if (table_list->handle_derived(thd->lex, DT_PREPARE)) - goto error; - - if (!table_list->single_table_updatable()) - { - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "UPDATE"); - goto error; - } - -#ifndef NO_EMBEDDED_ACCESS_CHECKS - /* Force privilege re-checking for views after they have been opened. */ - want_privilege= (table_list->view ? UPDATE_ACL : - table_list->grant.want_privilege); -#endif - - if (mysql_prepare_update(thd, table_list, &select->where, - select->order_list.elements, - select->order_list.first)) - goto error; - -#ifndef NO_EMBEDDED_ACCESS_CHECKS - table_list->grant.want_privilege= want_privilege; - table_list->table->grant.want_privilege= want_privilege; - table_list->register_want_access(want_privilege); -#endif - thd->lex->first_select_lex()->no_wrap_view_item= TRUE; - res= setup_fields(thd, Ref_ptr_array(), - select->item_list, MARK_COLUMNS_READ, 0, NULL, 0); - thd->lex->first_select_lex()->no_wrap_view_item= FALSE; - if (res) - goto error; -#ifndef NO_EMBEDDED_ACCESS_CHECKS - /* Check values */ - table_list->grant.want_privilege= - table_list->table->grant.want_privilege= - (SELECT_ACL & ~table_list->table->grant.privilege); - table_list->register_want_access(SELECT_ACL); -#endif - if (setup_fields(thd, Ref_ptr_array(), - stmt->lex->value_list, COLUMNS_READ, 0, NULL, 0) || - check_unique_table(thd, table_list)) - goto error; - /* TODO: here we should send types of placeholders to the client. */ - DBUG_RETURN(0); -error: - DBUG_RETURN(1); -} - - -/** - Validate DELETE statement. - - @param stmt prepared statement - @param tables list of tables used in this query - - @retval - FALSE success - @retval - TRUE error, error message is set in THD -*/ - -static bool mysql_test_delete(Prepared_statement *stmt, - TABLE_LIST *table_list) -{ - uint table_count= 0; - THD *thd= stmt->thd; - LEX *lex= stmt->lex; - bool delete_while_scanning; - DBUG_ENTER("mysql_test_delete"); - - if (delete_precheck(thd, table_list) || - open_tables(thd, &table_list, &table_count, MYSQL_OPEN_FORCE_SHARED_MDL)) - goto error; - - if (mysql_handle_derived(thd->lex, DT_INIT)) - goto error; - if (mysql_handle_derived(thd->lex, DT_MERGE_FOR_INSERT)) - goto error; - if (mysql_handle_derived(thd->lex, DT_PREPARE)) - goto error; - - if (!table_list->single_table_updatable()) - { - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE"); - goto error; - } - if (!table_list->table || !table_list->table->is_created()) - { - my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), - table_list->view_db.str, table_list->view_name.str); - goto error; - } - - DBUG_RETURN(mysql_prepare_delete(thd, table_list, - &lex->first_select_lex()->where, - &delete_while_scanning)); -error: - DBUG_RETURN(TRUE); -} - - -/** Validate SELECT statement. In case of success, if this query is not EXPLAIN, send column list info @@ -2137,74 +1979,6 @@ err: } -/* - Validate and prepare for execution a multi update statement. - - @param stmt prepared statement - @param tables list of tables used in this query - @param converted converted to multi-update from usual update - - @retval - FALSE success - @retval - TRUE error, error message is set in THD -*/ - -static bool mysql_test_multiupdate(Prepared_statement *stmt, - TABLE_LIST *tables, - bool converted) -{ - /* if we switched from normal update, rights are checked */ - if (!converted && multi_update_precheck(stmt->thd, tables)) - return TRUE; - - return select_like_stmt_test(stmt, &mysql_multi_update_prepare, - OPTION_SETUP_TABLES_DONE); -} - - -/** - Validate and prepare for execution a multi delete statement. - - @param stmt prepared statement - @param tables list of tables used in this query - - @retval - FALSE success - @retval - TRUE error, error message in THD is set. -*/ - -static bool mysql_test_multidelete(Prepared_statement *stmt, - TABLE_LIST *tables) -{ - THD *thd= stmt->thd; - - thd->lex->current_select= thd->lex->first_select_lex(); - if (add_item_to_list(thd, new (thd->mem_root) - Item_null(thd))) - { - my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), 0); - goto error; - } - - if (multi_delete_precheck(thd, tables) || - select_like_stmt_test_with_open(stmt, tables, - &mysql_multi_delete_prepare, - OPTION_SETUP_TABLES_DONE)) - goto error; - if (!tables->table) - { - my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), - tables->view_db.str, tables->view_name.str); - goto error; - } - return FALSE; -error: - return TRUE; -} - - /** Wrapper for mysql_insert_select_prepare, to make change of local tables after open_normal_and_derived_tables() call. @@ -2486,18 +2260,14 @@ static bool check_prepared_statement(Prepared_statement *stmt) break; case SQLCOM_UPDATE: - res= mysql_test_update(stmt, tables); - /* mysql_test_update returns 2 if we need to switch to multi-update */ - if (res != 2) - break; - /* fall through */ case SQLCOM_UPDATE_MULTI: - res= mysql_test_multiupdate(stmt, tables, res == 2); - break; - case SQLCOM_DELETE: - res= mysql_test_delete(stmt, tables); + case SQLCOM_DELETE_MULTI: + res = lex->m_sql_cmd->prepare(thd); + if (!res) + lex->m_sql_cmd->unprepare(thd); break; + /* The following allow WHERE clause, so they must be tested like SELECT */ case SQLCOM_SHOW_DATABASES: case SQLCOM_SHOW_TABLES: @@ -2634,10 +2404,6 @@ static bool check_prepared_statement(Prepared_statement *stmt) res= mysql_test_set_fields(stmt, tables, &lex->var_list); break; - case SQLCOM_DELETE_MULTI: - res= mysql_test_multidelete(stmt, tables); - break; - case SQLCOM_INSERT_SELECT: case SQLCOM_REPLACE_SELECT: res= mysql_test_insert_select(stmt, tables); @@ -4373,6 +4139,9 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) thd->is_error() || init_param_array(this)); + if (lex->m_sql_cmd) + lex->m_sql_cmd->set_owner(this); + if (thd->security_ctx->password_expired && lex->sql_command != SQLCOM_SET_OPTION && lex->sql_command != SQLCOM_PREPARE && diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ed29c4399e4..4501168ec72 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1492,7 +1492,7 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num, } } - if (setup_fields(thd, ref_ptrs, fields_list, MARK_COLUMNS_READ, + if (setup_fields(thd, ref_ptrs, fields_list, select_lex->item_list_usage, &all_fields, &select_lex->pre_fix, 1)) DBUG_RETURN(-1); thd->lex->current_select->context_analysis_place= save_place; @@ -1781,6 +1781,8 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num, if (!procedure && result && result->prepare(fields_list, unit_arg)) goto err; /* purecov: inspected */ + select_lex->where_cond_after_prepare= conds; + unit= unit_arg; if (prepare_stage2()) goto err; @@ -2301,6 +2303,8 @@ JOIN::optimize_inner() } transform_in_predicates_into_equalities(thd); + if (thd->lex->are_date_funcs_used()) + transform_date_conds_into_sargable(); conds= optimize_cond(this, conds, join_list, ignore_on_expr, &cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS); @@ -5976,8 +5980,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, s->needed_reg=select->needed_reg; select->quick=0; impossible_range= records == 0 && s->table->reginfo.impossible_range; - if (join->thd->lex->sql_command == SQLCOM_SELECT && - optimizer_flag(join->thd, OPTIMIZER_SWITCH_USE_ROWID_FILTER)) + if (optimizer_flag(join->thd, OPTIMIZER_SWITCH_USE_ROWID_FILTER)) s->table->init_cost_info_for_usable_range_rowid_filters(join->thd); } if (!impossible_range) @@ -31447,7 +31450,8 @@ static bool get_range_limit_read_cost(const POSITION *pos, @note This function takes into account table->opt_range_condition_rows statistic (that is calculated by the make_join_statistics function). - However, single table procedures such as mysql_update() and mysql_delete() + However, single table procedures such as Sql_cmd_update:update_single_table() + and Sql_cmd_delete::delete_single_table() never call make_join_statistics, so they have to update it manually (@see get_index_for_order()). */ @@ -32885,6 +32889,20 @@ bool JOIN::transform_in_predicates_into_equalities(THD *thd) /** @brief + Rewrite datetime comparison conditions into sargable. + See details in the description for class Date_cmp_func_rewriter +*/ + +bool JOIN::transform_date_conds_into_sargable() +{ + DBUG_ENTER("JOIN::transform_date_conds_into_sargable"); + DBUG_RETURN(transform_all_conds_and_on_exprs( + thd, &Item::date_conds_transformer)); +} + + +/** + @brief Transform all items in WHERE and ON expressions using a given transformer @param thd The context of the statement @@ -32942,6 +32960,273 @@ bool JOIN::transform_all_conds_and_on_exprs_in_join_list( return false; } + +static void MYSQL_DML_START(THD *thd) +{ + switch (thd->lex->sql_command) { + + case SQLCOM_UPDATE: + MYSQL_UPDATE_START(thd->query()); + break; + case SQLCOM_UPDATE_MULTI: + MYSQL_MULTI_UPDATE_START(thd->query()); + break; + case SQLCOM_DELETE: + MYSQL_DELETE_START(thd->query()); + break; + case SQLCOM_DELETE_MULTI: + MYSQL_MULTI_DELETE_START(thd->query()); + break; + default: + DBUG_ASSERT(0); + } +} + + +static void MYSQL_DML_DONE(THD *thd, int rc) +{ + switch (thd->lex->sql_command) { + + case SQLCOM_UPDATE: + MYSQL_UPDATE_DONE( + rc, + (rc ? 0 : + ((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result())) + ->num_found()), + (rc ? 0 : + ((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result())) + ->num_updated())); + break; + case SQLCOM_UPDATE_MULTI: + MYSQL_MULTI_UPDATE_DONE( + rc, + (rc ? 0 : + ((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result())) + ->num_found()), + (rc ? 0 : + ((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result())) + ->num_updated())); + break; + case SQLCOM_DELETE: + MYSQL_DELETE_DONE(rc, (rc ? 0 : (ulong) (thd->get_row_count_func()))); + break; + case SQLCOM_DELETE_MULTI: + MYSQL_MULTI_DELETE_DONE( + rc, + (rc ? 0 : + ((multi_delete*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result())) + ->num_deleted())); + break; + default: + DBUG_ASSERT(0); + } +} + + +/* + @brief Perform actions needed before locking tables for a DML statement + + @param thd global context the processed statement + @returns false if success, true if error + + @details + This function calls the precheck() procedure fo the processed statement, + then is opens tables used in the statement and finally it calls the function + prepare_inner() that is specific for the type of the statement. + + @note + The function are used when processing: + - a DML statement + - PREPARE stmt FROM <DML "statement>" + - EXECUTE stmt when stmt is prepared from a DML statement. +*/ + +bool Sql_cmd_dml::prepare(THD *thd) +{ + lex= thd->lex; + SELECT_LEX_UNIT *unit= &lex->unit; + + DBUG_ASSERT(!is_prepared()); + + // Perform a coarse statement-specific privilege check. + if (precheck(thd)) + goto err; + + MYSQL_DML_START(thd); + + lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED; + + if (open_tables_for_query(thd, lex->query_tables, &table_count, 0, + get_dml_prelocking_strategy())) + { + if (thd->is_error()) + goto err; + (void)unit->cleanup(); + return true; + } + + if (prepare_inner(thd)) + goto err; + + lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED; + + set_prepared(); + unit->set_prepared(); + + return false; + +err: + DBUG_ASSERT(thd->is_error()); + DBUG_PRINT("info", ("report_error: %d", thd->is_error())); + + (void)unit->cleanup(); + + return true; +} + + +/** + @brief Execute a DML statement + + @param thd global context the processed statement + @returns false if success, true if error + + @details + The function assumes that each type of a DML statement has its own + implementation of the virtunal functions precheck(). It is also + assumed that that the virtual function execute execute_inner() is to be + overridden by the implementations for specific commands. + + @note + Currently only UPDATE and DELETE statement are executed using this function. +*/ + +bool Sql_cmd_dml::execute(THD *thd) +{ + lex = thd->lex; + bool res; + + SELECT_LEX_UNIT *unit = &lex->unit; + SELECT_LEX *select_lex= lex->first_select_lex(); + + if (!is_prepared()) + { + /* + This is called when processing + - a DML statement + - PREPARE stmt FROM <DML "statement>" + - EXECUTE stmt when stmt is prepared from a DML statement. + The call will invoke open_tables_for_query() + */ + if (prepare(thd)) + goto err; + } + else // This branch currently is never used for DML commands + { + if (precheck(thd)) + goto err; + + MYSQL_DML_START(thd); + + if (open_tables_for_query(thd, lex->query_tables, &table_count, 0, + get_dml_prelocking_strategy())) + goto err; + } + + THD_STAGE_INFO(thd, stage_init); + + /* + Locking of tables is done after preparation but before optimization. + This allows to do better partition pruning and avoid locking unused + partitions. As a consequence, in such a case, prepare stage can rely only + on metadata about tables used and not data from them. + */ + if (!is_empty_query()) + { + if (lock_tables(thd, lex->query_tables, table_count, 0)) + goto err; + } + + unit->set_limit(select_lex); + + /* Perform statement-specific execution */ + res = execute_inner(thd); + + if (res) + goto err; + + res= unit->cleanup(); + + /* "Unprepare" this object since unit->cleanup actually unprepares */ + unprepare(thd); + + THD_STAGE_INFO(thd, stage_end); + + MYSQL_DML_DONE(thd, res); + + return res; + +err: + DBUG_ASSERT(thd->is_error() || thd->killed); + MYSQL_DML_DONE(thd, 1); + THD_STAGE_INFO(thd, stage_end); + (void)unit->cleanup(); + if (is_prepared()) + unprepare(thd); + + return thd->is_error(); +} + + +/** + @brief Generic implemention of optimization and execution phases + @param thd global context the processed statement + @returns false if success, true if error + + @note + This implementation assumes that the processed DML statement is represented + as a SELECT_LEX or SELECT_LEX_UNIT tree with attached corresponding + JOIN structures. Any JOIN structure is constructed at the prepare phase. + When created at the top level join it is provided with an object of a class + derived from select_result_sink. The pointer to the object is saved in + the this->result field. For different types of DML statements different + derived classes are used for this object. The class of this object determines + additional specific actions performed at the phases of context analysis, + optimization and execution. +*/ + +bool Sql_cmd_dml::execute_inner(THD *thd) +{ + SELECT_LEX_UNIT *unit = &lex->unit; + SELECT_LEX *select_lex= unit->first_select(); + JOIN *join= select_lex->join; + + if (join->optimize()) + goto err; + + if (thd->lex->describe & DESCRIBE_EXTENDED) + { + join->conds_history= join->conds; + join->having_history= (join->having?join->having:join->tmp_having); + } + + if (unlikely(thd->is_error())) + goto err; + + if (join->exec()) + goto err; + + if (thd->lex->describe & DESCRIBE_EXTENDED) + { + select_lex->where= join->conds_history; + select_lex->having= join->having_history; + } + +err: + return join->error; +} + + /** @} (end of group Query_Optimizer) */ diff --git a/sql/sql_select.h b/sql/sql_select.h index 85924fbb170..ed8f459fd6c 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1946,6 +1946,7 @@ private: void free_pushdown_handlers(List<TABLE_LIST>& join_list); void init_join_cache_and_keyread(); bool transform_in_predicates_into_equalities(THD *thd); + bool transform_date_conds_into_sargable(); bool transform_all_conds_and_on_exprs(THD *thd, Item_transformer transformer); bool transform_all_conds_and_on_exprs_in_join_list(THD *thd, diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 922dfc5cab8..3b2a690860b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -45,6 +45,9 @@ #include "sql_insert.h" // For vers_insert_history_row() that may be // needed for System Versioning. +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif /** True if the table's input and output record buffers are comparable using @@ -197,22 +200,11 @@ static bool check_fields(THD *thd, TABLE_LIST *table, List<Item> &items, return true; } - DBUG_ASSERT(thd->lex->sql_command == SQLCOM_UPDATE); - for (List_iterator_fast<Item> it(items); (item=it++);) - { - Field *f= item->field_for_view_update()->field; - vers_select_conds_t &period= table->period_conditions; - if (period.field_start->field == f || period.field_end->field == f) - { - my_error(ER_PERIOD_COLUMNS_UPDATED, MYF(0), - item->name.str, period.name.str); - return true; - } - } } return FALSE; } + bool TABLE::vers_check_update(List<Item> &items) { List_iterator<Item> it(items); @@ -339,36 +331,25 @@ int cut_fields_for_portion_of_time(THD *thd, TABLE *table, return res; } -/* - Process usual UPDATE - - SYNOPSIS - mysql_update() - thd thread handler - fields fields for update - values values of fields for update - conds WHERE clause expression - order_num number of elemen in ORDER BY clause - order ORDER BY clause list - limit limit clause +/** + @brief Special handling of single-table updates after prepare phase - RETURN - 0 - OK - 2 - privilege check and openning table passed, but we need to convert to - multi-update because of view substitution - 1 - error + @param thd global context the processed statement + @returns false on success, true on error */ -int mysql_update(THD *thd, - TABLE_LIST *table_list, - List<Item> &fields, - List<Item> &values, - COND *conds, - uint order_num, ORDER *order, - ha_rows limit, - bool ignore, - ha_rows *found_return, ha_rows *updated_return) +bool Sql_cmd_update::update_single_table(THD *thd) { + SELECT_LEX_UNIT *unit = &lex->unit; + SELECT_LEX *select_lex= unit->first_select(); + TABLE_LIST *const table_list = select_lex->get_table_list(); + List<Item> *fields= &select_lex->item_list; + List<Item> *values= &lex->value_list; + COND *conds= select_lex->where_cond_after_prepare; + ORDER *order= select_lex->order_list.first; + ha_rows limit= unit->lim.get_select_limit(); + bool ignore= lex->ignore; + bool using_limit= limit != HA_POS_ERROR; bool safe_update= (thd->variables.option_bits & OPTION_SAFE_UPDATES) && !thd->lex->describe; @@ -380,76 +361,38 @@ int mysql_update(THD *thd, ha_rows dup_key_found; bool need_sort= TRUE; bool reverse= FALSE; -#ifndef NO_EMBEDDED_ACCESS_CHECKS - privilege_t want_privilege(NO_ACL); -#endif - uint table_count= 0; ha_rows updated, updated_or_same, found; key_map old_covering_keys; TABLE *table; SQL_SELECT *select= NULL; SORT_INFO *file_sort= 0; READ_RECORD info; - SELECT_LEX *select_lex= thd->lex->first_select_lex(); ulonglong id; List<Item> all_fields; killed_state killed_status= NOT_KILLED; bool has_triggers, binlog_is_row, do_direct_update= FALSE; Update_plan query_plan(thd->mem_root); Explain_update *explain; - TABLE_LIST *update_source_table; query_plan.index= MAX_KEY; query_plan.using_filesort= FALSE; // For System Versioning (may need to insert new fields to a table). ha_rows rows_inserted= 0; - DBUG_ENTER("mysql_update"); - - create_explain_query(thd->lex, thd->mem_root); - if (open_tables(thd, &table_list, &table_count, 0)) - DBUG_RETURN(1); - - /* Prepare views so they are handled correctly */ - if (mysql_handle_derived(thd->lex, DT_INIT)) - DBUG_RETURN(1); - - if (table_list->has_period() && table_list->is_view_or_derived()) - { - my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str); - DBUG_RETURN(TRUE); - } - - if (((update_source_table=unique_table(thd, table_list, - table_list->next_global, 0)) || - table_list->is_multitable())) - { - DBUG_ASSERT(update_source_table || table_list->view != 0); - DBUG_PRINT("info", ("Switch to multi-update")); - /* pass counter value */ - thd->lex->table_count_update= table_count; - if (thd->lex->period_conditions.is_set()) - { - my_error(ER_NOT_SUPPORTED_YET, MYF(0), - "updating and querying the same temporal periods table"); - - DBUG_RETURN(1); - } + DBUG_ENTER("Sql_cmd_update::update_single_table"); - /* convert to multiupdate */ - DBUG_RETURN(2); - } - if (lock_tables(thd, table_list, table_count, 0)) - DBUG_RETURN(1); + THD_STAGE_INFO(thd, stage_init_update); - (void) read_statistics_for_tables_if_needed(thd, table_list); + thd->table_map_for_update= 0; - THD_STAGE_INFO(thd, stage_init_update); if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT)) DBUG_RETURN(1); if (table_list->handle_derived(thd->lex, DT_PREPARE)) DBUG_RETURN(1); + if (setup_ftfuncs(select_lex)) + DBUG_RETURN(1); + table= table_list->table; if (!table_list->single_table_updatable()) @@ -458,89 +401,26 @@ int mysql_update(THD *thd, DBUG_RETURN(1); } - /* Calculate "table->covering_keys" based on the WHERE */ - table->covering_keys= table->s->keys_in_use; table->opt_range_keys.clear_all(); query_plan.select_lex= thd->lex->first_select_lex(); query_plan.table= table; -#ifndef NO_EMBEDDED_ACCESS_CHECKS - /* Force privilege re-checking for views after they have been opened. */ - want_privilege= (table_list->view ? UPDATE_ACL : - table_list->grant.want_privilege); -#endif thd->lex->promote_select_describe_flag_if_needed(); - if (mysql_prepare_update(thd, table_list, &conds, order_num, order)) - DBUG_RETURN(1); - - if (table_list->has_period()) - { - if (!table_list->period_conditions.start.item->const_item() - || !table_list->period_conditions.end.item->const_item()) - { - my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF"); - DBUG_RETURN(true); - } - table->no_cache= true; - } - old_covering_keys= table->covering_keys; // Keys used in WHERE - /* Check the fields we are going to modify */ -#ifndef NO_EMBEDDED_ACCESS_CHECKS - table_list->grant.want_privilege= table->grant.want_privilege= want_privilege; - table_list->register_want_access(want_privilege); -#endif - /* 'Unfix' fields to allow correct marking by the setup_fields function. */ - if (table_list->is_view()) - unfix_fields(fields); - if (setup_fields_with_no_wrap(thd, Ref_ptr_array(), - fields, MARK_COLUMNS_WRITE, 0, 0)) - DBUG_RETURN(1); /* purecov: inspected */ - if (check_fields(thd, table_list, fields, table_list->view)) - { - DBUG_RETURN(1); - } - bool has_vers_fields= table->vers_check_update(fields); - if (check_key_in_view(thd, table_list)) - { - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "UPDATE"); - DBUG_RETURN(1); - } + bool has_vers_fields= table->vers_check_update(*fields); if (table->default_field) table->mark_default_fields_for_write(false); -#ifndef NO_EMBEDDED_ACCESS_CHECKS - /* Check values */ - table_list->grant.want_privilege= table->grant.want_privilege= - (SELECT_ACL & ~table->grant.privilege); -#endif - if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, NULL, 0)) - { - free_underlaid_joins(thd, select_lex); - DBUG_RETURN(1); /* purecov: inspected */ - } - - if (table_list->table->check_assignability_explicit_fields(fields, values, - ignore)) - DBUG_RETURN(true); - - if (check_unique_table(thd, table_list)) - DBUG_RETURN(TRUE); - - switch_to_nullable_trigger_fields(fields, table); - switch_to_nullable_trigger_fields(values, table); + switch_to_nullable_trigger_fields(*fields, table); + switch_to_nullable_trigger_fields(*values, table); /* Apply the IN=>EXISTS transformation to all subqueries and optimize them */ if (select_lex->optimize_unflattened_subqueries(false)) DBUG_RETURN(TRUE); - if (select_lex->inner_refs_list.elements && - fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array)) - DBUG_RETURN(1); - if (conds) { Item::cond_result cond_value; @@ -553,6 +433,12 @@ int mysql_update(THD *thd, goto produce_explain_and_leave; } } + if (conds && thd->lex->are_date_funcs_used()) + { + /* Rewrite datetime comparison conditions into sargable */ + conds= conds->top_level_transform(thd, &Item::date_conds_transformer, + (uchar *) 0); + } // Don't count on usage of 'only index' when calculating which key to use table->covering_keys.clear_all(); @@ -782,9 +668,9 @@ int mysql_update(THD *thd, } if (use_direct_update && - !table->file->info_push(INFO_KIND_UPDATE_FIELDS, &fields) && - !table->file->info_push(INFO_KIND_UPDATE_VALUES, &values) && - !table->file->direct_update_rows_init(&fields)) + !table->file->info_push(INFO_KIND_UPDATE_FIELDS, fields) && + !table->file->info_push(INFO_KIND_UPDATE_VALUES, values) && + !table->file->direct_update_rows_init(fields)) { do_direct_update= TRUE; @@ -1033,7 +919,7 @@ update_begin: cut_fields_for_portion_of_time(thd, table, table_list->period_conditions); - if (fill_record_n_invoke_before_triggers(thd, table, fields, values, 0, + if (fill_record_n_invoke_before_triggers(thd, table, *fields, *values, 0, TRG_EVENT_UPDATE)) break; /* purecov: inspected */ @@ -1366,9 +1252,9 @@ update_end: thd->lex->current_select->save_leaf_tables(thd); thd->lex->current_select->first_cond_optimization= 0; } - *found_return= found; - *updated_return= updated; - + ((multi_update *)result)->set_found(found); + ((multi_update *)result)->set_updated(updated); + if (unlikely(thd->lex->analyze_stmt)) goto emit_explain_and_leave; @@ -1401,77 +1287,6 @@ emit_explain_and_leave: DBUG_RETURN((err2 || thd->is_error()) ? 1 : 0); } -/* - Prepare items in UPDATE statement - - SYNOPSIS - mysql_prepare_update() - thd - thread handler - table_list - global/local table list - conds - conditions - order_num - number of ORDER BY list entries - order - ORDER BY clause list - - RETURN VALUE - FALSE OK - TRUE error -*/ -bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, - Item **conds, uint order_num, ORDER *order) -{ - Item *fake_conds= 0; -#ifndef NO_EMBEDDED_ACCESS_CHECKS - TABLE *table= table_list->table; -#endif - List<Item> all_fields; - SELECT_LEX *select_lex= thd->lex->first_select_lex(); - DBUG_ENTER("mysql_prepare_update"); - -#ifndef NO_EMBEDDED_ACCESS_CHECKS - table_list->grant.want_privilege= table->grant.want_privilege= - (SELECT_ACL & ~table->grant.privilege); - table_list->register_want_access(SELECT_ACL); -#endif - - thd->lex->allow_sum_func.clear_all(); - - if (table_list->has_period() && - select_lex->period_setup_conds(thd, table_list)) - DBUG_RETURN(true); - - DBUG_ASSERT(table_list->table); - // conds could be cached from previous SP call - DBUG_ASSERT(!table_list->vers_conditions.need_setup() || - !*conds || thd->stmt_arena->is_stmt_execute()); - if (select_lex->vers_setup_conds(thd, table_list)) - DBUG_RETURN(TRUE); - - *conds= select_lex->where; - - /* - We do not call DT_MERGE_FOR_INSERT because it has no sense for simple - (not multi-) update - */ - if (mysql_handle_derived(thd->lex, DT_PREPARE)) - DBUG_RETURN(TRUE); - - if (setup_tables_and_check_access(thd, &select_lex->context, - &select_lex->top_join_list, table_list, - select_lex->leaf_tables, - FALSE, UPDATE_ACL, SELECT_ACL, TRUE) || - setup_conds(thd, table_list, select_lex->leaf_tables, conds) || - select_lex->setup_ref_array(thd, order_num) || - setup_order(thd, select_lex->ref_pointer_array, - table_list, all_fields, all_fields, order) || - setup_ftfuncs(select_lex)) - DBUG_RETURN(TRUE); - - - select_lex->fix_prepare_information(thd, conds, &fake_conds); - if (!thd->lex->upd_del_where) - thd->lex->upd_del_where= *conds; - DBUG_RETURN(FALSE); -} /** Check that we are not using table that we are updating in a sub select @@ -1699,15 +1514,6 @@ static bool multi_update_check_table_access(THD *thd, TABLE_LIST *table, } -class Multiupdate_prelocking_strategy : public DML_prelocking_strategy -{ - bool done; - bool has_prelocking_list; -public: - void reset(THD *thd); - bool handle_end(THD *thd); -}; - void Multiupdate_prelocking_strategy::reset(THD *thd) { done= false; @@ -1737,7 +1543,13 @@ bool Multiupdate_prelocking_strategy::handle_end(THD *thd) mysql_handle_derived(lex, DT_PREPARE)) DBUG_RETURN(1); - /* + if (table_list->has_period() && table_list->is_view_or_derived()) + { + my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str); + DBUG_RETURN(TRUE); + } + + /* setup_tables() need for VIEWs. JOIN::prepare() will call setup_tables() second time, but this call will do nothing (there are check for second call in setup_tables()). @@ -1748,6 +1560,10 @@ bool Multiupdate_prelocking_strategy::handle_end(THD *thd) FALSE, UPDATE_ACL, SELECT_ACL, TRUE)) DBUG_RETURN(1); + if (table_list->has_period() && + select_lex->period_setup_conds(thd, table_list)) + DBUG_RETURN(true); + List<Item> *fields= &lex->first_select_lex()->item_list; if (setup_fields_with_no_wrap(thd, Ref_ptr_array(), *fields, MARK_COLUMNS_WRITE, 0, 0)) @@ -1856,156 +1672,6 @@ bool Multiupdate_prelocking_strategy::handle_end(THD *thd) DBUG_RETURN(0); } -/* - make update specific preparation and checks after opening tables - - SYNOPSIS - mysql_multi_update_prepare() - thd thread handler - - RETURN - FALSE OK - TRUE Error -*/ - -int mysql_multi_update_prepare(THD *thd) -{ - LEX *lex= thd->lex; - TABLE_LIST *table_list= lex->query_tables; - TABLE_LIST *tl; - Multiupdate_prelocking_strategy prelocking_strategy; - uint table_count= lex->table_count_update; - DBUG_ENTER("mysql_multi_update_prepare"); - - /* - Open tables and create derived ones, but do not lock and fill them yet. - - During prepare phase acquire only S metadata locks instead of SW locks to - keep prepare of multi-UPDATE compatible with concurrent LOCK TABLES WRITE - and global read lock. - - Don't evaluate any subqueries even if constant, because - tables aren't locked yet. - */ - lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED; - if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI) - { - if (open_tables(thd, &table_list, &table_count, - thd->stmt_arena->is_stmt_prepare() ? MYSQL_OPEN_FORCE_SHARED_MDL : 0, - &prelocking_strategy)) - DBUG_RETURN(TRUE); - } - else - { - /* following need for prepared statements, to run next time multi-update */ - thd->lex->sql_command= SQLCOM_UPDATE_MULTI; - prelocking_strategy.reset(thd); - if (prelocking_strategy.handle_end(thd)) - DBUG_RETURN(TRUE); - } - - /* now lock and fill tables */ - if (!thd->stmt_arena->is_stmt_prepare() && - lock_tables(thd, table_list, table_count, 0)) - DBUG_RETURN(TRUE); - - lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED; - - (void) read_statistics_for_tables_if_needed(thd, table_list); - /* @todo: downgrade the metadata locks here. */ - - /* - Check that we are not using table that we are updating, but we should - skip all tables of UPDATE SELECT itself - */ - lex->first_select_lex()->exclude_from_table_unique_test= TRUE; - /* We only need SELECT privilege for columns in the values list */ - List_iterator<TABLE_LIST> ti(lex->first_select_lex()->leaf_tables); - while ((tl= ti++)) - { - if (tl->is_jtbm()) - continue; - TABLE *table= tl->table; - TABLE_LIST *tlist; - if (!(tlist= tl->top_table())->derived) - { - tlist->grant.want_privilege= - (SELECT_ACL & ~tlist->grant.privilege); - table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege); - } - DBUG_PRINT("info", ("table: %s want_privilege: %llx", tl->alias.str, - (longlong) table->grant.want_privilege)); - } - /* - Set exclude_from_table_unique_test value back to FALSE. It is needed for - further check in multi_update::prepare whether to use record cache. - */ - lex->first_select_lex()->exclude_from_table_unique_test= FALSE; - - if (lex->save_prep_leaf_tables()) - DBUG_RETURN(TRUE); - - DBUG_RETURN (FALSE); -} - - -/* - Setup multi-update handling and call SELECT to do the join -*/ - -bool mysql_multi_update(THD *thd, TABLE_LIST *table_list, List<Item> *fields, - List<Item> *values, COND *conds, ulonglong options, - enum enum_duplicates handle_duplicates, - bool ignore, SELECT_LEX_UNIT *unit, - SELECT_LEX *select_lex, multi_update **result) -{ - bool res; - DBUG_ENTER("mysql_multi_update"); - - if (!(*result= new (thd->mem_root) multi_update(thd, table_list, - &thd->lex->first_select_lex()->leaf_tables, - fields, values, handle_duplicates, ignore))) - { - DBUG_RETURN(TRUE); - } - - if ((*result)->init(thd)) - DBUG_RETURN(1); - - thd->abort_on_warning= !ignore && thd->is_strict_mode(); - List<Item> total_list; - - if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list, - table_list, select_lex->leaf_tables, FALSE, FALSE)) - DBUG_RETURN(1); - - if (select_lex->vers_setup_conds(thd, table_list)) - DBUG_RETURN(1); - - res= mysql_select(thd, - table_list, total_list, conds, - select_lex->order_list.elements, - select_lex->order_list.first, NULL, NULL, NULL, - options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | - OPTION_SETUP_TABLES_DONE, - *result, unit, select_lex); - - DBUG_PRINT("info",("res: %d report_error: %d", res, (int) thd->is_error())); - res|= thd->is_error(); - if (unlikely(res)) - (*result)->abort_result_set(); - else - { - if (thd->lex->describe || thd->lex->analyze_stmt) - { - bool extended= thd->lex->describe & DESCRIBE_EXTENDED; - res= thd->lex->explain->send_explain(thd, extended); - } - } - thd->abort_on_warning= 0; - DBUG_RETURN(res); -} - multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list, List<TABLE_LIST> *leaves_list, @@ -2041,6 +1707,19 @@ bool multi_update::init(THD *thd) } +bool multi_update::init_for_single_table(THD *thd) +{ + List_iterator_fast<TABLE_LIST> li(*leaves); + TABLE_LIST *tbl; + while ((tbl =li++)) + { + if (updated_leaves.push_back(tbl, thd->mem_root)) + return true; + } + return false; +} + + /* Connect fields with tables and create list of tables that are updated */ @@ -2116,7 +1795,8 @@ int multi_update::prepare(List<Item> ¬_used_values, { table->read_set= &table->def_read_set; bitmap_union(table->read_set, &table->tmp_set); - table->file->prepare_for_insert(1); + if (!(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_PREPARE)) + table->file->prepare_for_insert(1); } } if (unlikely(error)) @@ -2805,6 +2485,8 @@ int multi_update::do_updates() table = cur_table->table; if (table == table_to_update) continue; // Already updated + if (table->file->pushed_rowid_filter) + table->file->disable_pushed_rowid_filter(); org_updated= updated; tmp_table= tmp_tables[cur_table->shared]; tmp_table->file->extra(HA_EXTRA_CACHE); // Change to read cache @@ -2999,7 +2681,8 @@ int multi_update::do_updates() check_opt_it.rewind(); while (TABLE *tbl= check_opt_it++) tbl->file->ha_rnd_end(); - + if (table->file->save_pushed_rowid_filter) + table->file->enable_pushed_rowid_filter(); } DBUG_RETURN(0); @@ -3010,6 +2693,8 @@ err: } err2: + if (table->file->save_pushed_rowid_filter) + table->file->enable_pushed_rowid_filter(); if (table->file->inited) (void) table->file->ha_rnd_end(); if (tmp_table->file->inited) @@ -3138,3 +2823,266 @@ bool multi_update::send_eof() } DBUG_RETURN(FALSE); } + + +/** + @brief Check whether conversion to multi-table update is prohibited + + @param thd global context the processed statement + @returns true if conversion is prohibited, false otherwise + + @todo + Introduce handler level flag for storage engines that would prohibit + such conversion for any single-table update. +*/ + +bool Sql_cmd_update::processing_as_multitable_update_prohibited(THD *thd) +{ + SELECT_LEX *const select_lex = thd->lex->first_select_lex(); + return + (select_lex->order_list.elements && + select_lex->limit_params.select_limit); +} + + +/** + @brief Perform precheck of table privileges for update statements + + @param thd global context the processed statement + @returns false on success, true on error +*/ + +bool Sql_cmd_update::precheck(THD *thd) +{ + if (!multitable) + { + if (update_precheck(thd, lex->query_tables)) + return true; + } + else + { + if (multi_update_precheck(thd, lex->query_tables)) + return true; + } + +#ifdef WITH_WSREP + WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE); +#endif + + return false; + +#ifdef WITH_WSREP +wsrep_error_label: +#endif + return true; +} + + +/** + @brief Perform context analysis for update statements + + @param thd global context the processed statement + @returns false on success, true on error + + @note + The main bulk of the context analysis actions for and update statement + is performed by a call of JOIN::prepare(). +*/ + +bool Sql_cmd_update::prepare_inner(THD *thd) +{ + JOIN *join; + int err= 0; + SELECT_LEX *const select_lex = thd->lex->first_select_lex(); + TABLE_LIST *const table_list = select_lex->get_table_list(); + ulonglong select_options= select_lex->options; + bool free_join= 1; + DBUG_ENTER("Sql_cmd_update::prepare_inner"); + + (void) read_statistics_for_tables_if_needed(thd, table_list); + + THD_STAGE_INFO(thd, stage_init_update); + + if (!multitable) + { + if (mysql_handle_derived(lex, DT_INIT)) + DBUG_RETURN(TRUE); + } + + if (table_list->has_period() && table_list->is_view_or_derived()) + { + my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str); + DBUG_RETURN(TRUE); + } + + if (!multitable) + { + TABLE_LIST *update_source_table= 0; + + if (((update_source_table=unique_table(thd, table_list, + table_list->next_global, 0)) || + table_list->is_multitable())) + { + DBUG_ASSERT(update_source_table || table_list->view != 0); + if (thd->lex->period_conditions.is_set()) + { + my_error(ER_NOT_SUPPORTED_YET, MYF(0), + "updating and querying the same temporal periods table"); + DBUG_RETURN(TRUE); + } + if (!table_list->is_multitable() && + !processing_as_multitable_update_prohibited(thd)) + multitable= true; + } + } + + if(!multitable) + { + if (table_list->is_view_or_derived() && + select_lex->leaf_tables.elements > 1) + multitable = true; + } + + if (!multitable) + { + if (lex->ignore) + lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_UPDATE_IGNORE); + } + + if (!(result= new (thd->mem_root) multi_update(thd, table_list, + &select_lex->leaf_tables, + &select_lex->item_list, + &lex->value_list, + lex->duplicates, + lex->ignore))) + { + DBUG_RETURN(TRUE); + } + + if (((multi_update *)result)->init(thd)) + DBUG_RETURN(TRUE); + + if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list, + table_list, select_lex->leaf_tables, false, false)) + DBUG_RETURN(TRUE); + + if (select_lex->vers_setup_conds(thd, table_list)) + DBUG_RETURN(TRUE); + + { + if (thd->lex->describe) + select_options|= SELECT_DESCRIBE; + + /* + When in EXPLAIN, delay deleting the joins so that they are still + available when we're producing EXPLAIN EXTENDED warning text. + */ + if (select_options & SELECT_DESCRIBE) + free_join= 0; + + select_options|= + SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | OPTION_SETUP_TABLES_DONE; + + if (!(join= new (thd->mem_root) JOIN(thd, select_lex->item_list, + select_options, result))) + DBUG_RETURN(TRUE); + THD_STAGE_INFO(thd, stage_init); + select_lex->join= join; + thd->lex->used_tables=0; + select_lex->item_list_usage= MARK_COLUMNS_WRITE; + if ((err= join->prepare(table_list, select_lex->where, + select_lex->order_list.elements, + select_lex->order_list.first, + false, NULL, NULL, NULL, + select_lex, &lex->unit))) + { + goto err; + } + if (!multitable && + select_lex->sj_subselects.elements) + multitable= true; + } + + if (table_list->has_period()) + { + Item *item; + for (List_iterator_fast<Item> it(select_lex->item_list); (item=it++);) + { + Field *f= item->field_for_view_update()->field; + vers_select_conds_t &period= table_list->period_conditions; + if (period.field_start->field == f || period.field_end->field == f) + { + my_error(ER_PERIOD_COLUMNS_UPDATED, MYF(0), + item->name.str, period.name.str); + DBUG_RETURN(true); + } + } + + if (!table_list->period_conditions.start.item->const_item() + || !table_list->period_conditions.end.item->const_item()) + { + my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF"); + DBUG_RETURN(true); + } + table_list->table->no_cache= true; + } + + + free_join= false; + +err: + + if (free_join) + { + THD_STAGE_INFO(thd, stage_end); + err|= (int)(select_lex->cleanup()); + DBUG_RETURN(err || thd->is_error()); + } + DBUG_RETURN(err); + +} + + +/** + @brief Perform optimization and execution actions needed for updates + + @param thd global context the processed statement + @returns false on success, true on error +*/ + +bool Sql_cmd_update::execute_inner(THD *thd) +{ + bool res= 0; + + thd->get_stmt_da()->reset_current_row_for_warning(1); + if (!multitable) + res= update_single_table(thd); + else + { + thd->abort_on_warning= !thd->lex->ignore && thd->is_strict_mode(); + res= Sql_cmd_dml::execute_inner(thd); + } + + res|= thd->is_error(); + if (multitable) + { + if (unlikely(res)) + result->abort_result_set(); + else + { + if (thd->lex->describe || thd->lex->analyze_stmt) + { + bool extended= thd->lex->describe & DESCRIBE_EXTENDED; + res= thd->lex->explain->send_explain(thd, extended); + } + } + } + + if (result) + { + res= false; + delete result; + } + + return res; +} diff --git a/sql/sql_update.h b/sql/sql_update.h index 65e44d112a4..d01ecb7354a 100644 --- a/sql/sql_update.h +++ b/sql/sql_update.h @@ -17,6 +17,8 @@ #define SQL_UPDATE_INCLUDED #include "sql_class.h" /* enum_duplicates */ +#include "sql_cmd.h" // Sql_cmd_dml +#include "sql_base.h" class Item; struct TABLE_LIST; @@ -25,20 +27,83 @@ class THD; typedef class st_select_lex SELECT_LEX; typedef class st_select_lex_unit SELECT_LEX_UNIT; -bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, - Item **conds, uint order_num, ORDER *order); bool check_unique_table(THD *thd, TABLE_LIST *table_list); -int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields, - List<Item> &values,COND *conds, - uint order_num, ORDER *order, ha_rows limit, - bool ignore, ha_rows *found_return, ha_rows *updated_return); -bool mysql_multi_update(THD *thd, TABLE_LIST *table_list, - List<Item> *fields, List<Item> *values, - COND *conds, ulonglong options, - enum enum_duplicates handle_duplicates, bool ignore, - SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex, - multi_update **result); bool records_are_comparable(const TABLE *table); bool compare_record(const TABLE *table); +/** + @class Sql_cmd_update - class used for any UPDATE statements + + This class is derived from Sql_cmd_dml and contains implementations + for abstract virtual function of the latter such as precheck() and + prepare_inner(). It also overrides the implementation of execute_inner() + providing a special handling for single-table update statements that + are not converted to multi-table updates. + The class provides an object of the Multiupdate_prelocking_strategy class + for the virtual function get_dml_prelocking_strategy(). +*/ +class Sql_cmd_update final : public Sql_cmd_dml +{ +public: + Sql_cmd_update(bool multitable_arg) + : orig_multitable(multitable_arg), multitable(multitable_arg) + {} + + enum_sql_command sql_command_code() const override + { + return orig_multitable ? SQLCOM_UPDATE_MULTI : SQLCOM_UPDATE; + } + + DML_prelocking_strategy *get_dml_prelocking_strategy() override + { + return &multiupdate_prelocking_strategy; + } + + bool processing_as_multitable_update_prohibited(THD *thd); + + bool is_multitable() const { return multitable; } + + void set_as_multitable() { multitable= true; } + +protected: + /** + @brief Perform precheck of table privileges for update statements + */ + bool precheck(THD *thd) override; + + /** + @brief Perform context analysis for update statements + */ + bool prepare_inner(THD *thd) override; + + /** + @brief Perform optimization and execution actions needed for updates + */ + bool execute_inner(THD *thd) override; + +private: + + /** + @brief Special handling of single-table updates after prepare phase + */ + bool update_single_table(THD *thd); + + /* Original value of the 'multitable' flag set by constructor */ + const bool orig_multitable; + + /* + True if the statement is a multi-table update or converted to such. + For a single-table update this flag is set to true if the statement + is supposed to be converted to multi-table update. + */ + bool multitable; + + /* The prelocking strategy used when opening the used tables */ + Multiupdate_prelocking_strategy multiupdate_prelocking_strategy; + + public: + /* The list of the updating expressions used in the set clause */ + List<Item> *update_value_list; +}; + #endif /* SQL_UPDATE_INCLUDED */ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 7d434a10ddc..24284402e84 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -69,6 +69,8 @@ #include "my_base.h" #include "sql_type_json.h" #include "json_table.h" +#include "sql_update.h" +#include "sql_delete.h" /* this is to get the bison compilation windows warnings out */ #ifdef _MSC_VER @@ -1709,7 +1711,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); opt_mi_check_type opt_to mi_check_types table_to_table_list table_to_table opt_table_list opt_as handler_rkey_function handler_read_or_scan - single_multi table_wild_list table_wild_one opt_wild + single_multi opt_wild opt_and select_var_list select_var_list_init help opt_extended_describe shutdown @@ -9896,6 +9898,7 @@ function_call_keyword: $$= new (thd->mem_root) Item_date_typecast(thd, $3); if (unlikely($$ == NULL)) MYSQL_YYABORT; + Lex->set_date_funcs_used_flag(); } | DAY_SYM '(' expr ')' { @@ -9958,6 +9961,7 @@ function_call_keyword: $$= new (thd->mem_root) Item_func_month(thd, $3); if (unlikely($$ == NULL)) MYSQL_YYABORT; + Lex->set_date_funcs_used_flag(); } | RIGHT '(' expr ',' expr ')' { @@ -10009,6 +10013,7 @@ function_call_keyword: $$= new (thd->mem_root) Item_func_year(thd, $3); if (unlikely($$ == NULL)) MYSQL_YYABORT; + Lex->set_date_funcs_used_flag(); } ; @@ -13301,9 +13306,14 @@ update: opt_low_priority opt_ignore update_table_list SET update_list { + bool is_multiupdate= false; + LEX *lex= Lex; SELECT_LEX *slex= Lex->first_select_lex(); if (slex->table_list.elements > 1) + { Lex->sql_command= SQLCOM_UPDATE_MULTI; + is_multiupdate= true; + } else if (slex->get_table_list()->derived) { /* it is single table update and it is update of derived table */ @@ -13311,10 +13321,13 @@ update: slex->get_table_list()->alias.str, "UPDATE"); MYSQL_YYABORT; } + if (!(lex->m_sql_cmd= + new (thd->mem_root) Sql_cmd_update(is_multiupdate))) + MYSQL_YYABORT; /* In case of multi-update setting write lock for all tables may - be too pessimistic. We will decrease lock level if possible in - mysql_multi_update(). + be too pessimistic. We will decrease lock level if possible + later while processing the statement. */ slex->set_lock_for_tables($3, slex->table_list.elements == 1, false); } @@ -13371,12 +13384,11 @@ delete: DELETE_SYM { LEX *lex= Lex; - lex->sql_command= SQLCOM_DELETE; YYPS->m_lock_type= TL_WRITE_DEFAULT; YYPS->m_mdl_type= MDL_SHARED_WRITE; if (Lex->main_select_push()) MYSQL_YYABORT; - lex->init_select(); + mysql_init_delete(lex); lex->ignore= 0; lex->first_select_lex()->order_list.empty(); } @@ -13402,11 +13414,17 @@ delete_part2: opt_delete_options single_multi {} | HISTORY_SYM delete_single_table opt_delete_system_time { - Lex->last_table()->vers_conditions= Lex->vers_conditions; - Lex->pop_select(); //main select - if (Lex->check_main_unit_semantics()) + LEX *lex= Lex; + lex->last_table()->vers_conditions= lex->vers_conditions; + lex->sql_command= SQLCOM_DELETE; + if (!(lex->m_sql_cmd= + new (thd->mem_root) Sql_cmd_delete(false))) + MYSQL_YYABORT; + if (lex->check_main_unit_semantics()) MYSQL_YYABORT; } + stmt_end + {} ; delete_single_table: @@ -13417,8 +13435,23 @@ delete_single_table: YYPS->m_lock_type, YYPS->m_mdl_type, NULL, + 0))) + MYSQL_YYABORT; + Select->table_list.save_and_clear(&Lex->auxiliary_table_list); + /* Save the number of auxiliary tables */ + Lex->table_count_update= 1; + + Lex->query_tables= 0; + Lex->query_tables_last= &Lex->query_tables; + if (unlikely(!Select-> + add_table_to_list(thd, $2, NULL, TL_OPTION_UPDATING, + YYPS->m_lock_type, + YYPS->m_mdl_type, + NULL, $3))) MYSQL_YYABORT; + Lex->auxiliary_table_list.first->correspondent_table= + Lex->query_tables; YYPS->m_lock_type= TL_READ_DEFAULT; YYPS->m_mdl_type= MDL_SHARED_READ; } @@ -13439,14 +13472,24 @@ single_multi: delete_limit_clause opt_returning { + LEX *lex= Lex; if ($3) Select->order_list= *($3); - Lex->pop_select(); //main select + lex->sql_command= SQLCOM_DELETE; + if (!(lex->m_sql_cmd= + new (thd->mem_root) Sql_cmd_delete(false))) + MYSQL_YYABORT; if (Lex->check_main_unit_semantics()) MYSQL_YYABORT; } - | table_wild_list + stmt_end {} + | table_alias_ref_list { + LEX *lex= Lex; + lex->sql_command= SQLCOM_DELETE_MULTI; + if (!(lex->m_sql_cmd= + new (thd->mem_root) Sql_cmd_delete(true))) + MYSQL_YYABORT; mysql_init_multi_delete(Lex); YYPS->m_lock_type= TL_READ_DEFAULT; YYPS->m_mdl_type= MDL_SHARED_READ; @@ -13458,6 +13501,11 @@ single_multi: } stmt_end {} | FROM table_alias_ref_list { + LEX *lex= Lex; + lex->sql_command= SQLCOM_DELETE_MULTI; + if (!(lex->m_sql_cmd= + new (thd->mem_root) Sql_cmd_delete(true))) + MYSQL_YYABORT; mysql_init_multi_delete(Lex); YYPS->m_lock_type= TL_READ_DEFAULT; YYPS->m_mdl_type= MDL_SHARED_READ; @@ -13507,44 +13555,6 @@ opt_returning: } ; -table_wild_list: - table_wild_one - | table_wild_list ',' table_wild_one - ; - -table_wild_one: - ident opt_wild - { - Table_ident *ti= new (thd->mem_root) Table_ident(&$1); - if (unlikely(ti == NULL)) - MYSQL_YYABORT; - if (unlikely(!Select-> - add_table_to_list(thd, - ti, - NULL, - (TL_OPTION_UPDATING | - TL_OPTION_ALIAS), - YYPS->m_lock_type, - YYPS->m_mdl_type))) - MYSQL_YYABORT; - } - | ident '.' ident opt_wild - { - Table_ident *ti= new (thd->mem_root) Table_ident(thd, &$1, &$3, 0); - if (unlikely(ti == NULL)) - MYSQL_YYABORT; - if (unlikely(!Select-> - add_table_to_list(thd, - ti, - NULL, - (TL_OPTION_UPDATING | - TL_OPTION_ALIAS), - YYPS->m_lock_type, - YYPS->m_mdl_type))) - MYSQL_YYABORT; - } - ; - opt_wild: /* empty */ {} | '.' '*' {} @@ -16796,7 +16806,7 @@ transaction_access_mode: MYSQL_YYABORT; set_var *var= (new (thd->mem_root) set_var(thd, lex->option_type, - find_sys_var(thd, "tx_read_only"), + find_sys_var(thd, "transaction_read_only"), &null_clex_str, item)); if (unlikely(var == NULL)) @@ -16815,7 +16825,7 @@ isolation_level: MYSQL_YYABORT; set_var *var= (new (thd->mem_root) set_var(thd, lex->option_type, - find_sys_var(thd, "tx_isolation"), + find_sys_var(thd, "transaction_isolation"), &null_clex_str, item)); if (unlikely(var == NULL) || diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index a77841e4dda..c98a8b60746 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -4205,7 +4205,7 @@ Sys_threadpool_dedicated_listener( #endif /* HAVE_POOL_OF_THREADS */ /** - Can't change the 'next' tx_isolation if we are already in a + Can't change the 'next' transaction_isolation if we are already in a transaction. */ @@ -4222,14 +4222,22 @@ static bool check_tx_isolation(sys_var *self, THD *thd, set_var *var) // NO_CMD_LINE - different name of the option static Sys_var_tx_isolation Sys_tx_isolation( - "tx_isolation", "Default transaction isolation level", - NO_SET_STMT SESSION_VAR(tx_isolation), NO_CMD_LINE, + "tx_isolation", "Default transaction isolation level." + "This variable is deprecated and will be removed in a future release.", + SESSION_VAR(tx_isolation), NO_CMD_LINE, + tx_isolation_names, DEFAULT(ISO_REPEATABLE_READ), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_tx_isolation), + ON_UPDATE(0), DEPRECATED("'@@transaction_isolation'")); // since 11.1.0 + +static Sys_var_tx_isolation Sys_transaction_isolation( + "transaction_isolation", "Default transaction isolation level", + SESSION_VAR(tx_isolation), NO_CMD_LINE, tx_isolation_names, DEFAULT(ISO_REPEATABLE_READ), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_tx_isolation)); /** - Can't change the tx_read_only state if we are already in a + Can't change the transaction_read_only state if we are already in a transaction. */ @@ -4269,11 +4277,21 @@ bool Sys_var_tx_read_only::session_update(THD *thd, set_var *var) return false; } - +// NO_CMD_LINE - different name of the option static Sys_var_tx_read_only Sys_tx_read_only( "tx_read_only", "Default transaction access mode. If set to OFF, " "the default, access is read/write. If set to ON, access is read-only. " "The SET TRANSACTION statement can also change the value of this variable. " + "See SET TRANSACTION and START TRANSACTION." + "This variable is deprecated and will be removed in a future release.", + SESSION_VAR(tx_read_only), NO_CMD_LINE, DEFAULT(0), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_tx_read_only), + ON_UPDATE(0), DEPRECATED("'@@transaction_read_only'")); // since 11.1.0 + +static Sys_var_tx_read_only Sys_transaction_read_only( + "transaction_read_only", "Default transaction access mode. If set to OFF, " + "the default, access is read/write. If set to ON, access is read-only. " + "The SET TRANSACTION statement can also change the value of this variable. " "See SET TRANSACTION and START TRANSACTION.", SESSION_VAR(tx_read_only), NO_CMD_LINE, DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_tx_read_only)); diff --git a/sql/sys_vars.inl b/sql/sys_vars.inl index 2c5acdcdc6b..97ba03c84ab 100644 --- a/sql/sys_vars.inl +++ b/sql/sys_vars.inl @@ -2402,9 +2402,12 @@ public: CMD_LINE getopt, const char *values[], uint def_val, PolyLock *lock, enum binlog_status_enum binlog_status_arg, - on_check_function on_check_func) + on_check_function on_check_func, + on_update_function on_update_func=0, + const char *substitute=0) :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt, - values, def_val, lock, binlog_status_arg, on_check_func) + values, def_val, lock, binlog_status_arg, on_check_func, + on_update_func, substitute) {} bool session_update(THD *thd, set_var *var) { @@ -2448,7 +2451,7 @@ public: /** - Class representing the tx_read_only system variable for setting + Class representing the transaction_read_only system variable for setting default transaction access mode. Note that there is a special syntax - SET TRANSACTION READ ONLY @@ -2463,9 +2466,12 @@ public: ptrdiff_t off, size_t size, CMD_LINE getopt, my_bool def_val, PolyLock *lock, enum binlog_status_enum binlog_status_arg, - on_check_function on_check_func) + on_check_function on_check_func, + on_update_function on_update_func=0, + const char *substitute=0) :Sys_var_mybool(name_arg, comment, flag_args, off, size, getopt, - def_val, lock, binlog_status_arg, on_check_func) + def_val, lock, binlog_status_arg, on_check_func, + on_update_func, substitute) {} virtual bool session_update(THD *thd, set_var *var); }; diff --git a/sql/table.cc b/sql/table.cc index fc53d0b062c..b8ed7a99156 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -46,6 +46,10 @@ #include "sql_show.h" #include "opt_trace.h" #include "sql_db.h" // get_default_db_collation +#include "sql_update.h" // class Sql_cmd_update +#include "sql_delete.h" // class Sql_cmd_delete + + /* For MySQL 5.7 virtual fields */ #define MYSQL57_GENERATED_FIELD 128 @@ -7178,7 +7182,8 @@ void Field_iterator_table_ref::set_field_iterator() table_ref->alias.str)); } /* This is a merge view, so use field_translation. */ - else if (table_ref->is_merged_derived() && table_ref->field_translation) + else if (!table_ref->is_materialized_derived() && + table_ref->is_merged_derived() && table_ref->field_translation) { field_it= &view_field_it; DBUG_PRINT("info", ("field_it for '%s' is Field_iterator_view", @@ -7187,7 +7192,7 @@ void Field_iterator_table_ref::set_field_iterator() /* This is a base table or stored view. */ else { - DBUG_ASSERT(table_ref->table || table_ref->view); + DBUG_ASSERT(table_ref->table || table_ref->is_materialized_derived()); field_it= &table_field_it; DBUG_PRINT("info", ("field_it for '%s' is Field_iterator_table", table_ref->alias.str)); @@ -9774,8 +9779,15 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view) (is_view() || optimizer_flag(thd, OPTIMIZER_SWITCH_DERIVED_MERGE)) && !thd->lex->can_not_use_merged() && - !((thd->lex->sql_command == SQLCOM_UPDATE_MULTI || - thd->lex->sql_command == SQLCOM_DELETE_MULTI) && !is_view()) && + !(!is_view() && + (thd->lex->sql_command == SQLCOM_UPDATE_MULTI || + thd->lex->sql_command == SQLCOM_DELETE_MULTI || + (thd->lex->sql_command == SQLCOM_UPDATE && + (((Sql_cmd_update *) thd->lex->m_sql_cmd)->is_multitable() || + thd->lex->query_tables->is_multitable())) || + (thd->lex->sql_command == SQLCOM_DELETE && + (((Sql_cmd_delete *) thd->lex->m_sql_cmd)->is_multitable() || + thd->lex->query_tables->is_multitable())))) && !is_recursive_with_table()) set_merged_derived(); else diff --git a/sql/table.h b/sql/table.h index 3874ccacb9a..d0d6f1e178b 100644 --- a/sql/table.h +++ b/sql/table.h @@ -2480,6 +2480,7 @@ struct TABLE_LIST */ select_unit *derived_result; /* Stub used for materialized derived tables. */ + bool delete_while_scanning; table_map map; /* ID bit of table (1,2,4,8,16...) */ table_map get_map() { diff --git a/sql/transaction.cc b/sql/transaction.cc index 123f9283d23..94c3ec1d1e1 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -181,7 +181,7 @@ bool trans_begin(THD *thd, uint flags) } thd->tx_read_only= false; /* - This flags that tx_read_only was set explicitly, rather than + This flags that transaction_read_only was set explicitly, rather than just from the session's default. */ #ifndef EMBEDDED_LIBRARY diff --git a/storage/connect/mysql-test/connect/r/upd.result b/storage/connect/mysql-test/connect/r/upd.result index 8faf00896bb..ad17f0f26ce 100644 --- a/storage/connect/mysql-test/connect/r/upd.result +++ b/storage/connect/mysql-test/connect/r/upd.result @@ -1627,3 +1627,159 @@ serialno name sex title manager department secretary salary DROP PROCEDURE test.tst_up; DROP TABLE employee; SET sql_mode = DEFAULT; +# +# End of 10.10 tests +# +SET sql_mode = 'NO_ENGINE_SUBSTITUTION'; +CREATE TABLE t1 +( +name char(12) not null, +city char(11) not null, +birth date not null date_format='DD/MM/YYYY', +hired date not null date_format='DD/MM/YYYY' flag=36 +) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='boys.txt' ENDING=1; +CREATE TABLE t2 ( +_id INT(2) NOT NULL, +name_first CHAR(9) NOT NULL JPATH='$.name.first', +name_aka CHAR(4) DEFAULT NULL JPATH='$.name.aka', +name_last CHAR(10) NOT NULL JPATH='$.name.last', +title CHAR(12) DEFAULT NULL, +birth CHAR(20) DEFAULT NULL, +death CHAR(20) DEFAULT NULL, +contribs CHAR(50) NOT NULL JPATH='$.contribs', +awards_award CHAR(42) DEFAULT NULL JPATH='$.awards.award', +awards_year CHAR(4) DEFAULT NULL JPATH='$.awards.year', +awards_by CHAR(38) DEFAULT NULL JPATH='$.awards.by' +) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='bios.json'; +# Multi-update +select t1.name, t1.city from t1; +name city +John Boston +Henry Boston +George San Jose +Sam Chicago +James Dallas +Bill Boston +select t2._id, t2.name_first, t2.name_aka, t2.name_last from t2; +_id name_first name_aka name_last +1 John NULL Backus +2 John NULL McCarthy +3 Grace NULL Hopper +4 Kristen NULL Nygaard +5 Ole-Johan NULL Dahl +6 Guido NULL van Rossum +7 Dennis NULL Ritchie +8 Yukihiro Matz Matsumoto +9 James NULL Gosling +10 Martin NULL Odersky +select t1.name, t2.name_last, t2.name_aka, t1.city from t1, t2 where t1.name=t2.name_first and t1.birth +BETWEEN '1992-01-01' and '1995-01-01'; +name name_last name_aka city +James Gosling NULL Dallas +explain update t1, t2 +set t1.city='Washington', t2.name_aka='von' where t1.name=t2.name_first and t1.birth +BETWEEN '1992-01-01' and '1995-01-01'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 10 Using where +update t1, t2 +set t1.city='Washington', t2.name_aka='von' where t1.name=t2.name_first and t1.birth +BETWEEN '1992-01-01' and '1995-01-01'; +select t1.name, t2.name_last, t2.name_aka, t1.city from t1, t2 where t1.name=t2.name_first and t1.birth +BETWEEN '1992-01-01' and '1995-01-01'; +name name_last name_aka city +James Gosling von Washington +# Conversion to multi-update +select t1.name, t1.city from t1; +name city +John Boston +Henry Boston +George San Jose +Sam Chicago +James Washington +Bill Boston +explain update t1 +set t1.city='New York' where t1.name in (select t2.name_first from t2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 6 +1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where; FirstMatch(t1) +update t1 +set t1.city='New York' where t1.name in (select t2.name_first from t2); +select t1.name, t1.city from t1; +name city +John New York +Henry Boston +George San Jose +Sam Chicago +James New York +Bill Boston +select t1.name, t1.city from t1 where t1.name in (select a.name from t1 as a where a.birth +BETWEEN '1981-01-01' and '1982-01-01'); +name city +George San Jose +explain update t1 set t1.city='Los Angeles' where t1.name in (select a.name from t1 as a where a.birth +BETWEEN '1981-01-01' and '1982-01-01'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 6 +1 PRIMARY a ALL NULL NULL NULL NULL 6 Using where; FirstMatch(t1) +update t1 set t1.city='Los Angeles' where t1.name in (select a.name from t1 as a where a.birth +BETWEEN '1981-01-01' and '1982-01-01'); +select t1.name, t1.city from t1 where t1.name in (select a.name from t1 as a where a.birth +BETWEEN '1981-01-01' and '1982-01-01'); +name city +George Los Angeles +# Multi-delete +explain delete t1.*, t2.* from t1, t2 where t1.name=t2.name_first and t1.birth +BETWEEN '1992-01-01' and '1995-01-01'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 10 Using where +delete t1.*, t2.* from t1, t2 where t1.name=t2.name_first and t1.birth +BETWEEN '1992-01-01' and '1995-01-01'; +select t1.name, t1.city from t1; +name city +John New York +Henry Boston +George Los Angeles +Sam Chicago +Bill Boston +select t2._id, t2.name_first, t2.name_aka, t2.name_last from t2; +_id name_first name_aka name_last +1 John NULL Backus +2 John NULL McCarthy +3 Grace NULL Hopper +4 Kristen NULL Nygaard +5 Ole-Johan NULL Dahl +6 Guido NULL van Rossum +7 Dennis NULL Ritchie +8 Yukihiro Matz Matsumoto +10 Martin NULL Odersky +# Conversion to multi-delete +explain delete from t1 where t1.name in (select t2.name_first from t2); +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 9 Using where; FirstMatch(t1) +delete from t1 where t1.name in (select t2.name_first from t2); +select t1.name, t1.city from t1; +name city +Henry Boston +George Los Angeles +Sam Chicago +Bill Boston +explain delete from t1 where t1.name in (select a.name from t1 as a where a.birth +BETWEEN '1981-01-01' and '1982-01-01'); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 +1 PRIMARY a ALL NULL NULL NULL NULL 4 Using where; FirstMatch(t1) +delete from t1 where t1.name in (select a.name from t1 as a where a.birth +BETWEEN '1981-01-01' and '1982-01-01'); +select t1.name, t1.city from t1; +name city +Henry Boston +Sam Chicago +Bill Boston +drop tables t1, t2; +SET sql_mode = DEFAULT; +# +# End of 11.0 tests +# diff --git a/storage/connect/mysql-test/connect/t/upd.test b/storage/connect/mysql-test/connect/t/upd.test index 28b566b5641..0372a9a83a1 100644 --- a/storage/connect/mysql-test/connect/t/upd.test +++ b/storage/connect/mysql-test/connect/t/upd.test @@ -155,3 +155,99 @@ DROP TABLE employee; SET sql_mode = DEFAULT; --remove_file $MYSQLD_DATADIR/test/employee.dat + +--echo # +--echo # End of 10.10 tests +--echo # + +--copy_file $MTR_SUITE_DIR/std_data/boys.txt $MYSQLD_DATADIR/test/boys.txt +--copy_file $MTR_SUITE_DIR/std_data/bios.json $MYSQLD_DATADIR/test/bios.json + +SET sql_mode = 'NO_ENGINE_SUBSTITUTION'; + +CREATE TABLE t1 +( + name char(12) not null, + city char(11) not null, + birth date not null date_format='DD/MM/YYYY', + hired date not null date_format='DD/MM/YYYY' flag=36 +) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='boys.txt' ENDING=1; + +CREATE TABLE t2 ( + _id INT(2) NOT NULL, + name_first CHAR(9) NOT NULL JPATH='$.name.first', + name_aka CHAR(4) DEFAULT NULL JPATH='$.name.aka', + name_last CHAR(10) NOT NULL JPATH='$.name.last', + title CHAR(12) DEFAULT NULL, + birth CHAR(20) DEFAULT NULL, + death CHAR(20) DEFAULT NULL, + contribs CHAR(50) NOT NULL JPATH='$.contribs', + awards_award CHAR(42) DEFAULT NULL JPATH='$.awards.award', + awards_year CHAR(4) DEFAULT NULL JPATH='$.awards.year', + awards_by CHAR(38) DEFAULT NULL JPATH='$.awards.by' +) ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='bios.json'; + +--echo # Multi-update + +select t1.name, t1.city from t1; +select t2._id, t2.name_first, t2.name_aka, t2.name_last from t2; + +let $c1 = where t1.name=t2.name_first and t1.birth + BETWEEN '1992-01-01' and '1995-01-01'; + +eval select t1.name, t2.name_last, t2.name_aka, t1.city from t1, t2 $c1; +eval explain update t1, t2 + set t1.city='Washington', t2.name_aka='von' $c1; +eval update t1, t2 + set t1.city='Washington', t2.name_aka='von' $c1; +eval select t1.name, t2.name_last, t2.name_aka, t1.city from t1, t2 $c1; + +--echo # Conversion to multi-update + +let $c2 = where t1.name in (select t2.name_first from t2); + +select t1.name, t1.city from t1; +eval explain update t1 + set t1.city='New York' $c2; +eval update t1 + set t1.city='New York' $c2; +select t1.name, t1.city from t1; + +let $c3 = where t1.name in (select a.name from t1 as a where a.birth + BETWEEN '1981-01-01' and '1982-01-01'); + +eval select t1.name, t1.city from t1 $c3; +eval explain update t1 set t1.city='Los Angeles' $c3; +eval update t1 set t1.city='Los Angeles' $c3; +eval select t1.name, t1.city from t1 $c3; + +--echo # Multi-delete + +eval explain delete t1.*, t2.* from t1, t2 $c1; +eval delete t1.*, t2.* from t1, t2 $c1; + +select t1.name, t1.city from t1; +select t2._id, t2.name_first, t2.name_aka, t2.name_last from t2; + +--echo # Conversion to multi-delete + +eval explain delete from t1 $c2; +eval delete from t1 $c2; + +select t1.name, t1.city from t1; + +eval explain delete from t1 $c3; +eval delete from t1 $c3; + +select t1.name, t1.city from t1; + +drop tables t1, t2; + +SET sql_mode = DEFAULT; + +--remove_file $MYSQLD_DATADIR/test/boys.txt +--remove_file $MYSQLD_DATADIR/test/bios.json + +--echo # +--echo # End of 11.0 tests +--echo # diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 3b1a285104c..c64fe95c71b 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -132,7 +132,6 @@ SET(INNOBASE_SOURCES btr/btr0cur.cc btr/btr0pcur.cc btr/btr0sea.cc - btr/btr0defragment.cc buf/buf0block_hint.cc buf/buf0buddy.cc buf/buf0buf.cc @@ -151,7 +150,6 @@ SET(INNOBASE_SOURCES dict/dict0mem.cc dict/dict0stats.cc dict/dict0stats_bg.cc - dict/dict0defrag_bg.cc dict/drop.cc eval/eval0eval.cc eval/eval0proc.cc @@ -186,7 +184,6 @@ SET(INNOBASE_SOURCES include/btr0bulk.h include/btr0cur.h include/btr0cur.inl - include/btr0defragment.h include/btr0pcur.h include/btr0pcur.inl include/btr0sea.h @@ -211,7 +208,6 @@ SET(INNOBASE_SOURCES include/dict0boot.h include/dict0crea.h include/dict0crea.inl - include/dict0defrag_bg.h include/dict0dict.h include/dict0dict.inl include/dict0load.h diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index a95866d4a05..06b785b8b39 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -34,7 +34,6 @@ Created 6/2/1994 Heikki Tuuri #include "btr0cur.h" #include "btr0sea.h" #include "btr0pcur.h" -#include "btr0defragment.h" #include "rem0cmp.h" #include "lock0lock.h" #include "trx0trx.h" @@ -2861,12 +2860,6 @@ got_split_rec: } btr_page_create(new_block, new_page_zip, cursor->index(), page_level, mtr); - /* Only record the leaf level page splits. */ - if (!page_level) { - cursor->index()->stat_defrag_n_page_split ++; - cursor->index()->stat_defrag_modified_counter ++; - btr_defragment_save_defrag_stats_if_needed(cursor->index()); - } /* 3. Calculate the first record on the upper half-page, and the first record (move_limit) on original page which ends up on the diff --git a/storage/innobase/btr/btr0defragment.cc b/storage/innobase/btr/btr0defragment.cc deleted file mode 100644 index 2f0b167f655..00000000000 --- a/storage/innobase/btr/btr0defragment.cc +++ /dev/null @@ -1,802 +0,0 @@ -/***************************************************************************** - -Copyright (C) 2012, 2014 Facebook, Inc. All Rights Reserved. -Copyright (C) 2014, 2023, MariaDB Corporation. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA - -*****************************************************************************/ -/**************************************************//** -@file btr/btr0defragment.cc -Index defragmentation. - -Created 05/29/2014 Rongrong Zhong -Modified 16/07/2014 Sunguck Lee -Modified 30/07/2014 Jan Lindström jan.lindstrom@mariadb.com -*******************************************************/ - -#include "btr0defragment.h" -#include "btr0btr.h" -#include "btr0cur.h" -#include "btr0sea.h" -#include "btr0pcur.h" -#include "dict0stats.h" -#include "dict0stats_bg.h" -#include "dict0defrag_bg.h" -#include "lock0lock.h" -#include "srv0start.h" -#include "mysqld.h" - -#include <list> - -/* When there's no work, either because defragment is disabled, or because no -query is submitted, thread checks state every BTR_DEFRAGMENT_SLEEP_IN_USECS.*/ -#define BTR_DEFRAGMENT_SLEEP_IN_USECS 1000000 -/* Reduce the target page size by this amount when compression failure happens -during defragmentaiton. 512 is chosen because it's a power of 2 and it is about -3% of the page size. When there are compression failures in defragmentation, -our goal is to get a decent defrag ratio with as few compression failure as -possible. From experimentation it seems that reduce the target size by 512 every -time will make sure the page is compressible within a couple of iterations. */ -#define BTR_DEFRAGMENT_PAGE_REDUCTION_STEP_SIZE 512 - -/** Item in the work queue for btr_degrament_thread. */ -struct btr_defragment_item_t -{ - /** persistent cursor where btr_defragment_n_pages should start */ - btr_pcur_t * const pcur; - /** completion signal */ - pthread_cond_t *cond; - /** timestamp of last time this index is processed by defragment thread */ - ulonglong last_processed= 0; - - btr_defragment_item_t(btr_pcur_t *pcur, pthread_cond_t *cond) - : pcur(pcur), cond(cond) {} -}; - -/* Work queue for defragmentation. */ -typedef std::list<btr_defragment_item_t*> btr_defragment_wq_t; -static btr_defragment_wq_t btr_defragment_wq; - -/* Mutex protecting the defragmentation work queue.*/ -static mysql_mutex_t btr_defragment_mutex; -#ifdef UNIV_PFS_MUTEX -mysql_pfs_key_t btr_defragment_mutex_key; -#endif /* UNIV_PFS_MUTEX */ - -/* Number of compression failures caused by defragmentation since server -start. */ -Atomic_counter<ulint> btr_defragment_compression_failures; -/* Number of btr_defragment_n_pages calls that altered page but didn't -manage to release any page. */ -Atomic_counter<ulint> btr_defragment_failures; -/* Total number of btr_defragment_n_pages calls that altered page. -The difference between btr_defragment_count and btr_defragment_failures shows -the amount of effort wasted. */ -Atomic_counter<ulint> btr_defragment_count; - -bool btr_defragment_active; -static void btr_defragment_chunk(void*); - -static tpool::timer* btr_defragment_timer; -static tpool::task_group task_group(1); -static tpool::task btr_defragment_task(btr_defragment_chunk, 0, &task_group); -static void btr_defragment_start(); - -static void submit_defragment_task(void*arg=0) -{ - srv_thread_pool->submit_task(&btr_defragment_task); -} - -/******************************************************************//** -Initialize defragmentation. */ -void -btr_defragment_init() -{ - srv_defragment_interval = 1000000000ULL / srv_defragment_frequency; - mysql_mutex_init(btr_defragment_mutex_key, &btr_defragment_mutex, - nullptr); - btr_defragment_timer = srv_thread_pool->create_timer(submit_defragment_task); - btr_defragment_active = true; -} - -/******************************************************************//** -Shutdown defragmentation. Release all resources. */ -void -btr_defragment_shutdown() -{ - if (!btr_defragment_timer) - return; - delete btr_defragment_timer; - btr_defragment_timer = 0; - task_group.cancel_pending(&btr_defragment_task); - mysql_mutex_lock(&btr_defragment_mutex); - std::list< btr_defragment_item_t* >::iterator iter = btr_defragment_wq.begin(); - while(iter != btr_defragment_wq.end()) { - btr_defragment_item_t* item = *iter; - iter = btr_defragment_wq.erase(iter); - if (item->cond) { - pthread_cond_signal(item->cond); - } - } - mysql_mutex_unlock(&btr_defragment_mutex); - mysql_mutex_destroy(&btr_defragment_mutex); - btr_defragment_active = false; -} - - -/******************************************************************//** -Functions used by the query threads: btr_defragment_xxx_index -Query threads find/add/remove index. */ -/******************************************************************//** -Check whether the given index is in btr_defragment_wq. We use index->id -to identify indices. */ -bool -btr_defragment_find_index( - dict_index_t* index) /*!< Index to find. */ -{ - mysql_mutex_lock(&btr_defragment_mutex); - for (std::list< btr_defragment_item_t* >::iterator iter = btr_defragment_wq.begin(); - iter != btr_defragment_wq.end(); - ++iter) { - btr_defragment_item_t* item = *iter; - btr_pcur_t* pcur = item->pcur; - btr_cur_t* cursor = btr_pcur_get_btr_cur(pcur); - dict_index_t* idx = btr_cur_get_index(cursor); - if (index->id == idx->id) { - mysql_mutex_unlock(&btr_defragment_mutex); - return true; - } - } - mysql_mutex_unlock(&btr_defragment_mutex); - return false; -} - -/** Defragment an index. -@param pcur persistent cursor -@param thd current session, for checking thd_killed() -@return whether the operation was interrupted */ -bool btr_defragment_add_index(btr_pcur_t *pcur, THD *thd) -{ - dict_stats_empty_defrag_summary(pcur->index()); - pthread_cond_t cond; - pthread_cond_init(&cond, nullptr); - btr_defragment_item_t item(pcur, &cond); - mysql_mutex_lock(&btr_defragment_mutex); - btr_defragment_wq.push_back(&item); - if (btr_defragment_wq.size() == 1) - /* Kick off defragmentation work */ - btr_defragment_start(); - bool interrupted= false; - for (;;) - { - timespec abstime; - set_timespec(abstime, 1); - if (!my_cond_timedwait(&cond, &btr_defragment_mutex.m_mutex, &abstime)) - break; - if (thd_killed(thd)) - { - item.cond= nullptr; - interrupted= true; - break; - } - } - - pthread_cond_destroy(&cond); - mysql_mutex_unlock(&btr_defragment_mutex); - return interrupted; -} - -/******************************************************************//** -When table is dropped, this function is called to mark a table as removed in -btr_efragment_wq. The difference between this function and the remove_index -function is this will not NULL the event. */ -void -btr_defragment_remove_table( - dict_table_t* table) /*!< Index to be removed. */ -{ - mysql_mutex_lock(&btr_defragment_mutex); - for (auto item : btr_defragment_wq) - { - if (item->cond && table == item->pcur->index()->table) - { - pthread_cond_signal(item->cond); - item->cond= nullptr; - } - } - mysql_mutex_unlock(&btr_defragment_mutex); -} - -/*********************************************************************//** -Check whether we should save defragmentation statistics to persistent storage. -Currently we save the stats to persistent storage every 100 updates. */ -void btr_defragment_save_defrag_stats_if_needed(dict_index_t *index) -{ - if (srv_defragment_stats_accuracy != 0 // stats tracking disabled - && index->table->space_id != 0 // do not track system tables - && !index->table->is_temporary() - && index->stat_defrag_modified_counter - >= srv_defragment_stats_accuracy) { - dict_stats_defrag_pool_add(index); - index->stat_defrag_modified_counter = 0; - } -} - -/*********************************************************************//** -Main defragment functionalities used by defragment thread.*/ -/*************************************************************//** -Calculate number of records from beginning of block that can -fit into size_limit -@return number of records */ -static -ulint -btr_defragment_calc_n_recs_for_size( - buf_block_t* block, /*!< in: B-tree page */ - dict_index_t* index, /*!< in: index of the page */ - ulint size_limit, /*!< in: size limit to fit records in */ - ulint* n_recs_size) /*!< out: actual size of the records that fit - in size_limit. */ -{ - page_t* page = buf_block_get_frame(block); - ulint n_recs = 0; - rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; - rec_offs* offsets = offsets_; - rec_offs_init(offsets_); - mem_heap_t* heap = NULL; - ulint size = 0; - page_cur_t cur; - - const ulint n_core = page_is_leaf(page) ? index->n_core_fields : 0; - page_cur_set_before_first(block, &cur); - while (rec_t* cur_rec = page_cur_move_to_next(&cur)) { - if (page_rec_is_supremum(cur_rec)) { - break; - } - offsets = rec_get_offsets(cur_rec, index, offsets, n_core, - ULINT_UNDEFINED, &heap); - ulint rec_size = rec_offs_size(offsets); - size += rec_size; - if (size > size_limit) { - size = size - rec_size; - break; - } - n_recs ++; - } - *n_recs_size = size; - if (UNIV_LIKELY_NULL(heap)) { - mem_heap_free(heap); - } - return n_recs; -} - -MY_ATTRIBUTE((nonnull(2,3,4), warn_unused_result)) -/************************************************************//** -Returns the upper level node pointer to a page. It is assumed that mtr holds -an sx-latch on the tree. -@return rec_get_offsets() of the node pointer record */ -static -rec_offs* -btr_page_search_father_node_ptr( - rec_offs* offsets,/*!< in: work area for the return value */ - mem_heap_t* heap, /*!< in: memory heap to use */ - btr_cur_t* cursor, /*!< in: cursor pointing to user record, - out: cursor on node pointer record, - its page x-latched */ - mtr_t* mtr) /*!< in: mtr */ -{ - const uint32_t page_no = btr_cur_get_block(cursor)->page.id().page_no(); - dict_index_t* index = btr_cur_get_index(cursor); - ut_ad(!index->is_spatial()); - - ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK - | MTR_MEMO_SX_LOCK)); - ut_ad(dict_index_get_page(index) != page_no); - - const auto level = btr_page_get_level(btr_cur_get_page(cursor)); - - const rec_t* user_rec = btr_cur_get_rec(cursor); - ut_a(page_rec_is_user_rec(user_rec)); - - if (btr_cur_search_to_nth_level(level + 1, - dict_index_build_node_ptr(index, - user_rec, 0, - heap, level), - RW_X_LATCH, - cursor, mtr) != DB_SUCCESS) { - return nullptr; - } - - const rec_t* node_ptr = btr_cur_get_rec(cursor); - ut_ad(!btr_cur_get_block(cursor)->page.lock.not_recursive() - || mtr->memo_contains(index->lock, MTR_MEMO_X_LOCK)); - - offsets = rec_get_offsets(node_ptr, index, offsets, 0, - ULINT_UNDEFINED, &heap); - - if (btr_node_ptr_get_child_page_no(node_ptr, offsets) != page_no) { - offsets = nullptr; - } - - return(offsets); -} - -static bool btr_page_search_father(mtr_t *mtr, btr_cur_t *cursor) -{ - rec_t *rec= - page_rec_get_next(page_get_infimum_rec(cursor->block()->page.frame)); - if (UNIV_UNLIKELY(!rec)) - return false; - cursor->page_cur.rec= rec; - mem_heap_t *heap= mem_heap_create(100); - const bool got= btr_page_search_father_node_ptr(nullptr, heap, cursor, mtr); - mem_heap_free(heap); - return got; -} - -/*************************************************************//** -Merge as many records from the from_block to the to_block. Delete -the from_block if all records are successfully merged to to_block. -@return the to_block to target for next merge operation. -@retval nullptr if corruption was noticed */ -static -buf_block_t* -btr_defragment_merge_pages( - dict_index_t* index, /*!< in: index tree */ - buf_block_t* from_block, /*!< in: origin of merge */ - buf_block_t* to_block, /*!< in: destination of merge */ - ulint zip_size, /*!< in: ROW_FORMAT=COMPRESSED size */ - ulint reserved_space, /*!< in: space reserved for future - insert to avoid immediate page split */ - ulint* max_data_size, /*!< in/out: max data size to - fit in a single compressed page. */ - mem_heap_t* heap, /*!< in/out: pointer to memory heap */ - mtr_t* mtr) /*!< in/out: mini-transaction */ -{ - page_t* from_page = buf_block_get_frame(from_block); - page_t* to_page = buf_block_get_frame(to_block); - ulint level = btr_page_get_level(from_page); - ulint n_recs = page_get_n_recs(from_page); - ulint new_data_size = page_get_data_size(to_page); - ulint max_ins_size = - page_get_max_insert_size(to_page, n_recs); - ulint max_ins_size_reorg = - page_get_max_insert_size_after_reorganize( - to_page, n_recs); - ulint max_ins_size_to_use = max_ins_size_reorg > reserved_space - ? max_ins_size_reorg - reserved_space : 0; - ulint move_size = 0; - ulint n_recs_to_move = 0; - rec_t* rec = NULL; - ulint target_n_recs = 0; - rec_t* orig_pred; - - // Estimate how many records can be moved from the from_page to - // the to_page. - if (zip_size) { - ulint page_diff = srv_page_size - *max_data_size; - max_ins_size_to_use = (max_ins_size_to_use > page_diff) - ? max_ins_size_to_use - page_diff : 0; - } - n_recs_to_move = btr_defragment_calc_n_recs_for_size( - from_block, index, max_ins_size_to_use, &move_size); - - // If max_ins_size >= move_size, we can move the records without - // reorganizing the page, otherwise we need to reorganize the page - // first to release more space. - if (move_size <= max_ins_size) { - } else if (dberr_t err = btr_page_reorganize_block(page_zip_level, - to_block, index, - mtr)) { - // If reorganization fails, that means page is - // not compressable. There's no point to try - // merging into this page. Continue to the - // next page. - return err == DB_FAIL ? from_block : nullptr; - } else { - ut_ad(page_validate(to_page, index)); - max_ins_size = page_get_max_insert_size(to_page, n_recs); - if (max_ins_size < move_size) { - return nullptr; - } - } - - // Move records to pack to_page more full. - orig_pred = NULL; - target_n_recs = n_recs_to_move; - dberr_t err; - while (n_recs_to_move > 0) { - if (!(rec = page_rec_get_nth(from_page, n_recs_to_move + 1))) { - return nullptr; - } - orig_pred = page_copy_rec_list_start( - to_block, from_block, rec, index, mtr, &err); - if (orig_pred) - break; - if (err != DB_FAIL) { - return nullptr; - } - - // If we reach here, that means compression failed after packing - // n_recs_to_move number of records to to_page. We try to reduce - // the targeted data size on the to_page by - // BTR_DEFRAGMENT_PAGE_REDUCTION_STEP_SIZE and try again. - btr_defragment_compression_failures++; - max_ins_size_to_use = - move_size > BTR_DEFRAGMENT_PAGE_REDUCTION_STEP_SIZE - ? move_size - BTR_DEFRAGMENT_PAGE_REDUCTION_STEP_SIZE - : 0; - if (max_ins_size_to_use == 0) { - n_recs_to_move = 0; - move_size = 0; - break; - } - n_recs_to_move = btr_defragment_calc_n_recs_for_size( - from_block, index, max_ins_size_to_use, &move_size); - } - // If less than target_n_recs are moved, it means there are - // compression failures during page_copy_rec_list_start. Adjust - // the max_data_size estimation to reduce compression failures - // in the following runs. - if (target_n_recs > n_recs_to_move - && *max_data_size > new_data_size + move_size) { - *max_data_size = new_data_size + move_size; - } - btr_cur_t parent; - parent.page_cur.index = index; - parent.page_cur.block = from_block; - - if (!btr_page_search_father(mtr, &parent)) { - to_block = nullptr; - } else if (n_recs_to_move == n_recs) { - /* The whole page is merged with the previous page, - free it. */ - lock_update_merge_left(*to_block, orig_pred, - from_block->page.id()); - btr_search_drop_page_hash_index(from_block, false); - if (btr_level_list_remove(*from_block, *index, mtr) - != DB_SUCCESS - || btr_cur_node_ptr_delete(&parent, mtr) != DB_SUCCESS - || btr_page_free(index, from_block, mtr) != DB_SUCCESS) { - return nullptr; - } - } else { - // There are still records left on the page, so - // increment n_defragmented. Node pointer will be changed - // so remove the old node pointer. - if (n_recs_to_move > 0) { - // Part of the page is merged to left, remove - // the merged records, update record locks and - // node pointer. - dtuple_t* node_ptr; - page_delete_rec_list_start(rec, from_block, - index, mtr); - lock_update_split_and_merge(to_block, - orig_pred, - from_block); - // FIXME: reuse the node_ptr! - if (btr_cur_node_ptr_delete(&parent, mtr) - != DB_SUCCESS) { - return nullptr; - } - rec = page_rec_get_next( - page_get_infimum_rec(from_page)); - if (!rec) { - return nullptr; - } - node_ptr = dict_index_build_node_ptr( - index, rec, page_get_page_no(from_page), - heap, level); - if (btr_insert_on_non_leaf_level(0, index, level+1, - node_ptr, mtr) - != DB_SUCCESS) { - return nullptr; - } - } - to_block = from_block; - } - return to_block; -} - -/*************************************************************//** -Tries to merge N consecutive pages, starting from the page pointed by the -cursor. Skip space 0. Only consider leaf pages. -This function first loads all N pages into memory, then for each of -the pages other than the first page, it tries to move as many records -as possible to the left sibling to keep the left sibling full. During -the process, if any page becomes empty, that page will be removed from -the level list. Record locks, hash, and node pointers are updated after -page reorganization. -@return pointer to the last block processed, or NULL if reaching end of index */ -static -buf_block_t* -btr_defragment_n_pages( - buf_block_t* block, /*!< in: starting block for defragmentation */ - dict_index_t* index, /*!< in: index tree */ - uint n_pages,/*!< in: number of pages to defragment */ - mtr_t* mtr) /*!< in/out: mini-transaction */ -{ - /* We will need to load the n+1 block because if the last page is freed - and we need to modify the prev_page_no of that block. */ - buf_block_t* blocks[BTR_DEFRAGMENT_MAX_N_PAGES + 1]; - page_t* first_page; - buf_block_t* current_block; - ulint total_data_size = 0; - ulint total_n_recs = 0; - ulint data_size_per_rec; - ulint optimal_page_size; - ulint reserved_space; - ulint max_data_size = 0; - uint n_defragmented = 0; - uint n_new_slots; - mem_heap_t* heap; - ibool end_of_index = FALSE; - - /* It doesn't make sense to call this function with n_pages = 1. */ - ut_ad(n_pages > 1); - - if (!page_is_leaf(block->page.frame)) { - return NULL; - } - - if (!index->table->space || !index->table->space_id) { - /* Ignore space 0. */ - return NULL; - } - - if (n_pages > BTR_DEFRAGMENT_MAX_N_PAGES) { - n_pages = BTR_DEFRAGMENT_MAX_N_PAGES; - } - - first_page = buf_block_get_frame(block); - const ulint zip_size = index->table->space->zip_size(); - - /* 1. Load the pages and calculate the total data size. */ - blocks[0] = block; - for (uint i = 1; i <= n_pages; i++) { - page_t* page = buf_block_get_frame(blocks[i-1]); - uint32_t page_no = btr_page_get_next(page); - total_data_size += page_get_data_size(page); - total_n_recs += page_get_n_recs(page); - if (page_no == FIL_NULL) { - n_pages = i; - end_of_index = TRUE; - break; - } - - blocks[i] = btr_block_get(*index, page_no, RW_X_LATCH, mtr); - if (!blocks[i]) { - return nullptr; - } - } - - if (n_pages == 1) { - if (!page_has_prev(first_page)) { - /* last page in the index */ - if (dict_index_get_page(index) - == page_get_page_no(first_page)) - return NULL; - /* given page is the last page. - Lift the records to father. */ - dberr_t err; - btr_lift_page_up(index, block, nullptr, mtr, &err); - } - return NULL; - } - - /* 2. Calculate how many pages data can fit in. If not compressable, - return early. */ - ut_a(total_n_recs != 0); - data_size_per_rec = total_data_size / total_n_recs; - // For uncompressed pages, the optimal data size if the free space of a - // empty page. - optimal_page_size = page_get_free_space_of_empty( - page_is_comp(first_page)); - // For compressed pages, we take compression failures into account. - if (zip_size) { - ulint size = 0; - uint i = 0; - // We estimate the optimal data size of the index use samples of - // data size. These samples are taken when pages failed to - // compress due to insertion on the page. We use the average - // of all samples we have as the estimation. Different pages of - // the same index vary in compressibility. Average gives a good - // enough estimation. - for (;i < STAT_DEFRAG_DATA_SIZE_N_SAMPLE; i++) { - if (index->stat_defrag_data_size_sample[i] == 0) { - break; - } - size += index->stat_defrag_data_size_sample[i]; - } - if (i != 0) { - size /= i; - optimal_page_size = ut_min(optimal_page_size, size); - } - max_data_size = optimal_page_size; - } - - reserved_space = ut_min(static_cast<ulint>( - static_cast<double>(optimal_page_size) - * (1 - srv_defragment_fill_factor)), - (data_size_per_rec - * srv_defragment_fill_factor_n_recs)); - optimal_page_size -= reserved_space; - n_new_slots = uint((total_data_size + optimal_page_size - 1) - / optimal_page_size); - if (n_new_slots >= n_pages) { - /* Can't defragment. */ - if (end_of_index) - return NULL; - return blocks[n_pages-1]; - } - - /* 3. Defragment pages. */ - heap = mem_heap_create(256); - // First defragmented page will be the first page. - current_block = blocks[0]; - // Start from the second page. - for (uint i = 1; i < n_pages; i ++) { - buf_block_t* new_block = btr_defragment_merge_pages( - index, blocks[i], current_block, zip_size, - reserved_space, &max_data_size, heap, mtr); - if (new_block != current_block) { - n_defragmented ++; - current_block = new_block; - if (!new_block) { - break; - } - } - } - mem_heap_free(heap); - n_defragmented ++; - btr_defragment_count++; - if (n_pages == n_defragmented) { - btr_defragment_failures++; - } else { - index->stat_defrag_n_pages_freed += (n_pages - n_defragmented); - } - if (end_of_index) - return NULL; - return current_block; -} - - - -void btr_defragment_start() { - if (!srv_defragment) - return; - ut_ad(!btr_defragment_wq.empty()); - submit_defragment_task(); -} - - -/** -Callback used by defragment timer - -Throttling "sleep", is implemented via rescheduling the -threadpool timer, which, when fired, will resume the work again, -where it is left. - -The state (current item) is stored in function parameter. -*/ -static void btr_defragment_chunk(void*) -{ - THD *thd = innobase_create_background_thd("InnoDB defragment"); - set_current_thd(thd); - - btr_defragment_item_t* item = nullptr; - mtr_t mtr; - - mysql_mutex_lock(&btr_defragment_mutex); - - while (srv_shutdown_state == SRV_SHUTDOWN_NONE) { - if (!item) { - if (btr_defragment_wq.empty()) { -release_and_exit: - mysql_mutex_unlock(&btr_defragment_mutex); -func_exit: - set_current_thd(nullptr); - destroy_background_thd(thd); - return; - } - item = *btr_defragment_wq.begin(); - ut_ad(item); - } - - if (!item->cond) { -processed: - btr_defragment_wq.remove(item); - item = nullptr; - continue; - } - - mysql_mutex_unlock(&btr_defragment_mutex); - - ulonglong now = my_interval_timer(); - ulonglong elapsed = now - item->last_processed; - - if (elapsed < srv_defragment_interval) { - /* If we see an index again before the interval - determined by the configured frequency is reached, - we just sleep until the interval pass. Since - defragmentation of all indices queue up on a single - thread, it's likely other indices that follow this one - don't need to sleep again. */ - int sleep_ms = (int)((srv_defragment_interval - elapsed) / 1000 / 1000); - if (sleep_ms) { - btr_defragment_timer->set_time(sleep_ms, 0); - goto func_exit; - } - } - log_free_check(); - mtr_start(&mtr); - dict_index_t *index = item->pcur->index(); - index->set_modified(mtr); - /* To follow the latching order defined in WL#6326, - acquire index->lock X-latch. This entitles us to - acquire page latches in any order for the index. */ - mtr_x_lock_index(index, &mtr); - if (buf_block_t *last_block = - item->pcur->restore_position( - BTR_PURGE_TREE_ALREADY_LATCHED, &mtr) - == btr_pcur_t::CORRUPTED - ? nullptr - : btr_defragment_n_pages(btr_pcur_get_block(item->pcur), - index, srv_defragment_n_pages, - &mtr)) { - /* If we haven't reached the end of the index, - place the cursor on the last record of last page, - store the cursor position, and put back in queue. */ - page_t* last_page = buf_block_get_frame(last_block); - rec_t* rec = page_rec_get_prev( - page_get_supremum_rec(last_page)); - if (rec && page_rec_is_user_rec(rec)) { - page_cur_position(rec, last_block, - btr_pcur_get_page_cur( - item->pcur)); - } - btr_pcur_store_position(item->pcur, &mtr); - mtr_commit(&mtr); - /* Update the last_processed time of this index. */ - item->last_processed = now; - mysql_mutex_lock(&btr_defragment_mutex); - } else { - mtr_commit(&mtr); - /* Reaching the end of the index. */ - dict_stats_empty_defrag_stats(index); - if (dberr_t err= dict_stats_save_defrag_stats(index)) { - ib::error() << "Saving defragmentation stats for table " - << index->table->name - << " index " << index->name() - << " failed with error " << err; - } else { - err = dict_stats_save_defrag_summary(index, - thd); - - if (err != DB_SUCCESS) { - ib::error() << "Saving defragmentation summary for table " - << index->table->name - << " index " << index->name() - << " failed with error " << err; - } - } - - mysql_mutex_lock(&btr_defragment_mutex); - if (item->cond) { - pthread_cond_signal(item->cond); - } - goto processed; - } - } - - goto release_and_exit; -} diff --git a/storage/innobase/dict/dict0defrag_bg.cc b/storage/innobase/dict/dict0defrag_bg.cc deleted file mode 100644 index b688f3970fc..00000000000 --- a/storage/innobase/dict/dict0defrag_bg.cc +++ /dev/null @@ -1,429 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2016, 2023, MariaDB Corporation. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/**************************************************//** -@file dict/dict0defrag_bg.cc -Defragmentation routines. - -Created 25/08/2016 Jan Lindström -*******************************************************/ - -#include "dict0dict.h" -#include "dict0stats.h" -#include "dict0stats_bg.h" -#include "dict0defrag_bg.h" -#include "btr0btr.h" -#include "srv0start.h" -#include "trx0trx.h" -#include "lock0lock.h" -#include "row0mysql.h" - -static mysql_mutex_t defrag_pool_mutex; - -/** Iterator type for iterating over the elements of objects of type -defrag_pool_t. */ -typedef defrag_pool_t::iterator defrag_pool_iterator_t; - -/** Pool where we store information on which tables are to be processed -by background defragmentation. */ -defrag_pool_t defrag_pool; - - -/*****************************************************************//** -Initialize the defrag pool, called once during thread initialization. */ -void -dict_defrag_pool_init(void) -/*=======================*/ -{ - ut_ad(!srv_read_only_mode); - mysql_mutex_init(0, &defrag_pool_mutex, nullptr); -} - -/*****************************************************************//** -Free the resources occupied by the defrag pool, called once during -thread de-initialization. */ -void -dict_defrag_pool_deinit(void) -/*=========================*/ -{ - ut_ad(!srv_read_only_mode); - - mysql_mutex_destroy(&defrag_pool_mutex); -} - -/*****************************************************************//** -Get an index from the auto defrag pool. The returned index id is removed -from the pool. -@return true if the pool was non-empty and "id" was set, false otherwise */ -static -bool -dict_stats_defrag_pool_get( -/*=======================*/ - table_id_t* table_id, /*!< out: table id, or unmodified if - list is empty */ - index_id_t* index_id) /*!< out: index id, or unmodified if - list is empty */ -{ - ut_ad(!srv_read_only_mode); - - mysql_mutex_lock(&defrag_pool_mutex); - - if (defrag_pool.empty()) { - mysql_mutex_unlock(&defrag_pool_mutex); - return(false); - } - - defrag_pool_item_t& item = defrag_pool.back(); - *table_id = item.table_id; - *index_id = item.index_id; - - defrag_pool.pop_back(); - - mysql_mutex_unlock(&defrag_pool_mutex); - - return(true); -} - -/*****************************************************************//** -Add an index in a table to the defrag pool, which is processed by the -background stats gathering thread. Only the table id and index id are -added to the list, so the table can be closed after being enqueued and -it will be opened when needed. If the table or index does not exist later -(has been DROPped), then it will be removed from the pool and skipped. */ -void -dict_stats_defrag_pool_add( -/*=======================*/ - const dict_index_t* index) /*!< in: table to add */ -{ - defrag_pool_item_t item; - - ut_ad(!srv_read_only_mode); - - mysql_mutex_lock(&defrag_pool_mutex); - - /* quit if already in the list */ - for (defrag_pool_iterator_t iter = defrag_pool.begin(); - iter != defrag_pool.end(); - ++iter) { - if ((*iter).table_id == index->table->id - && (*iter).index_id == index->id) { - mysql_mutex_unlock(&defrag_pool_mutex); - return; - } - } - - item.table_id = index->table->id; - item.index_id = index->id; - defrag_pool.push_back(item); - if (defrag_pool.size() == 1) { - /* Kick off dict stats optimizer work */ - dict_stats_schedule_now(); - } - mysql_mutex_unlock(&defrag_pool_mutex); -} - -/*****************************************************************//** -Delete a given index from the auto defrag pool. */ -void -dict_stats_defrag_pool_del( -/*=======================*/ - const dict_table_t* table, /*!<in: if given, remove - all entries for the table */ - const dict_index_t* index) /*!< in: if given, remove this index */ -{ - ut_a((table && !index) || (!table && index)); - ut_ad(!srv_read_only_mode); - ut_ad(dict_sys.frozen()); - - mysql_mutex_lock(&defrag_pool_mutex); - - defrag_pool_iterator_t iter = defrag_pool.begin(); - while (iter != defrag_pool.end()) { - if ((table && (*iter).table_id == table->id) - || (index - && (*iter).table_id == index->table->id - && (*iter).index_id == index->id)) { - /* erase() invalidates the iterator */ - iter = defrag_pool.erase(iter); - if (index) - break; - } else { - iter++; - } - } - - mysql_mutex_unlock(&defrag_pool_mutex); -} - -/*****************************************************************//** -Get the first index that has been added for updating persistent defrag -stats and eventually save its stats. */ -static void dict_stats_process_entry_from_defrag_pool(THD *thd) -{ - table_id_t table_id; - index_id_t index_id; - - ut_ad(!srv_read_only_mode); - - /* pop the first index from the auto defrag pool */ - if (!dict_stats_defrag_pool_get(&table_id, &index_id)) - /* no index in defrag pool */ - return; - - /* If the table is no longer cached, we've already lost the in - memory stats so there's nothing really to write to disk. */ - MDL_ticket *mdl= nullptr; - if (dict_table_t *table= - dict_table_open_on_id(table_id, false, DICT_TABLE_OP_OPEN_ONLY_IF_CACHED, - thd, &mdl)) - { - if (dict_index_t *index= !table->corrupted - ? dict_table_find_index_on_id(table, index_id) : nullptr) - if (index->is_btree()) - dict_stats_save_defrag_stats(index); - dict_table_close(table, false, thd, mdl); - } -} - -/** -Get the first index that has been added for updating persistent defrag -stats and eventually save its stats. */ -void dict_defrag_process_entries_from_defrag_pool(THD *thd) -{ - while (!defrag_pool.empty()) - dict_stats_process_entry_from_defrag_pool(thd); -} - -/*********************************************************************//** -Save defragmentation result. -@return DB_SUCCESS or error code */ -dberr_t dict_stats_save_defrag_summary(dict_index_t *index, THD *thd) -{ - MDL_ticket *mdl_table= nullptr, *mdl_index= nullptr; - dict_table_t *table_stats= dict_table_open_on_name(TABLE_STATS_NAME, false, - DICT_ERR_IGNORE_NONE); - if (table_stats) - { - dict_sys.freeze(SRW_LOCK_CALL); - table_stats= dict_acquire_mdl_shared<false>(table_stats, thd, &mdl_table); - dict_sys.unfreeze(); - } - if (!table_stats || strcmp(table_stats->name.m_name, TABLE_STATS_NAME)) - { -release_and_exit: - if (table_stats) - dict_table_close(table_stats, false, thd, mdl_table); - return DB_STATS_DO_NOT_EXIST; - } - - dict_table_t *index_stats= dict_table_open_on_name(INDEX_STATS_NAME, false, - DICT_ERR_IGNORE_NONE); - if (index_stats) - { - dict_sys.freeze(SRW_LOCK_CALL); - index_stats= dict_acquire_mdl_shared<false>(index_stats, thd, &mdl_index); - dict_sys.unfreeze(); - } - if (!index_stats) - goto release_and_exit; - if (strcmp(index_stats->name.m_name, INDEX_STATS_NAME)) - { - dict_table_close(index_stats, false, thd, mdl_index); - goto release_and_exit; - } - - trx_t *trx= trx_create(); - trx->mysql_thd= thd; - trx_start_internal(trx); - dberr_t ret= trx->read_only - ? DB_READ_ONLY - : lock_table_for_trx(table_stats, trx, LOCK_X); - if (ret == DB_SUCCESS) - ret= lock_table_for_trx(index_stats, trx, LOCK_X); - row_mysql_lock_data_dictionary(trx); - if (ret == DB_SUCCESS) - ret= dict_stats_save_index_stat(index, time(nullptr), "n_pages_freed", - index->stat_defrag_n_pages_freed, - nullptr, - "Number of pages freed during" - " last defragmentation run.", - trx); - if (ret == DB_SUCCESS) - trx->commit(); - else - trx->rollback(); - - if (table_stats) - dict_table_close(table_stats, true, thd, mdl_table); - if (index_stats) - dict_table_close(index_stats, true, thd, mdl_index); - - row_mysql_unlock_data_dictionary(trx); - trx->free(); - - return ret; -} - -/**************************************************************//** -Gets the number of reserved and used pages in a B-tree. -@return number of pages reserved, or ULINT_UNDEFINED if the index -is unavailable */ -static -ulint -btr_get_size_and_reserved( - dict_index_t* index, /*!< in: index */ - ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */ - ulint* used, /*!< out: number of pages used (<= reserved) */ - mtr_t* mtr) /*!< in/out: mini-transaction where index - is s-latched */ -{ - ulint dummy; - - ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_SX_LOCK)); - ut_a(flag == BTR_N_LEAF_PAGES || flag == BTR_TOTAL_SIZE); - - if (index->page == FIL_NULL - || dict_index_is_online_ddl(index) - || !index->is_committed() - || !index->table->space) { - return(ULINT_UNDEFINED); - } - - dberr_t err; - buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, mtr, &err); - *used = 0; - if (!root) { - return ULINT_UNDEFINED; - } - - mtr->x_lock_space(index->table->space); - - ulint n = fseg_n_reserved_pages(*root, PAGE_HEADER + PAGE_BTR_SEG_LEAF - + root->page.frame, used, mtr); - if (flag == BTR_TOTAL_SIZE) { - n += fseg_n_reserved_pages(*root, - PAGE_HEADER + PAGE_BTR_SEG_TOP - + root->page.frame, &dummy, mtr); - *used += dummy; - } - - return(n); -} - -/*********************************************************************//** -Save defragmentation stats for a given index. -@return DB_SUCCESS or error code */ -dberr_t -dict_stats_save_defrag_stats( -/*============================*/ - dict_index_t* index) /*!< in: index */ -{ - if (!index->is_readable()) - return dict_stats_report_error(index->table, true); - - const time_t now= time(nullptr); - mtr_t mtr; - ulint n_leaf_pages; - mtr.start(); - mtr_sx_lock_index(index, &mtr); - ulint n_leaf_reserved= btr_get_size_and_reserved(index, BTR_N_LEAF_PAGES, - &n_leaf_pages, &mtr); - mtr.commit(); - - if (n_leaf_reserved == ULINT_UNDEFINED) - return DB_SUCCESS; - - THD *thd= current_thd; - MDL_ticket *mdl_table= nullptr, *mdl_index= nullptr; - dict_table_t* table_stats= dict_table_open_on_name(TABLE_STATS_NAME, false, - DICT_ERR_IGNORE_NONE); - if (table_stats) - { - dict_sys.freeze(SRW_LOCK_CALL); - table_stats= dict_acquire_mdl_shared<false>(table_stats, thd, &mdl_table); - dict_sys.unfreeze(); - } - if (!table_stats || strcmp(table_stats->name.m_name, TABLE_STATS_NAME)) - { -release_and_exit: - if (table_stats) - dict_table_close(table_stats, false, thd, mdl_table); - return DB_STATS_DO_NOT_EXIST; - } - - dict_table_t *index_stats= dict_table_open_on_name(INDEX_STATS_NAME, false, - DICT_ERR_IGNORE_NONE); - if (index_stats) - { - dict_sys.freeze(SRW_LOCK_CALL); - index_stats= dict_acquire_mdl_shared<false>(index_stats, thd, &mdl_index); - dict_sys.unfreeze(); - } - if (!index_stats) - goto release_and_exit; - - if (strcmp(index_stats->name.m_name, INDEX_STATS_NAME)) - { - dict_table_close(index_stats, false, thd, mdl_index); - goto release_and_exit; - } - - trx_t *trx= trx_create(); - trx->mysql_thd= thd; - trx_start_internal(trx); - dberr_t ret= trx->read_only - ? DB_READ_ONLY - : lock_table_for_trx(table_stats, trx, LOCK_X); - if (ret == DB_SUCCESS) - ret= lock_table_for_trx(index_stats, trx, LOCK_X); - - row_mysql_lock_data_dictionary(trx); - - if (ret == DB_SUCCESS) - ret= dict_stats_save_index_stat(index, now, "n_page_split", - index->stat_defrag_n_page_split, nullptr, - "Number of new page splits on leaves" - " since last defragmentation.", trx); - - if (ret == DB_SUCCESS) - ret= dict_stats_save_index_stat(index, now, "n_leaf_pages_defrag", - n_leaf_pages, nullptr, - "Number of leaf pages when" - " this stat is saved to disk", trx); - - if (ret == DB_SUCCESS) - ret= dict_stats_save_index_stat(index, now, "n_leaf_pages_reserved", - n_leaf_reserved, nullptr, - "Number of pages reserved for" - " this index leaves" - " when this stat is saved to disk", trx); - - if (ret == DB_SUCCESS) - trx->commit(); - else - trx->rollback(); - - if (table_stats) - dict_table_close(table_stats, true, thd, mdl_table); - if (index_stats) - dict_table_close(index_stats, true, thd, mdl_index); - row_mysql_unlock_data_dictionary(trx); - trx->free(); - - return ret; -} diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 8db2ff60162..5545727b015 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -2086,13 +2086,6 @@ dict_index_add_to_cache( new_index->stat_index_size = 1; new_index->stat_n_leaf_pages = 1; - new_index->stat_defrag_n_pages_freed = 0; - new_index->stat_defrag_n_page_split = 0; - - new_index->stat_defrag_sample_next_slot = 0; - memset(&new_index->stat_defrag_data_size_sample, - 0x0, sizeof(ulint) * STAT_DEFRAG_DATA_SIZE_N_SAMPLE); - /* Add the new index as the last index for the table */ UT_LIST_ADD_LAST(new_index->table->indexes, new_index); diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 04b1ec88ac3..ea623122686 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -675,9 +675,6 @@ dict_stats_table_clone_create( heap, idx->n_uniq * sizeof(idx->stat_n_non_null_key_vals[0])); ut_d(idx->magic_n = DICT_INDEX_MAGIC_N); - - idx->stat_defrag_n_page_split = 0; - idx->stat_defrag_n_pages_freed = 0; } ut_d(t->magic_n = DICT_TABLE_MAGIC_N); @@ -701,13 +698,7 @@ dict_stats_table_clone_free( /*********************************************************************//** Write all zeros (or 1 where it makes sense) into an index statistics members. The resulting stats correspond to an empty index. */ -static -void -dict_stats_empty_index( -/*===================*/ - dict_index_t* index, /*!< in/out: index */ - bool empty_defrag_stats) - /*!< in: whether to empty defrag stats */ +static void dict_stats_empty_index(dict_index_t *index) { ut_ad(!(index->type & DICT_FTS)); ut_ad(index->table->stats_mutex_is_owner()); @@ -722,23 +713,12 @@ dict_stats_empty_index( index->stat_index_size = 1; index->stat_n_leaf_pages = 1; - - if (empty_defrag_stats) { - dict_stats_empty_defrag_stats(index); - dict_stats_empty_defrag_summary(index); - } } /*********************************************************************//** Write all zeros (or 1 where it makes sense) into a table and its indexes' statistics members. The resulting stats correspond to an empty table. */ -static -void -dict_stats_empty_table( -/*===================*/ - dict_table_t* table, /*!< in/out: table */ - bool empty_defrag_stats) - /*!< in: whether to empty defrag stats */ +static void dict_stats_empty_table(dict_table_t *table) { /* Initialize table/index level stats is now protected by table level lock_mutex.*/ @@ -762,7 +742,7 @@ dict_stats_empty_table( continue; } - dict_stats_empty_index(index, empty_defrag_stats); + dict_stats_empty_index(index); } table->stat_initialized = TRUE; @@ -888,7 +868,7 @@ dict_stats_copy( if (dst_idx->type & DICT_FTS) { continue; } - dict_stats_empty_index(dst_idx, true); + dict_stats_empty_index(dst_idx); } else { continue; } @@ -906,7 +886,7 @@ dict_stats_copy( } if (!INDEX_EQ(src_idx, dst_idx)) { - dict_stats_empty_index(dst_idx, true); + dict_stats_empty_index(dst_idx); continue; } @@ -917,7 +897,7 @@ dict_stats_copy( /* Since src is smaller some elements in dst will remain untouched by the following memmove(), thus we init all of them here. */ - dict_stats_empty_index(dst_idx, true); + dict_stats_empty_index(dst_idx); } else { n_copy_el = dst_idx->n_uniq; } @@ -937,13 +917,6 @@ dict_stats_copy( dst_idx->stat_index_size = src_idx->stat_index_size; dst_idx->stat_n_leaf_pages = src_idx->stat_n_leaf_pages; - - dst_idx->stat_defrag_modified_counter = - src_idx->stat_defrag_modified_counter; - dst_idx->stat_defrag_n_pages_freed = - src_idx->stat_defrag_n_pages_freed; - dst_idx->stat_defrag_n_page_split = - src_idx->stat_defrag_n_page_split; } dst->stat_initialized = TRUE; @@ -966,9 +939,6 @@ dict_index_t::stat_n_sample_sizes[] dict_index_t::stat_n_non_null_key_vals[] dict_index_t::stat_index_size dict_index_t::stat_n_leaf_pages -dict_index_t::stat_defrag_modified_counter -dict_index_t::stat_defrag_n_pages_freed -dict_index_t::stat_defrag_n_page_split The returned object should be freed with dict_stats_snapshot_free() when no longer needed. @param[in] table table whose stats to copy @@ -1426,8 +1396,6 @@ Calculates new estimates for index statistics. This function is relatively quick and is used to calculate transient statistics that are not saved on disk. This was the only way to calculate statistics before the Persistent Statistics feature was introduced. -This function doesn't update the defragmentation related stats. -Only persistent statistics supports defragmentation stats. @return error code @retval DB_SUCCESS_LOCKED_REC if the table under bulk insert operation */ static @@ -1448,7 +1416,7 @@ dict_stats_update_transient_for_index( various means, also via secondary indexes. */ dummy_empty: index->table->stats_mutex_lock(); - dict_stats_empty_index(index, false); + dict_stats_empty_index(index); index->table->stats_mutex_unlock(); return err; } else if (dict_index_is_online_ddl(index) || !index->is_committed() @@ -1545,7 +1513,7 @@ dict_stats_update_transient( if (!table->space) { /* Nothing to do. */ empty_table: - dict_stats_empty_table(table, true); + dict_stats_empty_table(table); return err; } else if (index == NULL) { /* Table definition is corrupt */ @@ -1564,7 +1532,7 @@ empty_table: || !index->is_readable() || err == DB_SUCCESS_LOCKED_REC) { index->table->stats_mutex_lock(); - dict_stats_empty_index(index, false); + dict_stats_empty_index(index); index->table->stats_mutex_unlock(); continue; } @@ -2972,19 +2940,19 @@ dict_stats_update_persistent( || (index->type | DICT_UNIQUE) != (DICT_CLUSTERED | DICT_UNIQUE)) { /* Table definition is corrupt */ - dict_stats_empty_table(table, true); + dict_stats_empty_table(table); return(DB_CORRUPTION); } table->stats_mutex_lock(); - dict_stats_empty_index(index, false); + dict_stats_empty_index(index); table->stats_mutex_unlock(); index_stats_t stats = dict_stats_analyze_index(index); if (stats.is_bulk_operation()) { - dict_stats_empty_table(table, false); + dict_stats_empty_table(table); return DB_SUCCESS_LOCKED_REC; } @@ -3015,7 +2983,7 @@ dict_stats_update_persistent( continue; } - dict_stats_empty_index(index, false); + dict_stats_empty_index(index); if (dict_stats_should_ignore_index(index)) { continue; @@ -3027,7 +2995,7 @@ dict_stats_update_persistent( if (stats.is_bulk_operation()) { table->stats_mutex_unlock(); - dict_stats_empty_table(table, false); + dict_stats_empty_table(table); return DB_SUCCESS_LOCKED_REC; } @@ -3155,25 +3123,21 @@ dict_stats_save_index_stat( /** Report an error if updating table statistics failed because .ibd file is missing, table decryption failed or table is corrupted. @param[in,out] table Table -@param[in] defragment true if statistics is for defragment @retval DB_DECRYPTION_FAILED if decryption of the table failed @retval DB_TABLESPACE_DELETED if .ibd file is missing @retval DB_CORRUPTION if table is marked as corrupted */ -dberr_t -dict_stats_report_error(dict_table_t* table, bool defragment) +static dberr_t dict_stats_report_error(dict_table_t* table) { dberr_t err; - const char* df = defragment ? " defragment" : ""; - if (!table->space) { - ib::warn() << "Cannot save" << df << " statistics for table " + ib::warn() << "Cannot save statistics for table " << table->name << " because the .ibd file is missing. " << TROUBLESHOOTING_MSG; err = DB_TABLESPACE_DELETED; } else { - ib::warn() << "Cannot save" << df << " statistics for table " + ib::warn() << "Cannot save statistics for table " << table->name << " because file " << table->space->chain.start->name @@ -3183,7 +3147,7 @@ dict_stats_report_error(dict_table_t* table, bool defragment) err = table->corrupted ? DB_CORRUPTION : DB_DECRYPTION_FAILED; } - dict_stats_empty_table(table, defragment); + dict_stats_empty_table(table); return err; } @@ -3668,16 +3632,6 @@ dict_stats_fetch_index_stats_step( == 0) { index->stat_n_leaf_pages = (ulint) stat_value; arg->stats_were_modified = true; - } else if (stat_name_len == 12 /* strlen("n_page_split") */ - && strncasecmp("n_page_split", stat_name, stat_name_len) - == 0) { - index->stat_defrag_n_page_split = (ulint) stat_value; - arg->stats_were_modified = true; - } else if (stat_name_len == 13 /* strlen("n_pages_freed") */ - && strncasecmp("n_pages_freed", stat_name, stat_name_len) - == 0) { - index->stat_defrag_n_pages_freed = (ulint) stat_value; - arg->stats_were_modified = true; } else if (stat_name_len > PFX_LEN /* e.g. stat_name=="n_diff_pfx01" */ && strncasecmp(PFX, stat_name, PFX_LEN) == 0) { @@ -3785,7 +3739,7 @@ dict_stats_fetch_from_ps( the persistent storage contains incomplete stats (e.g. missing stats for some index) then we would end up with (partially) uninitialized stats. */ - dict_stats_empty_table(table, true); + dict_stats_empty_table(table); THD* thd = current_thd; MDL_ticket *mdl_table = nullptr, *mdl_index = nullptr; @@ -3919,22 +3873,6 @@ release_and_exit: } /*********************************************************************//** -Clear defragmentation stats modified counter for all indices in table. */ -static -void -dict_stats_empty_defrag_modified_counter( - dict_table_t* table) /*!< in: table */ -{ - dict_index_t* index; - ut_a(table); - for (index = dict_table_get_first_index(table); - index != NULL; - index = dict_table_get_next_index(index)) { - index->stat_defrag_modified_counter = 0; - } -} - -/*********************************************************************//** Fetches or calculates new estimates for index statistics. */ void dict_stats_update_for_index( @@ -4010,13 +3948,13 @@ dict_stats_update( /* If we have set a high innodb_force_recovery level, do not calculate statistics, as a badly corrupted index can cause a crash in it. */ - dict_stats_empty_table(table, false); + dict_stats_empty_table(table); return(DB_SUCCESS); } if (trx_id_t bulk_trx_id = table->bulk_trx_id) { if (trx_sys.find(nullptr, bulk_trx_id, false)) { - dict_stats_empty_table(table, false); + dict_stats_empty_table(table); return DB_SUCCESS_LOCKED_REC; } } @@ -4078,8 +4016,7 @@ dict_stats_update( goto transient; case DICT_STATS_EMPTY_TABLE: - - dict_stats_empty_table(table, true); + dict_stats_empty_table(table); /* If table is using persistent stats, then save the stats on disk */ @@ -4140,7 +4077,6 @@ dict_stats_update( t->stats_last_recalc = table->stats_last_recalc; t->stat_modified_counter = 0; - dict_stats_empty_defrag_modified_counter(t); switch (err) { case DB_SUCCESS: diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index a66aac226a3..8463c20eace 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -27,7 +27,6 @@ Created Apr 25, 2012 Vasil Dimov #include "dict0dict.h" #include "dict0stats.h" #include "dict0stats_bg.h" -#include "dict0defrag_bg.h" #include "row0mysql.h" #include "srv0start.h" #include "fil0fil.h" @@ -77,7 +76,6 @@ static void dict_stats_recalc_pool_deinit() ut_ad(!srv_read_only_mode); recalc_pool.clear(); - defrag_pool.clear(); /* recalc_pool may still have its buffer allocated. It will free it when its destructor is called. @@ -87,9 +85,7 @@ static void dict_stats_recalc_pool_deinit() to empty_pool object, which will free it when leaving this function: */ recalc_pool_t recalc_empty_pool; - defrag_pool_t defrag_empty_pool; recalc_pool.swap(recalc_empty_pool); - defrag_pool.swap(defrag_empty_pool); } /*****************************************************************//** @@ -255,7 +251,6 @@ void dict_stats_init() ut_ad(!srv_read_only_mode); mysql_mutex_init(recalc_pool_mutex_key, &recalc_pool_mutex, nullptr); pthread_cond_init(&recalc_pool_cond, nullptr); - dict_defrag_pool_init(); stats_initialised= true; } @@ -272,7 +267,6 @@ void dict_stats_deinit() stats_initialised = false; dict_stats_recalc_pool_deinit(); - dict_defrag_pool_deinit(); mysql_mutex_destroy(&recalc_pool_mutex); pthread_cond_destroy(&recalc_pool_cond); @@ -380,7 +374,6 @@ static void dict_stats_func(void*) THD *thd= innobase_create_background_thd("InnoDB statistics"); set_current_thd(thd); while (dict_stats_process_entry_from_recalc_pool(thd)) {} - dict_defrag_process_entries_from_defrag_pool(thd); set_current_thd(nullptr); destroy_background_thd(thd); } diff --git a/storage/innobase/dict/drop.cc b/storage/innobase/dict/drop.cc index abf08f225c5..d92c2e12409 100644 --- a/storage/innobase/dict/drop.cc +++ b/storage/innobase/dict/drop.cc @@ -66,8 +66,6 @@ before transaction commit and must be rolled back explicitly are as follows: #include "dict0stats.h" #include "dict0stats_bg.h" -#include "dict0defrag_bg.h" -#include "btr0defragment.h" #include "ibuf0ibuf.h" #include "lock0lock.h" @@ -264,9 +262,6 @@ void trx_t::commit(std::vector<pfs_os_file_t> &deleted) { dict_table_t *table= p.first; dict_stats_recalc_pool_del(table->id, true); - dict_stats_defrag_pool_del(table, nullptr); - if (btr_defragment_active) - btr_defragment_remove_table(table); const fil_space_t *space= table->space; ut_ad(!p.second.is_aux_table() || purge_sys.must_wait_FTS()); dict_sys.remove(table); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 461b222d3cf..6345435af97 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -77,7 +77,6 @@ this program; if not, write to the Free Software Foundation, Inc., #include "buf0lru.h" #include "dict0boot.h" #include "dict0load.h" -#include "btr0defragment.h" #include "dict0crea.h" #include "dict0stats.h" #include "dict0stats_bg.h" @@ -996,12 +995,6 @@ static SHOW_VAR innodb_status_variables[]= { {"have_snappy", &(provider_service_snappy->is_loaded), SHOW_BOOL}, {"have_punch_hole", &innodb_have_punch_hole, SHOW_BOOL}, - /* Defragmentation */ - {"defragment_compression_failures", - &export_vars.innodb_defragment_compression_failures, SHOW_SIZE_T}, - {"defragment_failures", &export_vars.innodb_defragment_failures,SHOW_SIZE_T}, - {"defragment_count", &export_vars.innodb_defragment_count, SHOW_SIZE_T}, - {"instant_alter_column", &export_vars.innodb_instant_alter_column, SHOW_ULONG}, @@ -15016,58 +15009,6 @@ ha_innobase::analyze(THD*, HA_CHECK_OPT*) return(HA_ADMIN_OK); } -/*****************************************************************//** -Defragment table. -@return error number */ -inline int ha_innobase::defragment_table() -{ - for (dict_index_t *index= dict_table_get_first_index(m_prebuilt->table); - index; index= dict_table_get_next_index(index)) - { - if (!index->is_btree()) - continue; - - if (btr_defragment_find_index(index)) - { - // We borrow this error code. When the same index is already in - // the defragmentation queue, issuing another defragmentation - // only introduces overhead. We return an error here to let the - // user know this is not necessary. Note that this will fail a - // query that's trying to defragment a full table if one of the - // indicies in that table is already in defragmentation. We - // choose this behavior so user is aware of this rather than - // silently defragment other indicies of that table. - return ER_SP_ALREADY_EXISTS; - } - - btr_pcur_t pcur; - - mtr_t mtr; - mtr.start(); - if (dberr_t err= pcur.open_leaf(true, index, BTR_SEARCH_LEAF, &mtr)) - { - mtr.commit(); - return convert_error_code_to_mysql(err, 0, m_user_thd); - } - else if (btr_pcur_get_block(&pcur)->page.id().page_no() == index->page) - { - mtr.commit(); - continue; - } - - btr_pcur_move_to_next(&pcur, &mtr); - btr_pcur_store_position(&pcur, &mtr); - mtr.commit(); - ut_ad(pcur.index() == index); - const bool interrupted= btr_defragment_add_index(&pcur, m_user_thd); - ut_free(pcur.old_rec_buf); - if (interrupted) - return ER_QUERY_INTERRUPTED; - } - - return 0; -} - /**********************************************************************//** This is mapped to "ALTER TABLE tablename ENGINE=InnoDB", which rebuilds the table in MySQL. */ @@ -15089,25 +15030,6 @@ ha_innobase::optimize( calls to OPTIMIZE, which is undesirable. */ bool try_alter = true; - if (!m_prebuilt->table->is_temporary() - && m_prebuilt->table->is_readable() - && srv_defragment) { - int err = defragment_table(); - - if (err == 0) { - try_alter = false; - } else { - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - uint(err), - "InnoDB: Cannot defragment table %s: returned error code %d\n", - m_prebuilt->table->name.m_name, err); - - if(err == ER_SP_ALREADY_EXISTS) { - try_alter = false; - } - } - } - if (innodb_optimize_fulltext_only) { if (m_prebuilt->table->fts && m_prebuilt->table->fts->cache && m_prebuilt->table->space) { @@ -18077,15 +17999,6 @@ innodb_reset_all_monitor_update( TRUE); } -static -void -innodb_defragment_frequency_update(THD*, st_mysql_sys_var*, void*, - const void* save) -{ - srv_defragment_frequency = (*static_cast<const uint*>(save)); - srv_defragment_interval = 1000000000ULL / srv_defragment_frequency; -} - static inline char *my_strtok_r(char *str, const char *delim, char **saveptr) { #if defined _WIN32 @@ -19111,60 +19024,6 @@ static MYSQL_SYSVAR_BOOL(buffer_pool_load_at_startup, srv_buffer_pool_load_at_st "Load the buffer pool from a file named @@innodb_buffer_pool_filename", NULL, NULL, TRUE); -static MYSQL_SYSVAR_BOOL(defragment, srv_defragment, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_DEPRECATED, - "Enable/disable InnoDB defragmentation (default FALSE). When set to FALSE, all existing " - "defragmentation will be paused. And new defragmentation command will fail." - "Paused defragmentation commands will resume when this variable is set to " - "true again.", - NULL, NULL, FALSE); - -static MYSQL_SYSVAR_UINT(defragment_n_pages, srv_defragment_n_pages, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_DEPRECATED, - "Number of pages considered at once when merging multiple pages to " - "defragment", - NULL, NULL, 7, 2, 32, 0); - -static MYSQL_SYSVAR_UINT(defragment_stats_accuracy, - srv_defragment_stats_accuracy, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_DEPRECATED, - "How many defragment stats changes there are before the stats " - "are written to persistent storage. Set to 0 meaning disable " - "defragment stats tracking.", - NULL, NULL, 0, 0, ~0U, 0); - -static MYSQL_SYSVAR_UINT(defragment_fill_factor_n_recs, - srv_defragment_fill_factor_n_recs, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_DEPRECATED, - "How many records of space defragmentation should leave on the page. " - "This variable, together with innodb_defragment_fill_factor, is introduced " - "so defragmentation won't pack the page too full and cause page split on " - "the next insert on every page. The variable indicating more defragmentation" - " gain is the one effective.", - NULL, NULL, 20, 1, 100, 0); - -static MYSQL_SYSVAR_DOUBLE(defragment_fill_factor, srv_defragment_fill_factor, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_DEPRECATED, - "A number between [0.7, 1] that tells defragmentation how full it should " - "fill a page. Default is 0.9. Number below 0.7 won't make much sense." - "This variable, together with innodb_defragment_fill_factor_n_recs, is " - "introduced so defragmentation won't pack the page too full and cause " - "page split on the next insert on every page. The variable indicating more " - "defragmentation gain is the one effective.", - NULL, NULL, 0.9, 0.7, 1, 0); - -static MYSQL_SYSVAR_UINT(defragment_frequency, srv_defragment_frequency, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_DEPRECATED, - "Do not defragment a single index more than this number of time per second." - "This controls the number of time defragmentation thread can request X_LOCK " - "on an index. Defragmentation thread will check whether " - "1/defragment_frequency (s) has passed since it worked on this index last " - "time, and put the index back to the queue if not enough time has passed. " - "The actual frequency can only be lower than this given number.", - NULL, innodb_defragment_frequency_update, - SRV_DEFRAGMENT_FREQUENCY_DEFAULT, 1, 1000, 0); - - static MYSQL_SYSVAR_ULONG(lru_scan_depth, srv_LRU_scan_depth, PLUGIN_VAR_RQCMDARG, "How deep to scan LRU to keep it clean", @@ -19739,12 +19598,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(buffer_pool_load_pages_abort), #endif /* UNIV_DEBUG */ MYSQL_SYSVAR(buffer_pool_load_at_startup), - MYSQL_SYSVAR(defragment), - MYSQL_SYSVAR(defragment_n_pages), - MYSQL_SYSVAR(defragment_stats_accuracy), - MYSQL_SYSVAR(defragment_fill_factor), - MYSQL_SYSVAR(defragment_fill_factor_n_recs), - MYSQL_SYSVAR(defragment_frequency), MYSQL_SYSVAR(lru_scan_depth), MYSQL_SYSVAR(lru_flush_size), MYSQL_SYSVAR(flush_neighbors), diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 60b56b4a22f..aedc7e097c4 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -207,7 +207,6 @@ public: int delete_table(const char *name) override; int rename_table(const char* from, const char* to) override; - inline int defragment_table(); int check(THD* thd, HA_CHECK_OPT* check_opt) override; inline void reload_statistics(); diff --git a/storage/innobase/include/btr0defragment.h b/storage/innobase/include/btr0defragment.h deleted file mode 100644 index 0523829bdc3..00000000000 --- a/storage/innobase/include/btr0defragment.h +++ /dev/null @@ -1,65 +0,0 @@ -/***************************************************************************** - -Copyright (C) 2013, 2014 Facebook, Inc. All Rights Reserved. -Copyright (C) 2014, 2021, MariaDB Corporation. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -#ifndef btr0defragment_h -#define btr0defragment_h - -#include "btr0pcur.h" - -/* Max number of pages to consider at once during defragmentation. */ -#define BTR_DEFRAGMENT_MAX_N_PAGES 32 - -/** stats in btr_defragment */ -extern Atomic_counter<ulint> btr_defragment_compression_failures; -extern Atomic_counter<ulint> btr_defragment_failures; -extern Atomic_counter<ulint> btr_defragment_count; - -/******************************************************************//** -Initialize defragmentation. */ -void -btr_defragment_init(void); -/******************************************************************//** -Shutdown defragmentation. */ -void -btr_defragment_shutdown(); -/******************************************************************//** -Check whether the given index is in btr_defragment_wq. */ -bool -btr_defragment_find_index( - dict_index_t* index); /*!< Index to find. */ -/** Defragment an index. -@param pcur persistent cursor -@param thd current session, for checking thd_killed() -@return whether the operation was interrupted */ -bool btr_defragment_add_index(btr_pcur_t *pcur, THD *thd); -/******************************************************************//** -When table is dropped, this function is called to mark a table as removed in -btr_efragment_wq. The difference between this function and the remove_index -function is this will not NULL the event. */ -void -btr_defragment_remove_table( - dict_table_t* table); /*!< Index to be removed. */ -/*********************************************************************//** -Check whether we should save defragmentation statistics to persistent storage.*/ -void btr_defragment_save_defrag_stats_if_needed(dict_index_t *index); - -/* Stop defragmentation.*/ -void btr_defragment_end(); -extern bool btr_defragment_active; -#endif diff --git a/storage/innobase/include/dict0defrag_bg.h b/storage/innobase/include/dict0defrag_bg.h deleted file mode 100644 index 679484ad64e..00000000000 --- a/storage/innobase/include/dict0defrag_bg.h +++ /dev/null @@ -1,101 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2016, 2021, MariaDB Corporation. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/**************************************************//** -@file include/dict0defrag_bg.h -Code used for background table and index -defragmentation - -Created 25/08/2016 Jan Lindström -*******************************************************/ - -#ifndef dict0defrag_bg_h -#define dict0defrag_bg_h - -#include "dict0types.h" - -/** Indices whose defrag stats need to be saved to persistent storage.*/ -struct defrag_pool_item_t { - table_id_t table_id; - index_id_t index_id; -}; - -/** Allocator type, used by std::vector */ -typedef ut_allocator<defrag_pool_item_t> - defrag_pool_allocator_t; - -/** The multitude of tables to be defragmented- an STL vector */ -typedef std::vector<defrag_pool_item_t, defrag_pool_allocator_t> - defrag_pool_t; - -/** Pool where we store information on which tables are to be processed -by background defragmentation. */ -extern defrag_pool_t defrag_pool; - -/*****************************************************************//** -Initialize the defrag pool, called once during thread initialization. */ -void -dict_defrag_pool_init(void); -/*========================*/ - -/*****************************************************************//** -Free the resources occupied by the defrag pool, called once during -thread de-initialization. */ -void -dict_defrag_pool_deinit(void); -/*==========================*/ - -/*****************************************************************//** -Add an index in a table to the defrag pool, which is processed by the -background stats gathering thread. Only the table id and index id are -added to the list, so the table can be closed after being enqueued and -it will be opened when needed. If the table or index does not exist later -(has been DROPped), then it will be removed from the pool and skipped. */ -void -dict_stats_defrag_pool_add( -/*=======================*/ - const dict_index_t* index); /*!< in: table to add */ - -/*****************************************************************//** -Delete a given index from the auto defrag pool. */ -void -dict_stats_defrag_pool_del( -/*=======================*/ - const dict_table_t* table, /*!<in: if given, remove - all entries for the table */ - const dict_index_t* index); /*!< in: index to remove */ - -/** -Get the first index that has been added for updating persistent defrag -stats and eventually save its stats. */ -void dict_defrag_process_entries_from_defrag_pool(THD *thd); - -/*********************************************************************//** -Save defragmentation result. -@return DB_SUCCESS or error code */ -dberr_t dict_stats_save_defrag_summary(dict_index_t *index, THD *thd) - MY_ATTRIBUTE((nonnull, warn_unused_result)); - -/*********************************************************************//** -Save defragmentation stats for a given index. -@return DB_SUCCESS or error code */ -dberr_t -dict_stats_save_defrag_stats( -/*============================*/ - dict_index_t* index); /*!< in: index */ -#endif /* dict0defrag_bg_h */ diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index bbbda57b05d..c1927bec916 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -945,10 +945,6 @@ struct zip_pad_info_t { rounds */ }; -/** Number of samples of data size kept when page compression fails for -a certain index.*/ -#define STAT_DEFRAG_DATA_SIZE_N_SAMPLE 10 - /** "GEN_CLUST_INDEX" is the name reserved for InnoDB default system clustered index when there is no primary key. */ const char innobase_index_reserve_name[] = "GEN_CLUST_INDEX"; @@ -1115,23 +1111,6 @@ struct dict_index_t { /*!< has persistent statistics error printed for this index ? */ /* @} */ - /** Statistics for defragmentation, these numbers are estimations and - could be very inaccurate at certain times, e.g. right after restart, - during defragmentation, etc. */ - /* @{ */ - ulint stat_defrag_modified_counter; - ulint stat_defrag_n_pages_freed; - /* number of pages freed by defragmentation. */ - ulint stat_defrag_n_page_split; - /* number of page splits since last full index - defragmentation. */ - ulint stat_defrag_data_size_sample[STAT_DEFRAG_DATA_SIZE_N_SAMPLE]; - /* data size when compression failure happened - the most recent 10 times. */ - ulint stat_defrag_sample_next_slot; - /* in which slot the next sample should be - saved. */ - /* @} */ private: /** R-tree split sequence number */ Atomic_relaxed<node_seq_t> rtr_ssn; @@ -2623,19 +2602,6 @@ dict_col_get_spatial_status( return(spatial_status); } -/** Clear defragmentation summary. */ -inline void dict_stats_empty_defrag_summary(dict_index_t* index) -{ - index->stat_defrag_n_pages_freed = 0; -} - -/** Clear defragmentation related index stats. */ -inline void dict_stats_empty_defrag_stats(dict_index_t* index) -{ - index->stat_defrag_modified_counter = 0; - index->stat_defrag_n_page_split = 0; -} - #include "dict0mem.inl" #endif /* dict0mem_h */ diff --git a/storage/innobase/include/dict0stats.h b/storage/innobase/include/dict0stats.h index 0dc1b984577..f7c13147b16 100644 --- a/storage/innobase/include/dict0stats.h +++ b/storage/innobase/include/dict0stats.h @@ -218,17 +218,6 @@ dict_stats_save_index_stat( trx_t* trx) MY_ATTRIBUTE((nonnull(1, 3, 6, 7))); -/** Report an error if updating table statistics failed because -.ibd file is missing, table decryption failed or table is corrupted. -@param[in,out] table Table -@param[in] defragment true if statistics is for defragment -@retval DB_DECRYPTION_FAILED if decryption of the table failed -@retval DB_TABLESPACE_DELETED if .ibd file is missing -@retval DB_CORRUPTION if table is marked as corrupted */ -dberr_t -dict_stats_report_error(dict_table_t* table, bool defragment = false) - MY_ATTRIBUTE((nonnull, warn_unused_result)); - #include "dict0stats.inl" #ifdef UNIV_ENABLE_UNIT_TEST_DICT_STATS diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index 16acd031177..4b85f5db72d 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -185,13 +185,6 @@ lock_update_split_left( void lock_update_merge_left(const buf_block_t& left, const rec_t *orig_pred, const page_id_t right); -/** Update the locks when a page is split and merged to two pages, -in defragmentation. */ -void lock_update_split_and_merge( - const buf_block_t* left_block, /*!< in: left page to which merged */ - const rec_t* orig_pred, /*!< in: original predecessor of - supremum on the left page before merge*/ - const buf_block_t* right_block);/*!< in: right page from which merged */ /*************************************************************//** Resets the original locks on heir and replaces them with gap type locks inherited from rec. */ diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index b4437bb57f3..6f0acbde975 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -260,16 +260,6 @@ extern ulong srv_read_ahead_threshold; extern uint srv_n_read_io_threads; extern uint srv_n_write_io_threads; -/* Defragmentation, Origianlly facebook default value is 100, but it's too high */ -#define SRV_DEFRAGMENT_FREQUENCY_DEFAULT 40 -extern my_bool srv_defragment; -extern uint srv_defragment_n_pages; -extern uint srv_defragment_stats_accuracy; -extern uint srv_defragment_fill_factor_n_recs; -extern double srv_defragment_fill_factor; -extern uint srv_defragment_frequency; -extern ulonglong srv_defragment_interval; - /* Number of IO operations per second the server can do */ extern ulong srv_io_capacity; @@ -644,14 +634,6 @@ struct export_var_t{ /** Number of undo tablespace truncation operations */ ulong innodb_undo_truncations; - ulint innodb_defragment_compression_failures; /*!< Number of - defragment re-compression - failures */ - - ulint innodb_defragment_failures; /*!< Number of defragment - failures*/ - ulint innodb_defragment_count; /*!< Number of defragment - operations*/ /** Number of instant ALTER TABLE operations that affect columns */ ulong innodb_instant_alter_column; diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index bbfed2490e9..d0f5e9ad1b4 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -589,8 +589,7 @@ public: So we take more expensive approach: get trx through current_thd()->ha_data. Some threads don't have trx attached to THD, and at least server - initialisation thread, fts_optimize_thread, srv_master_thread, - dict_stats_thread, srv_monitor_thread, btr_defragment_thread don't even + initialisation thread doesn't even have THD at all. For such cases we allocate pins only for duration of search and free them immediately. diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 3c7c3d348af..b56098f5e9d 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -6485,45 +6485,3 @@ void lock_sys_t::deadlock_check() if (acquired) wr_unlock(); } - -/** Update the locks when a page is split and merged to two pages, -in defragmentation. */ -void lock_update_split_and_merge( - const buf_block_t* left_block, /*!< in: left page to which merged */ - const rec_t* orig_pred, /*!< in: original predecessor of - supremum on the left page before merge*/ - const buf_block_t* right_block) /*!< in: right page from which merged */ -{ - ut_ad(page_is_leaf(left_block->page.frame)); - ut_ad(page_is_leaf(right_block->page.frame)); - ut_ad(page_align(orig_pred) == left_block->page.frame); - - const page_id_t l{left_block->page.id()}; - const page_id_t r{right_block->page.id()}; - const rec_t *left_next_rec= page_rec_get_next_const(orig_pred); - if (UNIV_UNLIKELY(!left_next_rec)) - { - ut_ad("corrupted page" == 0); - return; - } - ut_ad(!page_rec_is_metadata(left_next_rec)); - - /* This would likely be too large for a memory transaction. */ - LockMultiGuard g{lock_sys.rec_hash, l, r}; - - /* Inherit the locks on the supremum of the left page to the - first record which was moved from the right page */ - lock_rec_inherit_to_gap(g.cell1(), l, g.cell1(), l, left_block->page.frame, - page_rec_get_heap_no(left_next_rec), - PAGE_HEAP_NO_SUPREMUM); - - /* Reset the locks on the supremum of the left page, - releasing waiting transactions */ - lock_rec_reset_and_release_wait(g.cell1(), l, PAGE_HEAP_NO_SUPREMUM); - - /* Inherit the locks to the supremum of the left page from the - successor of the infimum on the right page */ - lock_rec_inherit_to_gap(g.cell1(), l, g.cell2(), r, left_block->page.frame, - PAGE_HEAP_NO_SUPREMUM, - lock_get_min_heap_no(right_block)); -} diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 38175934d6f..d763ef10734 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -43,7 +43,6 @@ Created 12/9/1995 Heikki Tuuri #include "log0recv.h" #include "fil0fil.h" #include "dict0stats_bg.h" -#include "btr0defragment.h" #include "srv0srv.h" #include "srv0start.h" #include "trx0sys.h" @@ -1090,7 +1089,6 @@ ATTRIBUTE_COLD void logs_empty_and_mark_files_at_shutdown() /* Wait for the end of the buffer resize task.*/ buf_resize_shutdown(); dict_stats_shutdown(); - btr_defragment_shutdown(); srv_shutdown_state = SRV_SHUTDOWN_CLEANUP; diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 9f14d100a8a..a86a2337813 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -60,7 +60,6 @@ Created 10/8/1995 Heikki Tuuri #include "srv0start.h" #include "trx0i_s.h" #include "trx0purge.h" -#include "btr0defragment.h" #include "ut0mem.h" #include "fil0fil.h" #include "fil0crypt.h" @@ -318,21 +317,6 @@ uint srv_spin_wait_delay; /** Number of initialized rollback segments for persistent undo log */ ulong srv_available_undo_logs; -/* Defragmentation */ -my_bool srv_defragment; -/** innodb_defragment_n_pages */ -uint srv_defragment_n_pages; -uint srv_defragment_stats_accuracy; -/** innodb_defragment_fill_factor_n_recs */ -uint srv_defragment_fill_factor_n_recs; -/** innodb_defragment_fill_factor */ -double srv_defragment_fill_factor; -/** innodb_defragment_frequency */ -uint srv_defragment_frequency; -/** derived from innodb_defragment_frequency; -@see innodb_defragment_frequency_update() */ -ulonglong srv_defragment_interval; - /** Current mode of operation */ enum srv_operation_mode srv_operation; @@ -959,11 +943,6 @@ srv_export_innodb_status(void) export_vars.innodb_n_temp_blocks_decrypted = srv_stats.n_temp_blocks_decrypted; - export_vars.innodb_defragment_compression_failures = - btr_defragment_compression_failures; - export_vars.innodb_defragment_failures = btr_defragment_failures; - export_vars.innodb_defragment_count = btr_defragment_count; - export_vars.innodb_onlineddl_rowlog_rows = onlineddl_rowlog_rows; export_vars.innodb_onlineddl_rowlog_pct_used = onlineddl_rowlog_pct_used; export_vars.innodb_onlineddl_pct_progress = onlineddl_pct_progress; diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 33545f42d05..12643dd1768 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -71,7 +71,6 @@ Created 2/16/1996 Heikki Tuuri #include "rem0rec.h" #include "srv0start.h" #include "srv0srv.h" -#include "btr0defragment.h" #include "mysql/service_wsrep.h" /* wsrep_recovery */ #include "trx0rseg.h" #include "buf0flu.h" @@ -1913,9 +1912,6 @@ skip_monitors: fil_crypt_threads_cond. */ fil_crypt_threads_init(); - /* Initialize online defragmentation. */ - btr_defragment_init(); - srv_started_redo = true; } @@ -2012,7 +2008,6 @@ void innodb_shutdown() fts_optimize_shutdown(); dict_stats_shutdown(); */ fil_crypt_threads_cleanup(); - btr_defragment_shutdown(); } /* This must be disabled before closing the buffer pool diff --git a/storage/rocksdb/mysql-test/rocksdb_stress/t/load_generator.py b/storage/rocksdb/mysql-test/rocksdb_stress/t/load_generator.py index 91dd9e90df8..eef50010d8c 100644 --- a/storage/rocksdb/mysql-test/rocksdb_stress/t/load_generator.py +++ b/storage/rocksdb/mysql-test/rocksdb_stress/t/load_generator.py @@ -230,14 +230,14 @@ class WorkerThread(threading.Thread): return self.con is None def get_isolation_level(self): - execute(self.cur, "SELECT @@SESSION.tx_isolation") + execute(self.cur, "SELECT @@SESSION.transaction_isolation") if self.cur.rowcount != 1: - raise TestError("Unable to retrieve tx_isolation") + raise TestError("Unable to retrieve transaction_isolation") return self.cur.fetchone()[0] def set_isolation_level(self, isolation_level, persist = False): if isolation_level is not None: - execute(self.cur, "SET @@SESSION.tx_isolation = '%s'" % isolation_level) + execute(self.cur, "SET @@SESSION.transaction_isolation = '%s'" % isolation_level) if self.cur.rowcount != 0: raise TestError("Unable to set the isolation level to %s") diff --git a/storage/spider/mysql-test/spider/r/error_row_number.result b/storage/spider/mysql-test/spider/r/error_row_number.result index cc2b54878a0..ad095fe8ebd 100644 --- a/storage/spider/mysql-test/spider/r/error_row_number.result +++ b/storage/spider/mysql-test/spider/r/error_row_number.result @@ -29,7 +29,7 @@ ERROR 23000: Duplicate entry '13' for key 'PRIMARY' get diagnostics condition 1 @n = row_number; select @n; @n -0 +1 drop table spd; connection child2_1; drop database auto_test_remote; diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index 583299515cb..46dca8221b2 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -183,11 +183,6 @@ typedef st_spider_result SPIDER_RESULT; #define SPIDER_SQL_TYPE_TMP_SQL (1 << 5) #define SPIDER_SQL_TYPE_DROP_TMP_TABLE_SQL (1 << 6) #define SPIDER_SQL_TYPE_OTHER_SQL (1 << 7) -#define SPIDER_SQL_TYPE_SELECT_HS (1 << 9) -#define SPIDER_SQL_TYPE_INSERT_HS (1 << 10) -#define SPIDER_SQL_TYPE_UPDATE_HS (1 << 11) -#define SPIDER_SQL_TYPE_DELETE_HS (1 << 12) -#define SPIDER_SQL_TYPE_OTHER_HS (1 << 13) enum spider_bulk_upd_start { SPD_BU_NOT_START, diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index 555ab33d777..90b8ededd6c 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -12272,23 +12272,14 @@ int spider_mbase_handler::append_from( DBUG_RETURN(0); } -int spider_mbase_handler::append_flush_tables_part( - ulong sql_type, - int link_idx, - bool lock -) { +int spider_mbase_handler::append_flush_tables_part(int link_idx, bool lock) +{ int error_num; spider_string *str; DBUG_ENTER("spider_mbase_handler::append_flush_tables_part"); DBUG_PRINT("info",("spider this=%p", this)); - switch (sql_type) - { - case SPIDER_SQL_TYPE_OTHER_SQL: - str = &spider->result_list.sqls[link_idx]; - break; - default: - DBUG_RETURN(0); - } + + str= &spider->result_list.sqls[link_idx]; error_num = append_flush_tables(str, link_idx, lock); DBUG_RETURN(error_num); } @@ -12316,22 +12307,14 @@ int spider_mbase_handler::append_flush_tables( DBUG_RETURN(0); } -int spider_mbase_handler::append_optimize_table_part( - ulong sql_type, - int link_idx -) { +int spider_mbase_handler::append_optimize_table_part(int link_idx) +{ int error_num; spider_string *str; DBUG_ENTER("spider_mbase_handler::append_optimize_table_part"); DBUG_PRINT("info",("spider this=%p", this)); - switch (sql_type) - { - case SPIDER_SQL_TYPE_OTHER_SQL: - str = &spider->result_list.sqls[link_idx]; - break; - default: - DBUG_RETURN(0); - } + + str= &spider->result_list.sqls[link_idx]; error_num = append_optimize_table(str, link_idx); DBUG_RETURN(error_num); } @@ -12362,22 +12345,14 @@ int spider_mbase_handler::append_optimize_table( DBUG_RETURN(0); } -int spider_mbase_handler::append_analyze_table_part( - ulong sql_type, - int link_idx -) { +int spider_mbase_handler::append_analyze_table_part(int link_idx) +{ int error_num; spider_string *str; DBUG_ENTER("spider_mbase_handler::append_analyze_table_part"); DBUG_PRINT("info",("spider this=%p", this)); - switch (sql_type) - { - case SPIDER_SQL_TYPE_OTHER_SQL: - str = &spider->result_list.sqls[link_idx]; - break; - default: - DBUG_RETURN(0); - } + + str= &spider->result_list.sqls[link_idx]; error_num = append_analyze_table(str, link_idx); DBUG_RETURN(error_num); } @@ -12408,23 +12383,15 @@ int spider_mbase_handler::append_analyze_table( DBUG_RETURN(0); } -int spider_mbase_handler::append_repair_table_part( - ulong sql_type, - int link_idx, - HA_CHECK_OPT* check_opt -) { +int spider_mbase_handler::append_repair_table_part(int link_idx, + HA_CHECK_OPT *check_opt) +{ int error_num; spider_string *str; DBUG_ENTER("spider_mbase_handler::append_repair_table_part"); DBUG_PRINT("info",("spider this=%p", this)); - switch (sql_type) - { - case SPIDER_SQL_TYPE_OTHER_SQL: - str = &spider->result_list.sqls[link_idx]; - break; - default: - DBUG_RETURN(0); - } + + str= &spider->result_list.sqls[link_idx]; error_num = append_repair_table(str, link_idx, check_opt); DBUG_RETURN(error_num); } @@ -12474,23 +12441,15 @@ int spider_mbase_handler::append_repair_table( DBUG_RETURN(0); } -int spider_mbase_handler::append_check_table_part( - ulong sql_type, - int link_idx, - HA_CHECK_OPT* check_opt -) { +int spider_mbase_handler::append_check_table_part(int link_idx, + HA_CHECK_OPT *check_opt) +{ int error_num; spider_string *str; DBUG_ENTER("spider_mbase_handler::append_check_table_part"); DBUG_PRINT("info",("spider this=%p", this)); - switch (sql_type) - { - case SPIDER_SQL_TYPE_OTHER_SQL: - str = &spider->result_list.sqls[link_idx]; - break; - default: - DBUG_RETURN(0); - } + + str= &spider->result_list.sqls[link_idx]; error_num = append_check_table(str, link_idx, check_opt); DBUG_RETURN(error_num); } @@ -12539,22 +12498,14 @@ int spider_mbase_handler::append_check_table( DBUG_RETURN(0); } -int spider_mbase_handler::append_enable_keys_part( - ulong sql_type, - int link_idx -) { +int spider_mbase_handler::append_enable_keys_part(int link_idx) +{ int error_num; spider_string *str; DBUG_ENTER("spider_mbase_handler::append_enable_keys_part"); DBUG_PRINT("info",("spider this=%p", this)); - switch (sql_type) - { - case SPIDER_SQL_TYPE_OTHER_SQL: - str = &spider->result_list.sqls[link_idx]; - break; - default: - DBUG_RETURN(0); - } + + str= &spider->result_list.sqls[link_idx]; error_num = append_enable_keys(str, link_idx); DBUG_RETURN(error_num); } @@ -12580,22 +12531,14 @@ int spider_mbase_handler::append_enable_keys( DBUG_RETURN(0); } -int spider_mbase_handler::append_disable_keys_part( - ulong sql_type, - int link_idx -) { +int spider_mbase_handler::append_disable_keys_part(int link_idx) +{ int error_num; spider_string *str; DBUG_ENTER("spider_mbase_handler::append_disable_keys_part"); DBUG_PRINT("info",("spider this=%p", this)); - switch (sql_type) - { - case SPIDER_SQL_TYPE_OTHER_SQL: - str = &spider->result_list.sqls[link_idx]; - break; - default: - DBUG_RETURN(0); - } + + str= &spider->result_list.sqls[link_idx]; error_num = append_disable_keys(str, link_idx); DBUG_RETURN(error_num); } @@ -14293,8 +14236,7 @@ int spider_mbase_handler::disable_keys( DBUG_ENTER("spider_mbase_handler::disable_keys"); DBUG_PRINT("info",("spider this=%p", this)); str->length(0); - if ((error_num = append_disable_keys_part(SPIDER_SQL_TYPE_OTHER_HS, - link_idx))) + if ((error_num= append_disable_keys_part(link_idx))) { DBUG_RETURN(error_num); } @@ -14352,8 +14294,7 @@ int spider_mbase_handler::enable_keys( DBUG_ENTER("spider_mbase_handler::enable_keys"); DBUG_PRINT("info",("spider this=%p", this)); str->length(0); - if ((error_num = append_enable_keys_part(SPIDER_SQL_TYPE_OTHER_HS, - link_idx))) + if ((error_num= append_enable_keys_part(link_idx))) { DBUG_RETURN(error_num); } @@ -14412,8 +14353,7 @@ int spider_mbase_handler::check_table( DBUG_ENTER("spider_mbase_handler::check_table"); DBUG_PRINT("info",("spider this=%p", this)); str->length(0); - if ((error_num = append_check_table_part(SPIDER_SQL_TYPE_OTHER_HS, - link_idx, check_opt))) + if ((error_num= append_check_table_part(link_idx, check_opt))) { DBUG_RETURN(error_num); } @@ -14472,8 +14412,7 @@ int spider_mbase_handler::repair_table( DBUG_ENTER("spider_mbase_handler::repair_table"); DBUG_PRINT("info",("spider this=%p", this)); str->length(0); - if ((error_num = append_repair_table_part(SPIDER_SQL_TYPE_OTHER_HS, - link_idx, check_opt))) + if ((error_num= append_repair_table_part(link_idx, check_opt))) { DBUG_RETURN(error_num); } @@ -14531,8 +14470,7 @@ int spider_mbase_handler::analyze_table( DBUG_ENTER("spider_mbase_handler::analyze_table"); DBUG_PRINT("info",("spider this=%p", this)); str->length(0); - if ((error_num = append_analyze_table_part(SPIDER_SQL_TYPE_OTHER_HS, - link_idx))) + if ((error_num= append_analyze_table_part(link_idx))) { DBUG_RETURN(error_num); } @@ -14590,8 +14528,7 @@ int spider_mbase_handler::optimize_table( DBUG_ENTER("spider_mbase_handler::optimize_table"); DBUG_PRINT("info",("spider this=%p", this)); str->length(0); - if ((error_num = append_optimize_table_part(SPIDER_SQL_TYPE_OTHER_HS, - link_idx))) + if ((error_num= append_optimize_table_part(link_idx))) { DBUG_RETURN(error_num); } @@ -14650,8 +14587,7 @@ int spider_mbase_handler::flush_tables( DBUG_ENTER("spider_mbase_handler::flush_tables"); DBUG_PRINT("info",("spider this=%p", this)); str->length(0); - if ((error_num = append_flush_tables_part(SPIDER_SQL_TYPE_OTHER_HS, - link_idx, lock))) + if ((error_num= append_flush_tables_part(link_idx, lock))) { DBUG_RETURN(error_num); } diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h index 35f4f8392d9..ba521a58fb8 100644 --- a/storage/spider/spd_db_mysql.h +++ b/storage/spider/spd_db_mysql.h @@ -1218,64 +1218,40 @@ public: ulong sql_type, int link_idx ); - int append_flush_tables_part( - ulong sql_type, - int link_idx, - bool lock - ); + int append_flush_tables_part(int link_idx, bool lock); int append_flush_tables( spider_string *str, int link_idx, bool lock ); - int append_optimize_table_part( - ulong sql_type, - int link_idx - ); + int append_optimize_table_part(int link_idx); int append_optimize_table( spider_string *str, int link_idx ); - int append_analyze_table_part( - ulong sql_type, - int link_idx - ); + int append_analyze_table_part(int link_idx); int append_analyze_table( spider_string *str, int link_idx ); - int append_repair_table_part( - ulong sql_type, - int link_idx, - HA_CHECK_OPT* check_opt - ); + int append_repair_table_part(int link_idx, HA_CHECK_OPT *check_opt); int append_repair_table( spider_string *str, int link_idx, HA_CHECK_OPT* check_opt ); - int append_check_table_part( - ulong sql_type, - int link_idx, - HA_CHECK_OPT* check_opt - ); + int append_check_table_part(int link_idx, HA_CHECK_OPT *check_opt); int append_check_table( spider_string *str, int link_idx, HA_CHECK_OPT* check_opt ); - int append_enable_keys_part( - ulong sql_type, - int link_idx - ); + int append_enable_keys_part(int link_idx); int append_enable_keys( spider_string *str, int link_idx ); - int append_disable_keys_part( - ulong sql_type, - int link_idx - ); + int append_disable_keys_part(int link_idx); int append_disable_keys( spider_string *str, int link_idx diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 943d781a171..327d4a30a0b 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -6806,7 +6806,8 @@ int spider_get_sts( current_thd, share->lgtm_tblhnd_share->table_name, share->lgtm_tblhnd_share->table_name_length, - &share->stat); + &share->stat + ); if (!error_num || (error_num != HA_ERR_KEY_NOT_FOUND && error_num != HA_ERR_END_OF_FILE)) need_to_get = FALSE; @@ -6933,7 +6934,8 @@ int spider_get_crd( share->lgtm_tblhnd_share->table_name, share->lgtm_tblhnd_share->table_name_length, share->cardinality, - table->s->fields); + table->s->fields + ); if (!error_num || (error_num != HA_ERR_KEY_NOT_FOUND && error_num != HA_ERR_END_OF_FILE)) need_to_get = FALSE; diff --git a/support-files/policy/apparmor/usr.sbin.mysqld b/support-files/policy/apparmor/usr.sbin.mysqld index c60ecd28531..c9b780bd413 100644 --- a/support-files/policy/apparmor/usr.sbin.mysqld +++ b/support-files/policy/apparmor/usr.sbin.mysqld @@ -47,7 +47,7 @@ /usr/lib/mysql/plugin/ r, /usr/lib/mysql/plugin/*.so* mr, /usr/sbin/mariadbd mr, - /usr/share/mysql/** r, + /usr/share/mariadb/** r, /var/lib/mysql/ r, /var/lib/mysql/** rwk, /var/log/mysql.err rw, diff --git a/support-files/rpm/server-postin.sh b/support-files/rpm/server-postin.sh index 8a017560623..e71efdb56de 100644 --- a/support-files/rpm/server-postin.sh +++ b/support-files/rpm/server-postin.sh @@ -78,7 +78,7 @@ SEDOMPROG=$SETARGETDIR/domains/program SECONPROG=$SETARGETDIR/file_contexts/program if [ -x /usr/sbin/semodule ] ; then - /usr/sbin/semodule -i /usr/share/mysql/policy/selinux/mariadb.pp + /usr/sbin/semodule -i /usr/share/mariadb/policy/selinux/mariadb.pp fi if [ -x /sbin/restorecon ] ; then diff --git a/support-files/rpm/server.cnf b/support-files/rpm/server.cnf index bf9ed9c4f46..624b47a25cb 100644 --- a/support-files/rpm/server.cnf +++ b/support-files/rpm/server.cnf @@ -2,13 +2,16 @@ # These groups are read by MariaDB server. # Use it for options that only the server (but not clients) should see # -# See the examples of server my.cnf files in /usr/share/mysql/ -# # this is read by the standalone daemon and embedded servers [server] -# this is only for the mysqld standalone daemon +# This group is only read by MariaDB servers, not by MySQL. +# If you use the same .cnf file for MySQL and MariaDB, +# you can put MariaDB-only options here +[mariadb] + +# This group is read by both MariaDB and MySQL servers [mysqld] # @@ -34,11 +37,6 @@ # this is only for embedded server [embedded] -# This group is only read by MariaDB servers, not by MySQL. -# If you use the same .cnf file for MySQL and MariaDB, -# you can put MariaDB-only options here -[mariadb] - # This group is only read by MariaDB-10.8 servers. # If you use the same .cnf file for MariaDB of different versions, # use this group for options that older servers don't understand |