From 39f63f6643a1e56d0199f108518dd14f0c6cbbaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 21 Oct 2021 15:53:35 +0300 Subject: [PATCH 1/8] MDEV-19522 fixup: Use correct printf format --- storage/innobase/unittest/innodb_fts-t.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/unittest/innodb_fts-t.cc b/storage/innobase/unittest/innodb_fts-t.cc index 4e10c0e439e..72a4ca3ae78 100644 --- a/storage/innobase/unittest/innodb_fts-t.cc +++ b/storage/innobase/unittest/innodb_fts-t.cc @@ -45,8 +45,8 @@ int main(int, char**) !memcmp(&fts_info[i].buf, buf, len) && fts_decode_vlc(&fts_buf) == fts_info[i].val && fts_buf == &buf[len]) - ok(true, "FTS Encoded for %d bytes", fts_info[i].len); + ok(true, "FTS Encoded for %zu bytes", fts_info[i].len); else - ok(false, "FTS Encoded for %d bytes", fts_info[i].len); + ok(false, "FTS Encoded for %zu bytes", fts_info[i].len); } } From 7d6617e966c02a08c36d86ac5ae4be70fe0f93e9 Mon Sep 17 00:00:00 2001 From: Sergei Krivonos Date: Thu, 21 Oct 2021 15:21:44 +0300 Subject: [PATCH 2/8] MDEV-19129: Xcode compatibility update: mysql-test-run.pl: rename $opt_vs_config to $multiconfig to use with other cmake multiconfig generators --- mysql-test/lib/My/Find.pm | 2 +- mysql-test/lib/v1/mysql-test-run.pl | 8 +-- mysql-test/mysql-test-run.pl | 71 ++++++++++--------- mysql-test/suite/unit/suite.pm | 2 +- storage/rocksdb/mysql-test/rocksdb/suite.pm | 2 +- .../rocksdb/mysql-test/rocksdb_rpl/suite.pm | 2 +- .../mysql-test/rocksdb_stress/suite.pm | 2 +- .../mysql-test/rocksdb_sys_vars/suite.pm | 2 +- 8 files changed, 46 insertions(+), 45 deletions(-) diff --git a/mysql-test/lib/My/Find.pm b/mysql-test/lib/My/Find.pm index b5a07ac8632..b8c13752212 100644 --- a/mysql-test/lib/My/Find.pm +++ b/mysql-test/lib/My/Find.pm @@ -159,7 +159,7 @@ sub my_build_path_list { # User can select to look in a special build dir # which is a subdirectory of any of the paths my @extra_dirs; - my $build_dir= $::opt_vs_config || $ENV{MTR_VS_CONFIG} || $ENV{MTR_BUILD_DIR}; + my $build_dir= $::multiconfig || $ENV{MTR_VS_CONFIG} || $ENV{MTR_BUILD_DIR}; push(@extra_dirs, $build_dir) if defined $build_dir; if (defined $extension){ diff --git a/mysql-test/lib/v1/mysql-test-run.pl b/mysql-test/lib/v1/mysql-test-run.pl index 6fe5f66fbfc..08f256bb2f2 100755 --- a/mysql-test/lib/v1/mysql-test-run.pl +++ b/mysql-test/lib/v1/mysql-test-run.pl @@ -141,7 +141,7 @@ our $opt_tmpdir; # A path but set directly on cmd line # configuration used to build them. To make life easier, an environment # variable or command-line option may be specified to control which set of # executables will be used by the test suite. -our $opt_vs_config = $ENV{'MTR_VS_CONFIG'}; +our $multiconfig = $ENV{'MTR_VS_CONFIG'}; our $default_vardir; @@ -502,7 +502,7 @@ sub command_line_setup () { 'compress' => \$opt_compress, 'bench' => \$opt_bench, 'small-bench' => \$opt_small_bench, - 'vs-config' => \$opt_vs_config, + 'vs-config' => \$multiconfig, # Control what test suites or cases to run 'force' => \$opt_force, @@ -2213,9 +2213,9 @@ sub vs_config_dirs ($$) { $exe = "" if not defined $exe; - if ($opt_vs_config) + if ($multiconfig) { - return ("$glob_bindir/$path_part/$opt_vs_config/$exe"); + return ("$glob_bindir/$path_part/$multiconfig/$exe"); } return ("$glob_bindir/$path_part/release/$exe", diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 4bc212aedbe..b87263eebd4 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -172,7 +172,7 @@ my $path_config_file; # The generated config file, var/my.cnf # configuration used to build them. To make life easier, an environment # variable or command-line option may be specified to control which set of # executables will be used by the test suite. -our $opt_vs_config = $ENV{'MTR_VS_CONFIG'}; +our $multiconfig = $ENV{'MTR_VS_CONFIG'}; my @DEFAULT_SUITES= qw( main- @@ -420,7 +420,7 @@ sub check_wsrep_support() { my $my_print_defaults_exe= mtr_exe_maybe_exists( "$bindir/extra/my_print_defaults", - "$bindir/extra/Debug/my_print_defaults", + "$bindir/extra/$multiconfig/my_print_defaults", "$path_client_bindir/my_print_defaults"); my $epath= ""; if ($my_print_defaults_exe ne "") { @@ -481,7 +481,7 @@ sub check_mariabackup_support() { $mariabackup_path= ""; $mariabackup_exe= mtr_exe_maybe_exists( - "$bindir/extra/mariabackup$opt_vs_config/mariabackup", + "$bindir/extra/mariabackup$multiconfig/mariabackup", "$path_client_bindir/mariabackup"); if ($mariabackup_exe ne "") { my $bpath= dirname($mariabackup_exe); @@ -493,7 +493,7 @@ sub check_mariabackup_support() { $ENV{XTRABACKUP}= $mariabackup_exe; $ENV{XBSTREAM}= mtr_exe_maybe_exists( - "$bindir/extra/mariabackup/$opt_vs_config/mbstream", + "$bindir/extra/mariabackup/$multiconfig/mbstream", "$path_client_bindir/mbstream"); $ENV{INNOBACKUPEX}= "$mariabackup_exe --innobackupex"; @@ -1236,7 +1236,7 @@ sub command_line_setup { 'ssl|with-openssl' => \$opt_ssl, 'skip-ssl' => \$opt_skip_ssl, 'compress' => \$opt_compress, - 'vs-config=s' => \$opt_vs_config, + 'vs-config=s' => \$multiconfig, # Max number of parallel threads to use 'parallel=s' => \$opt_parallel, @@ -1416,8 +1416,8 @@ sub command_line_setup { { $path_client_bindir= mtr_path_exists("$bindir/client_release", "$bindir/client_debug", - "$bindir/client/debug", - "$bindir/client$opt_vs_config", + "$bindir/client/$multiconfig", + "$bindir/client$multiconfig", "$bindir/client", "$bindir/bin"); } @@ -1974,7 +1974,7 @@ sub executable_setup () { if ( $opt_embedded_server ) { $exe_mysqltest= - mtr_exe_exists("$bindir/libmysqld/examples$opt_vs_config/mysqltest_embedded", + mtr_exe_exists("$bindir/libmysqld/examples$multiconfig/mysqltest_embedded", "$path_client_bindir/mysqltest_embedded"); } else @@ -2078,10 +2078,10 @@ sub mysql_client_test_arguments(){ # mysql_client_test executable may _not_ exist if ( $opt_embedded_server ) { $exe= mtr_exe_maybe_exists( - "$bindir/libmysqld/examples$opt_vs_config/mysql_client_test_embedded", + "$bindir/libmysqld/examples$multiconfig/mysql_client_test_embedded", "$bindir/bin/mysql_client_test_embedded"); } else { - $exe= mtr_exe_maybe_exists("$bindir/tests$opt_vs_config/mysql_client_test", + $exe= mtr_exe_maybe_exists("$bindir/tests$multiconfig/mysql_client_test", "$bindir/bin/mysql_client_test"); } @@ -2251,7 +2251,7 @@ sub environment_setup { my $client_config_exe= mtr_exe_maybe_exists( - "$bindir/libmariadb/mariadb_config$opt_vs_config/mariadb_config", + "$bindir/libmariadb/mariadb_config$multiconfig/mariadb_config", "$bindir/bin/mariadb_config"); if ($client_config_exe) { @@ -2270,7 +2270,7 @@ sub environment_setup { # some versions, test using it should be skipped # ---------------------------------------------------- my $exe_bug25714= - mtr_exe_maybe_exists("$bindir/tests$opt_vs_config/bug25714"); + mtr_exe_maybe_exists("$bindir/tests$multiconfig/bug25714"); $ENV{'MYSQL_BUG25714'}= native_path($exe_bug25714); # ---------------------------------------------------- @@ -2287,7 +2287,7 @@ sub environment_setup { # my_print_defaults # ---------------------------------------------------- my $exe_my_print_defaults= - mtr_exe_exists("$bindir/extra$opt_vs_config/my_print_defaults", + mtr_exe_exists("$bindir/extra$multiconfig/my_print_defaults", "$path_client_bindir/my_print_defaults"); $ENV{'MYSQL_MY_PRINT_DEFAULTS'}= native_path($exe_my_print_defaults); @@ -2322,16 +2322,16 @@ sub environment_setup { # ---------------------------------------------------- # perror # ---------------------------------------------------- - my $exe_perror= mtr_exe_exists("$bindir/extra$opt_vs_config/perror", + my $exe_perror= mtr_exe_exists("$bindir/extra$multiconfig/perror", "$path_client_bindir/perror"); $ENV{'MY_PERROR'}= native_path($exe_perror); # ---------------------------------------------------- # mysql_tzinfo_to_sql # ---------------------------------------------------- - my $exe_mysql_tzinfo_to_sql= mtr_exe_exists("$basedir/sql$opt_vs_config/mysql_tzinfo_to_sql", + my $exe_mysql_tzinfo_to_sql= mtr_exe_exists("$basedir/sql$multiconfig/mysql_tzinfo_to_sql", "$path_client_bindir/mysql_tzinfo_to_sql", - "$bindir/sql$opt_vs_config/mysql_tzinfo_to_sql"); + "$bindir/sql$multiconfig/mysql_tzinfo_to_sql"); $ENV{'MYSQL_TZINFO_TO_SQL'}= native_path($exe_mysql_tzinfo_to_sql); # ---------------------------------------------------- @@ -2339,7 +2339,7 @@ sub environment_setup { # ---------------------------------------------------- my $exe_replace= mtr_exe_exists(vs_config_dirs('extra', 'replace'), "$basedir/extra/replace", - "$bindir/extra$opt_vs_config/replace", + "$bindir/extra$multiconfig/replace", "$path_client_bindir/replace"); $ENV{'REPLACE'}= native_path($exe_replace); @@ -2347,7 +2347,7 @@ sub environment_setup { # innochecksum # ---------------------------------------------------- my $exe_innochecksum= - mtr_exe_maybe_exists("$bindir/extra$opt_vs_config/innochecksum", + mtr_exe_maybe_exists("$bindir/extra$multiconfig/innochecksum", "$path_client_bindir/innochecksum"); if ($exe_innochecksum) { @@ -2535,10 +2535,10 @@ sub setup_vardir() { { if (!$opt_embedded_server) { - for (<$bindir/storage/*$opt_vs_config/*.dll>, - <$bindir/plugin/*$opt_vs_config/*.dll>, - <$bindir/libmariadb$opt_vs_config/*.dll>, - <$bindir/sql$opt_vs_config/*.dll>) + for (<$bindir/storage/*$multiconfig/*.dll>, + <$bindir/plugin/*$multiconfig/*.dll>, + <$bindir/libmariadb$multiconfig/*.dll>, + <$bindir/sql$multiconfig/*.dll>) { my $pname=basename($_); copy rel2abs($_), "$plugindir/$pname"; @@ -2555,11 +2555,11 @@ sub setup_vardir() { unlink "$plugindir/symlink_test"; } - for (<$bindir/storage/*/*.so>, - <$bindir/plugin/*/*.so>, + for (<$bindir/storage/*$multiconfig/*.so>, + <$bindir/plugin/*$multiconfig/*.so>, <$bindir/libmariadb/plugins/*/*.so>, - <$bindir/libmariadb/*.so>, - <$bindir/sql/*.so>) + <$bindir/libmariadb/$multiconfig/*.so>, + <$bindir/sql$multiconfig/*.so>) { my $pname=basename($_); if ($opt_use_copy) @@ -2681,23 +2681,24 @@ sub check_debug_support { # executables, and plugins - that is, something that can affect the test suite # sub fix_vs_config_dir () { - return $opt_vs_config="" unless IS_WINDOWS; - return $opt_vs_config="/$opt_vs_config" if $opt_vs_config; + return $multiconfig="/$multiconfig" if $multiconfig; my $modified = 1e30; - $opt_vs_config=""; + $multiconfig=""; - for (<$bindir/sql/*/mysqld.exe>) { #/ + for (<$bindir/sql/*/mysqld.exe>, + <$bindir/sql/*/mysqld> + ) { #/ if (-M $_ < $modified) { $modified = -M _; - $opt_vs_config = basename(dirname($_)); + $multiconfig = basename(dirname($_)); } } - mtr_report("VS config: $opt_vs_config"); - $opt_vs_config="/$opt_vs_config" if $opt_vs_config; + mtr_report("VS config: $multiconfig"); + $multiconfig="/$multiconfig" if $multiconfig; } @@ -2717,9 +2718,9 @@ sub vs_config_dirs ($$) { # Don't look in these dirs when not on windows return () unless IS_WINDOWS; - if ($opt_vs_config) + if ($multiconfig) { - return ("$basedir/$path_part/$opt_vs_config/$exe"); + return ("$basedir/$path_part/$multiconfig/$exe"); } return ("$basedir/$path_part/release/$exe", diff --git a/mysql-test/suite/unit/suite.pm b/mysql-test/suite/unit/suite.pm index c8180c59240..6cd0dfd4bfd 100644 --- a/mysql-test/suite/unit/suite.pm +++ b/mysql-test/suite/unit/suite.pm @@ -40,7 +40,7 @@ sub start_test { my $bin=$ENV{MTR_BINDIR} || '..'; return "Not run for embedded server" if $::opt_embedded_server; return "Not configured to run ctest" unless -f "$bin/CTestTestfile.cmake"; - my ($ctest_vs)= $::opt_vs_config ? "-C ".substr($::opt_vs_config,1) : ""; + my ($ctest_vs)= $::multiconfig ? "-C ".substr($::multiconfig,1) : ""; my (@ctest_list)= `cd "$bin" && ctest $ctest_vs --show-only --verbose`; return "No ctest" if $?; diff --git a/storage/rocksdb/mysql-test/rocksdb/suite.pm b/storage/rocksdb/mysql-test/rocksdb/suite.pm index 633e883f46d..b4feb20a451 100644 --- a/storage/rocksdb/mysql-test/rocksdb/suite.pm +++ b/storage/rocksdb/mysql-test/rocksdb/suite.pm @@ -15,7 +15,7 @@ use strict; my $sst_dump= ::mtr_exe_maybe_exists( - "$::bindir/storage/rocksdb$::opt_vs_config/sst_dump", + "$::bindir/storage/rocksdb$::multiconfig/sst_dump", "$::path_client_bindir/sst_dump"); return "RocksDB is not compiled, no sst_dump" unless $sst_dump; $ENV{MARIAROCKS_SST_DUMP}="$sst_dump"; diff --git a/storage/rocksdb/mysql-test/rocksdb_rpl/suite.pm b/storage/rocksdb/mysql-test/rocksdb_rpl/suite.pm index 1cc123b2a2a..7e9fba4a59c 100644 --- a/storage/rocksdb/mysql-test/rocksdb_rpl/suite.pm +++ b/storage/rocksdb/mysql-test/rocksdb_rpl/suite.pm @@ -13,7 +13,7 @@ use strict; my $sst_dump= ::mtr_exe_maybe_exists( - "$::bindir/storage/rocksdb$::opt_vs_config/sst_dump", + "$::bindir/storage/rocksdb$::multiconfig/sst_dump", "$::path_client_bindir/sst_dump"); return "RocksDB is not compiled, no sst_dump" unless $sst_dump; $ENV{MARIAROCKS_SST_DUMP}="$sst_dump"; diff --git a/storage/rocksdb/mysql-test/rocksdb_stress/suite.pm b/storage/rocksdb/mysql-test/rocksdb_stress/suite.pm index 106a1d6a0e7..66a46291a8c 100644 --- a/storage/rocksdb/mysql-test/rocksdb_stress/suite.pm +++ b/storage/rocksdb/mysql-test/rocksdb_stress/suite.pm @@ -15,7 +15,7 @@ use strict; my $sst_dump= ::mtr_exe_maybe_exists( - "$::bindir/storage/rocksdb$::opt_vs_config/sst_dump", + "$::bindir/storage/rocksdb$::multiconfig/sst_dump", "$::path_client_bindir/sst_dump"); return "RocksDB is not compiled, no sst_dump" unless $sst_dump; $ENV{MARIAROCKS_SST_DUMP}="$sst_dump"; diff --git a/storage/rocksdb/mysql-test/rocksdb_sys_vars/suite.pm b/storage/rocksdb/mysql-test/rocksdb_sys_vars/suite.pm index 5264d657ef7..d50f4d2422e 100644 --- a/storage/rocksdb/mysql-test/rocksdb_sys_vars/suite.pm +++ b/storage/rocksdb/mysql-test/rocksdb_sys_vars/suite.pm @@ -12,7 +12,7 @@ use strict; my $sst_dump= ::mtr_exe_maybe_exists( - "$::bindir/storage/rocksdb$::opt_vs_config/sst_dump", + "$::bindir/storage/rocksdb$::multiconfig/sst_dump", "$::path_client_bindir/sst_dump"); return "RocksDB is not compiled, no sst_dump" unless $sst_dump; $ENV{MARIAROCKS_SST_DUMP}="$sst_dump"; From 2011fcf87ddb0dc4e15bdfd7ab93577c862e82c4 Mon Sep 17 00:00:00 2001 From: Bernard Spil Date: Sun, 31 May 2020 14:40:22 +0200 Subject: [PATCH 3/8] MDEV-22552: mytop packaging Make `my_print_defaults` a client app (required by `mytop`). Closes #1566 Reviewed by: serg@mariadb.com, anel@mariadb.org --- extra/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/CMakeLists.txt b/extra/CMakeLists.txt index 71c9d60afb0..f53e9fdf8d8 100644 --- a/extra/CMakeLists.txt +++ b/extra/CMakeLists.txt @@ -46,7 +46,7 @@ ADD_CUSTOM_TARGET(GenError DEPENDS ${CMAKE_BINARY_DIR}/include/mysqld_error.h.tmp) -MYSQL_ADD_EXECUTABLE(my_print_defaults my_print_defaults.c) +MYSQL_ADD_EXECUTABLE(my_print_defaults my_print_defaults.c COMPONENT Client) TARGET_LINK_LIBRARIES(my_print_defaults mysys) MYSQL_ADD_EXECUTABLE(perror perror.c) From 395a033237686f2504e1acd9cb9555941a8e7179 Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Mon, 21 Jun 2021 14:02:17 +0200 Subject: [PATCH 4/8] MDEV-22552: mytop packaging `mytop` and `my_print_defaults` for RPM - Add `mytop` to client package - Add man page of `my_print_defaults` to client package - Add dependencies for RPMs - Remove old comment - Remove dead link Reviewed by: serg@mariadb.com --- cmake/cpack_rpm.cmake | 13 ++++++++----- cmake/install_layout.cmake | 2 -- man/CMakeLists.txt | 4 ++-- scripts/CMakeLists.txt | 2 +- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 4f33f6f951d..068068a2962 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -150,11 +150,14 @@ ENDMACRO(SETA) SETA(CPACK_RPM_client_PACKAGE_OBSOLETES "mysql-client" - "MySQL-client") + "MySQL-client" + "mytop <= 1.7") SETA(CPACK_RPM_client_PACKAGE_PROVIDES "MySQL-client" - "mysql-client") - + "mysql-client" + "mytop") +SET(CPACK_RPM_client_PACKAGE_CONFLICTS + "MariaDB-server <= 10.5.10") SETA(CPACK_RPM_devel_PACKAGE_OBSOLETES "MySQL-devel") SETA(CPACK_RPM_devel_PACKAGE_PROVIDES @@ -180,7 +183,7 @@ SETA(CPACK_RPM_test_PACKAGE_PROVIDES SETA(CPACK_RPM_server_PACKAGE_REQUIRES "${CPACK_RPM_PACKAGE_REQUIRES}" - "MariaDB-client") + "MariaDB-client >= 10.5.11") IF(WITH_WSREP) SETA(CPACK_RPM_server_PACKAGE_REQUIRES @@ -223,7 +226,7 @@ ALTERNATIVE_NAME("test" "mysql-test") IF(RPM MATCHES "(rhel|centos)6") ALTERNATIVE_NAME("client" "mysql") ELSEIF(RPM MATCHES "fedora" OR RPM MATCHES "(rhel|centos)7") - SET(epoch 1:) # this is fedora + SET(epoch 1:) ALTERNATIVE_NAME("client" "mariadb") ALTERNATIVE_NAME("client" "mysql") ALTERNATIVE_NAME("devel" "mariadb-devel") diff --git a/cmake/install_layout.cmake b/cmake/install_layout.cmake index bbffc80ec0a..877b147bc6e 100644 --- a/cmake/install_layout.cmake +++ b/cmake/install_layout.cmake @@ -64,8 +64,6 @@ # # - INSTALL_UNIX_ADDRDIR (path to mysql.sock) # -# When changing this page, _please_ do not forget to update public Wiki -# http://forge.mysql.com/wiki/CMake#Fine-tuning_installation_paths IF(NOT INSTALL_LAYOUT) IF(DEB) diff --git a/man/CMakeLists.txt b/man/CMakeLists.txt index 6c5fe2c2050..f5ae0a0fb38 100644 --- a/man/CMakeLists.txt +++ b/man/CMakeLists.txt @@ -13,7 +13,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA -SET(MAN1_SERVER innochecksum.1 my_print_defaults.1 myisam_ftdump.1 myisamchk.1 +SET(MAN1_SERVER innochecksum.1 myisam_ftdump.1 myisamchk.1 aria_chk.1 aria_dump_log.1 aria_ftdump.1 aria_pack.1 aria_read_log.1 aria_s3_copy.1 myisamlog.1 myisampack.1 mysql.server.1 mariadb-conv.1 @@ -34,7 +34,7 @@ SET(MAN8_SERVER mysqld.8) SET(MAN1_CLIENT msql2mysql.1 mysql.1 mysql_find_rows.1 mysql_waitpid.1 mysqlaccess.1 mysqladmin.1 mysqlbinlog.1 mysqlcheck.1 mysqldump.1 mysqlimport.1 mysqlshow.1 mysqlslap.1 mytop.1 - mysql_plugin.1 mysql_embedded.1) + mysql_plugin.1 mysql_embedded.1 my_print_defaults.1) SET(MAN1_DEVEL mysql_config.1) SET(MAN1_TEST mysql-stress-test.pl.1 mysql-test-run.pl.1 mysql_client_test.1 mysqltest.1 mysqltest_embedded.1 mysql_client_test_embedded.1 diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 923b3110af7..bed65a19e39 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -253,7 +253,7 @@ SET(mysql_config_COMPONENT Development) SET(msql2mysql_COMPONENT Client) SET(mariadb-access_COMPONENT Client) SET(mariadb-find-rows_COMPONENT Client) -SET(mytop_COMPONENT Mytop) +SET(mytop_COMPONENT Client) IF(WIN32) # On Windows, some .sh and some .pl.in files are configured From 49098bfd4908ff3a33ae6c6a30c2a9b7dd90e4df Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 7 Oct 2021 20:58:18 +0400 Subject: [PATCH 5/8] MDEV-26732 Assertion `0' failed in Item::val_native Also fixes MDEV-24619 Wrong result or Assertion `0' in Item::val_native / Type_handler_inet6::Item_val_native_with_conversion Type_handler_inet6::create_item_copy() created a generic Item_copy_string, which does not implement val_native() - it has a dummy implementation with DBUG_ASSERT(0), which made the server crash. Fix: - Adding a new class Type_handler_inet6 which implements val_native(). - Fixing Type_handler_inet6::create_item_copy() to make Item_copy_inet6 instead of Item_copy_string. --- .../mysql-test/type_inet/type_inet6.result | 35 ++++++++++++ .../mysql-test/type_inet/type_inet6.test | 26 +++++++++ plugin/type_inet/sql_type_inet.cc | 57 +++++++++++++++++++ plugin/type_inet/sql_type_inet.h | 1 + 4 files changed, 119 insertions(+) diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6.result b/plugin/type_inet/mysql-test/type_inet/type_inet6.result index da949481337..ac16f5c06ce 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6.result @@ -2159,3 +2159,38 @@ IFNULL(c, '::1') ::1 DROP TABLE t2; DROP TABLE t1; +# +# MDEV-26732 Assertion `0' failed in Item::val_native +# +SELECT CAST(CONCAT('::', REPEAT('',RAND())) AS INET6) AS f, var_pop('x') FROM dual HAVING f > ''; +f var_pop('x') +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'x' +Warning 1292 Incorrect inet6 value: '' +SELECT CAST(CONCAT('::', REPEAT('',RAND())) AS INET6) AS f, var_pop(1) FROM dual HAVING f >= '::'; +f var_pop(1) +:: 0.0000 +CREATE TABLE t1(id INET6 NOT NULL PRIMARY KEY, dsc INET6); +INSERT INTO t1 VALUES ('::1', '1::1'),('::3', '1::3'),('::4', NULL); +CREATE TABLE t2 SELECT COALESCE(t1.dsc), COUNT(*) FROM t1 GROUP BY t1.id; +SELECT * FROM t2 ORDER BY 1,2; +COALESCE(t1.dsc) COUNT(*) +NULL 1 +1::1 1 +1::3 1 +DROP TABLE t1, t2; +# +# MDEV-24619 Wrong result or Assertion `0' in Item::val_native / Type_handler_inet6::Item_val_native_with_conversion +# +CREATE TABLE t1 (a INET6); +INSERT INTO t1 VALUES ('::'),('::'); +SELECT IF(1, '::', a) AS f FROM t1 GROUP BY 'foo' HAVING f != ''; +f +Warnings: +Warning 1292 Incorrect inet6 value: '' +SELECT IF(1, '::', a) AS f FROM t1 GROUP BY 'foo' HAVING f != '::'; +f +SELECT IF(1, '::', a) AS f FROM t1 GROUP BY 'foo' HAVING f != '::1'; +f +:: +DROP TABLE t1; diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6.test b/plugin/type_inet/mysql-test/type_inet/type_inet6.test index ad4cfe57986..6a5db1ad43f 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6.test +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6.test @@ -1586,3 +1586,29 @@ SELECT * FROM t2; DROP TABLE t2; DROP TABLE t1; + +--echo # +--echo # MDEV-26732 Assertion `0' failed in Item::val_native +--echo # + +# This tests Item_copy_inet6::val_native() +SELECT CAST(CONCAT('::', REPEAT('',RAND())) AS INET6) AS f, var_pop('x') FROM dual HAVING f > ''; +SELECT CAST(CONCAT('::', REPEAT('',RAND())) AS INET6) AS f, var_pop(1) FROM dual HAVING f >= '::'; + +# This tests Item_copy_inet6::save_in_field() +CREATE TABLE t1(id INET6 NOT NULL PRIMARY KEY, dsc INET6); +INSERT INTO t1 VALUES ('::1', '1::1'),('::3', '1::3'),('::4', NULL); +CREATE TABLE t2 SELECT COALESCE(t1.dsc), COUNT(*) FROM t1 GROUP BY t1.id; +SELECT * FROM t2 ORDER BY 1,2; +DROP TABLE t1, t2; + +--echo # +--echo # MDEV-24619 Wrong result or Assertion `0' in Item::val_native / Type_handler_inet6::Item_val_native_with_conversion +--echo # + +CREATE TABLE t1 (a INET6); +INSERT INTO t1 VALUES ('::'),('::'); +SELECT IF(1, '::', a) AS f FROM t1 GROUP BY 'foo' HAVING f != ''; +SELECT IF(1, '::', a) AS f FROM t1 GROUP BY 'foo' HAVING f != '::'; +SELECT IF(1, '::', a) AS f FROM t1 GROUP BY 'foo' HAVING f != '::1'; +DROP TABLE t1; diff --git a/plugin/type_inet/sql_type_inet.cc b/plugin/type_inet/sql_type_inet.cc index 14d854be14f..9832a84a1b9 100644 --- a/plugin/type_inet/sql_type_inet.cc +++ b/plugin/type_inet/sql_type_inet.cc @@ -1227,6 +1227,57 @@ public: }; +class Item_copy_inet6: public Item_copy +{ + NativeBufferInet6 m_value; +public: + Item_copy_inet6(THD *thd, Item *item_arg): Item_copy(thd, item_arg) {} + + bool val_native(THD *thd, Native *to) override + { + if (null_value) + return true; + return to->copy(m_value.ptr(), m_value.length()); + } + String *val_str(String *to) override + { + if (null_value) + return NULL; + Inet6_null tmp(m_value.ptr(), m_value.length()); + return tmp.is_null() || tmp.to_string(to) ? NULL : to; + } + my_decimal *val_decimal(my_decimal *to) override + { + my_decimal_set_zero(to); + return to; + } + double val_real() override + { + return 0; + } + longlong val_int() override + { + return 0; + } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override + { + set_zero_time(ltime, MYSQL_TIMESTAMP_TIME); + return null_value; + } + void copy() override + { + null_value= item->val_native(current_thd, &m_value); + DBUG_ASSERT(null_value == item->null_value); + } + int save_in_field(Field *field, bool no_conversions) override + { + return Item::save_in_field(field, no_conversions); + } + Item *get_copy(THD *thd) override + { return get_item_copy(thd, this); } +}; + + class in_inet6 :public in_vector { Inet6 m_value; @@ -1465,6 +1516,12 @@ Item_cache *Type_handler_inet6::Item_get_cache(THD *thd, const Item *item) const } +Item_copy *Type_handler_inet6::create_item_copy(THD *thd, Item *item) const +{ + return new (thd->mem_root) Item_copy_inet6(thd, item); +} + + Item * Type_handler_inet6::make_const_item_for_comparison(THD *thd, Item *src, diff --git a/plugin/type_inet/sql_type_inet.h b/plugin/type_inet/sql_type_inet.h index 4de1124f4c1..c1abb11fc59 100644 --- a/plugin/type_inet/sql_type_inet.h +++ b/plugin/type_inet/sql_type_inet.h @@ -691,6 +691,7 @@ public: Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const override; + Item_copy *create_item_copy(THD *thd, Item *item) const override; int cmp_native(const Native &a, const Native &b) const override { DBUG_ASSERT(a.length() == Inet6::binary_length()); From d74d95961a31b47986d943216489513896108782 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Tue, 10 Aug 2021 00:54:12 +0600 Subject: [PATCH 6/8] MDEV-18543 IMPORT TABLESPACE fails after instant DROP COLUMN ALTER TABLE IMPORT doesn't properly handle instant alter metadata. This patch makes IMPORT read, parse and apply instant alter metadata at the very beginning of operation. So, cases when source table has some metadata and destination table doesn't have it now works fine. DISCARD already removes instant metadata so importing normal table into instant table worked fine before this patch. decrypt_decompress(): decrypts and decompresses page if needed handle_instant_metadata(): this should be the first thing to read source table. Basically, it applies instant metadata to a destination dict_table_t object. This is the first thing to read FSP flags so all possible checks of it were moved to this function. PageConverter::update_index_page(): it doesn't now read instant metadata. This logic were moved into handle_instant_metadata() row_import::match_flags(): this is a first part row_import::match_schema(). As a separate function it's used by handle_instant_metadata(). fil_space_t::is_full_crc32_compressed(): added convenient function ha_innobase::discard_or_import_tablespace(): do not reload table definition to read instant metadata because handle_instant_metadata() does it better. The reverted code was originally added in 4e7ee166a9c76eb3546356aabfd2dbc759671cd0 ANONYMOUS_VAR: this is a handy thing to use along with make_scope_exit() full_crc32_import.test shows different results, because no dict_table_close() and dict_table_open_on_id() happens. Thus, SHOW CREATE TABLE shows a little bit older table definition. --- include/scope.h | 8 + .../encryption/r/instant_alter_import.result | 24 + .../encryption/t/instant_alter_import.test | 52 ++ .../r/default_row_format_compatibility.result | 3 +- .../suite/innodb/r/full_crc32_import.result | 4 +- .../suite/innodb/r/innodb-wl5522-debug.result | 2 +- .../innodb/r/instant_alter_import.result | 52 +- .../t/default_row_format_compatibility.test | 5 +- .../suite/innodb/t/innodb-wl5522-debug.test | 2 +- .../suite/innodb/t/instant_alter_import.test | 93 ++- .../innodb_zip/r/wl5522_debug_zip.result | 2 +- .../suite/innodb_zip/t/wl5522_debug_zip.test | 2 +- storage/innobase/handler/ha_innodb.cc | 19 - storage/innobase/include/fil0fil.h | 32 +- storage/innobase/row/row0import.cc | 553 ++++++++++++++---- 15 files changed, 693 insertions(+), 160 deletions(-) create mode 100644 mysql-test/suite/encryption/r/instant_alter_import.result create mode 100644 mysql-test/suite/encryption/t/instant_alter_import.test diff --git a/include/scope.h b/include/scope.h index b9e2e96ae5c..e0e9fc62969 100644 --- a/include/scope.h +++ b/include/scope.h @@ -64,3 +64,11 @@ make_scope_exit(Callable &&f) return detail::scope_exit::type>( std::forward(f)); } + +#define CONCAT_IMPL(x, y) x##y + +#define CONCAT(x, y) CONCAT_IMPL(x, y) + +#define ANONYMOUS_VARIABLE CONCAT(_anonymous_variable, __LINE__) + +#define SCOPE_EXIT auto ANONYMOUS_VARIABLE= make_scope_exit diff --git a/mysql-test/suite/encryption/r/instant_alter_import.result b/mysql-test/suite/encryption/r/instant_alter_import.result new file mode 100644 index 00000000000..cb6e7ea7307 --- /dev/null +++ b/mysql-test/suite/encryption/r/instant_alter_import.result @@ -0,0 +1,24 @@ +SET GLOBAL innodb_encrypt_tables = ON; +SET GLOBAL innodb_encryption_threads = 4; +CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT, i2 INT, i1 INT) +ENGINE=INNODB ENCRYPTED=YES ENCRYPTION_KEY_ID=4; +INSERT INTO t1 (i2) SELECT 4 FROM seq_1_to_1024; +ALTER TABLE t1 DROP COLUMN i2, ALGORITHM=INSTANT; +CREATE TABLE t2 LIKE t1; +ALTER TABLE t2 DISCARD TABLESPACE; +FLUSH TABLE t1 FOR EXPORT; +UNLOCK TABLES; +ALTER TABLE t2 IMPORT TABLESPACE; +DROP TABLE t2, t1; +CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT, i2 INT, i1 INT) +ENGINE=INNODB ENCRYPTED=YES ENCRYPTION_KEY_ID=4 PAGE_COMPRESSED=1; +INSERT INTO t1 (i2) SELECT 4 FROM seq_1_to_1024; +ALTER TABLE t1 DROP COLUMN i2, ALGORITHM=INSTANT; +CREATE TABLE t2 LIKE t1; +ALTER TABLE t2 DISCARD TABLESPACE; +FLUSH TABLE t1 FOR EXPORT; +UNLOCK TABLES; +ALTER TABLE t2 IMPORT TABLESPACE; +DROP TABLE t2, t1; +SET GLOBAL innodb_encrypt_tables = OFF; +SET GLOBAL innodb_encryption_threads = 0; diff --git a/mysql-test/suite/encryption/t/instant_alter_import.test b/mysql-test/suite/encryption/t/instant_alter_import.test new file mode 100644 index 00000000000..3a00c54665c --- /dev/null +++ b/mysql-test/suite/encryption/t/instant_alter_import.test @@ -0,0 +1,52 @@ +--source include/have_innodb.inc +--source include/have_sequence.inc +--source include/have_file_key_management_plugin.inc + +SET GLOBAL innodb_encrypt_tables = ON; +SET GLOBAL innodb_encryption_threads = 4; + + +--let $MYSQLD_DATADIR= `SELECT @@datadir` + +CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT, i2 INT, i1 INT) + ENGINE=INNODB ENCRYPTED=YES ENCRYPTION_KEY_ID=4; + +INSERT INTO t1 (i2) SELECT 4 FROM seq_1_to_1024; +ALTER TABLE t1 DROP COLUMN i2, ALGORITHM=INSTANT; + +CREATE TABLE t2 LIKE t1; +ALTER TABLE t2 DISCARD TABLESPACE; + +FLUSH TABLE t1 FOR EXPORT; + +--copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd +--copy_file $MYSQLD_DATADIR/test/t1.cfg $MYSQLD_DATADIR/test/t2.cfg + +UNLOCK TABLES; +ALTER TABLE t2 IMPORT TABLESPACE; + +DROP TABLE t2, t1; + + +CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT, i2 INT, i1 INT) + ENGINE=INNODB ENCRYPTED=YES ENCRYPTION_KEY_ID=4 PAGE_COMPRESSED=1; + +INSERT INTO t1 (i2) SELECT 4 FROM seq_1_to_1024; +ALTER TABLE t1 DROP COLUMN i2, ALGORITHM=INSTANT; + +CREATE TABLE t2 LIKE t1; +ALTER TABLE t2 DISCARD TABLESPACE; + +FLUSH TABLE t1 FOR EXPORT; + +--copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd +--copy_file $MYSQLD_DATADIR/test/t1.cfg $MYSQLD_DATADIR/test/t2.cfg + +UNLOCK TABLES; +ALTER TABLE t2 IMPORT TABLESPACE; + +DROP TABLE t2, t1; + + +SET GLOBAL innodb_encrypt_tables = OFF; +SET GLOBAL innodb_encryption_threads = 0; diff --git a/mysql-test/suite/innodb/r/default_row_format_compatibility.result b/mysql-test/suite/innodb/r/default_row_format_compatibility.result index 5070fa33a2e..f7aa984b279 100644 --- a/mysql-test/suite/innodb/r/default_row_format_compatibility.result +++ b/mysql-test/suite/innodb/r/default_row_format_compatibility.result @@ -1,3 +1,4 @@ +call mtr.add_suppression("Index for table 'tab' is corrupt; try to repair it"); SET @row_format = @@GLOBAL.innodb_default_row_format; # ########################################################### # Check with Import/Export tablespace with Default_row_format @@ -38,7 +39,7 @@ tab InnoDB # Compact # # # # # # NULL # NULL NULL latin1_swedish_ci NULL 0 N ALTER TABLE tab DISCARD TABLESPACE; call mtr.add_suppression("InnoDB: Tried to read .* bytes at offset 0"); ALTER TABLE tab IMPORT TABLESPACE; -ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`tab` : I/O error +ERROR HY000: Index for table 'tab' is corrupt; try to repair it ALTER TABLE tab IMPORT TABLESPACE; SELECT * FROM tab; a diff --git a/mysql-test/suite/innodb/r/full_crc32_import.result b/mysql-test/suite/innodb/r/full_crc32_import.result index b7f6f1ab09a..6f0daaf0f0f 100644 --- a/mysql-test/suite/innodb/r/full_crc32_import.result +++ b/mysql-test/suite/innodb/r/full_crc32_import.result @@ -46,7 +46,7 @@ t1 CREATE TABLE `t1` ( `b` blob DEFAULT NULL, `c` blob DEFAULT NULL, PRIMARY KEY (`a`) -) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +) ENGINE=InnoDB AUTO_INCREMENT=57 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC UPDATE t1 set b = repeat("de", 100) where b = repeat("cd", 200); explain SELECT a FROM t1 where b = repeat("de", 100); id select_type table type possible_keys key key_len ref rows Extra @@ -126,7 +126,7 @@ t1 CREATE TABLE `t1` ( `c2` point NOT NULL, `c3` linestring NOT NULL, PRIMARY KEY (`c1`) -) ENGINE=InnoDB AUTO_INCREMENT=14325 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +) ENGINE=InnoDB AUTO_INCREMENT=16372 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC UPDATE t1 SET C2 = ST_GeomFromText('POINT(0 0)'); SELECT COUNT(*) FROM t1; COUNT(*) diff --git a/mysql-test/suite/innodb/r/innodb-wl5522-debug.result b/mysql-test/suite/innodb/r/innodb-wl5522-debug.result index 2a08054712c..729f157b076 100644 --- a/mysql-test/suite/innodb/r/innodb-wl5522-debug.result +++ b/mysql-test/suite/innodb/r/innodb-wl5522-debug.result @@ -951,7 +951,7 @@ ERROR HY000: Tablespace has been discarded for table `t1` restore: t1 .ibd and .cfg files SET SESSION debug_dbug="+d,fsp_flags_is_valid_failure"; ALTER TABLE t1 IMPORT TABLESPACE; -ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`t1` : Data structure corruption +ERROR HY000: Index for table 't1' is corrupt; try to repair it SET SESSION debug_dbug=@saved_debug_dbug; DROP TABLE t1; unlink: t1.ibd diff --git a/mysql-test/suite/innodb/r/instant_alter_import.result b/mysql-test/suite/innodb/r/instant_alter_import.result index 008a26ea6af..c31e9c8e656 100644 --- a/mysql-test/suite/innodb/r/instant_alter_import.result +++ b/mysql-test/suite/innodb/r/instant_alter_import.result @@ -61,13 +61,10 @@ alter table t1 discard tablespace; flush tables t2 for export; unlock tables; alter table t1 import tablespace; -ERROR HY000: Schema mismatch (Index field count 4 doesn't match tablespace metadata file value 5) select * from t1; -ERROR HY000: Tablespace has been discarded for table `t1` -alter table t1 import tablespace; -ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`t1` : Unsupported -select * from t1; -ERROR HY000: Tablespace has been discarded for table `t1` +z +42 +41 drop table t2; drop table t1; CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT, i1 INT) ENGINE=INNODB; @@ -78,3 +75,46 @@ FLUSH TABLE t1 FOR EXPORT; UNLOCK TABLES; ALTER TABLE t2 IMPORT TABLESPACE; DROP TABLE t2, t1; +CREATE TABLE t1 (id INT PRIMARY KEY, i2 INT, i1 INT) ENGINE=INNODB; +INSERT INTO t1 VALUES (1, 1, 1); +ALTER TABLE t1 MODIFY COLUMN i2 INT AFTER i1, ALGORITHM=INSTANT; +CREATE TABLE t2 LIKE t1; +ALTER TABLE t2 DISCARD TABLESPACE; +FLUSH TABLE t1 FOR EXPORT; +UNLOCK TABLES; +ALTER TABLE t2 IMPORT TABLESPACE; +SELECT * FROM t2; +id i1 i2 +1 1 1 +DROP TABLE t2, t1; +CREATE TABLE t1 (id INT PRIMARY KEY, i2 INT, i1 INT) ENGINE=INNODB; +INSERT INTO t1 VALUES (1, 1, 1); +ALTER TABLE t1 DROP COLUMN i2, ALGORITHM=INSTANT; +CREATE TABLE t2 LIKE t1; +ALTER TABLE t2 DISCARD TABLESPACE; +FLUSH TABLE t1 FOR EXPORT; +UNLOCK TABLES; +ALTER TABLE t2 IMPORT TABLESPACE; +SELECT * FROM t2; +id i1 +1 1 +DROP TABLE t2, t1; +CREATE TABLE t1 (id INT PRIMARY KEY, i2 INT, i1 INT) +ENGINE=INNODB PAGE_COMPRESSED=1; +INSERT INTO t1 VALUES (1, 1, 1); +ALTER TABLE t1 DROP COLUMN i2, ALGORITHM=INSTANT; +CREATE TABLE t2 LIKE t1; +ALTER TABLE t2 DISCARD TABLESPACE; +FLUSH TABLE t1 FOR EXPORT; +UNLOCK TABLES; +ALTER TABLE t2 IMPORT TABLESPACE; +DROP TABLE t2, t1; +CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT, i2 INT, i1 INT) ENGINE=INNODB; +INSERT INTO t1 (i2) SELECT 4 FROM seq_1_to_1024; +ALTER TABLE t1 DROP COLUMN i2, ALGORITHM=INSTANT; +CREATE TABLE t2 LIKE t1; +ALTER TABLE t2 DISCARD TABLESPACE; +FLUSH TABLE t1 FOR EXPORT; +UNLOCK TABLES; +ALTER TABLE t2 IMPORT TABLESPACE; +DROP TABLE t2, t1; diff --git a/mysql-test/suite/innodb/t/default_row_format_compatibility.test b/mysql-test/suite/innodb/t/default_row_format_compatibility.test index 3dea78b2ff0..0868974c9df 100644 --- a/mysql-test/suite/innodb/t/default_row_format_compatibility.test +++ b/mysql-test/suite/innodb/t/default_row_format_compatibility.test @@ -1,5 +1,8 @@ --source include/have_innodb.inc +call mtr.add_suppression("Index for table 'tab' is corrupt; try to repair it"); + + SET @row_format = @@GLOBAL.innodb_default_row_format; # set the variables @@ -79,7 +82,7 @@ ALTER TABLE tab DISCARD TABLESPACE; call mtr.add_suppression("InnoDB: Tried to read .* bytes at offset 0"); ---error ER_INTERNAL_ERROR +--error ER_NOT_KEYFILE ALTER TABLE tab IMPORT TABLESPACE; --remove_file $MYSQLD_DATADIR/test/tab.ibd --move_file $MYSQLD_DATADIR/tab.ibd $MYSQLD_DATADIR/test/tab.ibd diff --git a/mysql-test/suite/innodb/t/innodb-wl5522-debug.test b/mysql-test/suite/innodb/t/innodb-wl5522-debug.test index 7159b164065..79ea4753904 100644 --- a/mysql-test/suite/innodb/t/innodb-wl5522-debug.test +++ b/mysql-test/suite/innodb/t/innodb-wl5522-debug.test @@ -1375,7 +1375,7 @@ SET SESSION debug_dbug="+d,fsp_flags_is_valid_failure"; --replace_regex /'.*t1.cfg'/'t1.cfg'/ ---error ER_INTERNAL_ERROR +--error ER_NOT_KEYFILE ALTER TABLE t1 IMPORT TABLESPACE; SET SESSION debug_dbug=@saved_debug_dbug; diff --git a/mysql-test/suite/innodb/t/instant_alter_import.test b/mysql-test/suite/innodb/t/instant_alter_import.test index d01f4325f1e..4bec3f8b7f5 100644 --- a/mysql-test/suite/innodb/t/instant_alter_import.test +++ b/mysql-test/suite/innodb/t/instant_alter_import.test @@ -1,4 +1,7 @@ --source include/have_innodb.inc +--source include/have_sequence.inc +--source include/innodb_checksum_algorithm.inc + set default_storage_engine=innodb; --echo # @@ -70,14 +73,7 @@ flush tables t2 for export; --copy_file $MYSQLD_DATADIR/test/t2.ibd $MYSQLD_DATADIR/test/t1.ibd unlock tables; ---error ER_TABLE_SCHEMA_MISMATCH alter table t1 import tablespace; ---error ER_TABLESPACE_DISCARDED -select * from t1; ---remove_file $MYSQLD_DATADIR/test/t1.cfg ---error ER_INTERNAL_ERROR -alter table t1 import tablespace; ---error ER_TABLESPACE_DISCARDED select * from t1; drop table t2; @@ -101,3 +97,86 @@ UNLOCK TABLES; ALTER TABLE t2 IMPORT TABLESPACE; DROP TABLE t2, t1; + + +CREATE TABLE t1 (id INT PRIMARY KEY, i2 INT, i1 INT) ENGINE=INNODB; + +INSERT INTO t1 VALUES (1, 1, 1); +ALTER TABLE t1 MODIFY COLUMN i2 INT AFTER i1, ALGORITHM=INSTANT; + +CREATE TABLE t2 LIKE t1; +ALTER TABLE t2 DISCARD TABLESPACE; + + +FLUSH TABLE t1 FOR EXPORT; + +--copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd +--copy_file $MYSQLD_DATADIR/test/t1.cfg $MYSQLD_DATADIR/test/t2.cfg + +UNLOCK TABLES; +ALTER TABLE t2 IMPORT TABLESPACE; + +SELECT * FROM t2; + +DROP TABLE t2, t1; + + +CREATE TABLE t1 (id INT PRIMARY KEY, i2 INT, i1 INT) ENGINE=INNODB; + +INSERT INTO t1 VALUES (1, 1, 1); +ALTER TABLE t1 DROP COLUMN i2, ALGORITHM=INSTANT; + +CREATE TABLE t2 LIKE t1; +ALTER TABLE t2 DISCARD TABLESPACE; + + +FLUSH TABLE t1 FOR EXPORT; + +--copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd +--copy_file $MYSQLD_DATADIR/test/t1.cfg $MYSQLD_DATADIR/test/t2.cfg + +UNLOCK TABLES; +ALTER TABLE t2 IMPORT TABLESPACE; + +SELECT * FROM t2; + +DROP TABLE t2, t1; + + +CREATE TABLE t1 (id INT PRIMARY KEY, i2 INT, i1 INT) + ENGINE=INNODB PAGE_COMPRESSED=1; + +INSERT INTO t1 VALUES (1, 1, 1); +ALTER TABLE t1 DROP COLUMN i2, ALGORITHM=INSTANT; + +CREATE TABLE t2 LIKE t1; +ALTER TABLE t2 DISCARD TABLESPACE; + +FLUSH TABLE t1 FOR EXPORT; + +--copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd +--copy_file $MYSQLD_DATADIR/test/t1.cfg $MYSQLD_DATADIR/test/t2.cfg + +UNLOCK TABLES; +ALTER TABLE t2 IMPORT TABLESPACE; + +DROP TABLE t2, t1; + + +CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT, i2 INT, i1 INT) ENGINE=INNODB; + +INSERT INTO t1 (i2) SELECT 4 FROM seq_1_to_1024; +ALTER TABLE t1 DROP COLUMN i2, ALGORITHM=INSTANT; + +CREATE TABLE t2 LIKE t1; +ALTER TABLE t2 DISCARD TABLESPACE; + +FLUSH TABLE t1 FOR EXPORT; + +--copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd +--copy_file $MYSQLD_DATADIR/test/t1.cfg $MYSQLD_DATADIR/test/t2.cfg + +UNLOCK TABLES; +ALTER TABLE t2 IMPORT TABLESPACE; + +DROP TABLE t2, t1; diff --git a/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result b/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result index 02593bcd7d3..927cc0aefcb 100644 --- a/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result +++ b/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result @@ -407,7 +407,7 @@ ERROR HY000: Tablespace has been discarded for table `t1` restore: t1 .ibd and .cfg files SET SESSION debug_dbug="+d,fsp_flags_is_valid_failure"; ALTER TABLE t1 IMPORT TABLESPACE; -ERROR HY000: Internal error: Cannot reset LSNs in table `test`.`t1` : Data structure corruption +ERROR HY000: Index for table 't1' is corrupt; try to repair it SET SESSION debug_dbug=@saved_debug_dbug; DROP TABLE t1; unlink: t1.ibd diff --git a/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test b/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test index a060acc19a9..9cab7733481 100644 --- a/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test +++ b/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test @@ -624,7 +624,7 @@ EOF SET SESSION debug_dbug="+d,fsp_flags_is_valid_failure"; ---error ER_INTERNAL_ERROR +--error ER_NOT_KEYFILE ALTER TABLE t1 IMPORT TABLESPACE; SET SESSION debug_dbug=@saved_debug_dbug; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 5bbdee683bb..9c8a1e1f350 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -13117,25 +13117,6 @@ ha_innobase::discard_or_import_tablespace( err, m_prebuilt->table->flags, NULL)); } - /* Evict and reload the table definition in order to invoke - btr_cur_instant_init(). */ - table_id_t id = m_prebuilt->table->id; - ut_ad(id); - mutex_enter(&dict_sys.mutex); - dict_table_close(m_prebuilt->table, TRUE, FALSE); - dict_sys.remove(m_prebuilt->table); - m_prebuilt->table = dict_table_open_on_id(id, TRUE, - DICT_TABLE_OP_NORMAL); - mutex_exit(&dict_sys.mutex); - if (!m_prebuilt->table) { - err = DB_TABLE_NOT_FOUND; - } else { - if (const Field* ai = table->found_next_number_field) { - initialize_auto_increment(m_prebuilt->table, ai); - } - dict_stats_init(m_prebuilt->table); - } - if (dict_stats_is_persistent_enabled(m_prebuilt->table)) { dberr_t ret; diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 418b6daabc1..604ec51fced 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -316,6 +316,18 @@ public: static bool full_crc32(ulint flags) { return flags & FSP_FLAGS_FCRC32_MASK_MARKER; } + /** Determine if full_crc32 is used along with compression */ + static bool is_full_crc32_compressed(ulint flags) + { + if (full_crc32(flags)) + { + ulint algo= FSP_FLAGS_FCRC32_GET_COMPRESSED_ALGO(flags); + DBUG_ASSERT(algo <= PAGE_ALGORITHM_LAST); + return algo > 0; + } + + return false; + } /** @return whether innodb_checksum_algorithm=full_crc32 is active */ bool full_crc32() const { return full_crc32(flags); } /** Determine the logical page size. @@ -377,19 +389,13 @@ public: unsigned zip_size() const { return zip_size(flags); } /** @return the physical page size */ unsigned physical_size() const { return physical_size(flags); } - /** Check whether the compression enabled in tablespace. - @param[in] flags tablespace flags */ - static bool is_compressed(ulint flags) { - - if (full_crc32(flags)) { - ulint algo = FSP_FLAGS_FCRC32_GET_COMPRESSED_ALGO( - flags); - DBUG_ASSERT(algo <= PAGE_ALGORITHM_LAST); - return algo > 0; - } - - return FSP_FLAGS_HAS_PAGE_COMPRESSION(flags); - } + /** Check whether the compression enabled in tablespace. + @param[in] flags tablespace flags */ + static bool is_compressed(ulint flags) + { + return is_full_crc32_compressed(flags) + || FSP_FLAGS_HAS_PAGE_COMPRESSION(flags); + } /** @return whether the compression enabled for the tablespace. */ bool is_compressed() const { return is_compressed(flags); } diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index a774143200a..aaa3b381b23 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -40,6 +40,7 @@ Created 2012-02-08 by Sunny Bains. #include "row0quiesce.h" #include "fil0pagecompress.h" #include "trx0undo.h" +#include "row0row.h" #ifdef HAVE_LZO #include "lzo/lzo1x.h" #endif @@ -47,6 +48,8 @@ Created 2012-02-08 by Sunny Bains. #include "snappy-c.h" #endif +#include "scope.h" + #include #ifdef HAVE_MY_AES_H @@ -190,6 +193,9 @@ struct row_import { dberr_t match_schema( THD* thd) UNIV_NOTHROW; + dberr_t match_flags(THD *thd) const ; + + dict_table_t* m_table; /*!< Table instance */ ulint m_version; /*!< Version of config file */ @@ -575,8 +581,6 @@ AbstractCallback::init( if (!fil_space_t::is_valid_flags(m_space_flags, true)) { ulint cflags = fsp_flags_convert_from_101(m_space_flags); if (cflags == ULINT_UNDEFINED) { - ib::error() << "Invalid FSP_SPACE_FLAGS=" - << ib::hex(m_space_flags); return(DB_CORRUPTION); } m_space_flags = cflags; @@ -1103,7 +1107,8 @@ row_import::match_index_columns( for (ulint i = 0; i < index->n_fields; ++i, ++field, ++cfg_field) { - if (strcmp(field->name(), cfg_field->name()) != 0) { + if (field->name() && cfg_field->name() + && strcmp(field->name(), cfg_field->name()) != 0) { ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, "Index field name %s doesn't match" @@ -1272,6 +1277,61 @@ row_import::match_table_columns( return(err); } +dberr_t row_import::match_flags(THD *thd) const +{ + ulint mismatch= (m_table->flags ^ m_flags) & ~DICT_TF_MASK_DATA_DIR; + if (!mismatch) + return DB_SUCCESS; + + const char *msg; + if (mismatch & DICT_TF_MASK_ZIP_SSIZE) + { + if ((m_table->flags & DICT_TF_MASK_ZIP_SSIZE) && + (m_flags & DICT_TF_MASK_ZIP_SSIZE)) + { + switch (m_flags & DICT_TF_MASK_ZIP_SSIZE) { + case 0U << DICT_TF_POS_ZIP_SSIZE: + goto uncompressed; + case 1U << DICT_TF_POS_ZIP_SSIZE: + msg= "ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1"; + break; + case 2U << DICT_TF_POS_ZIP_SSIZE: + msg= "ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2"; + break; + case 3U << DICT_TF_POS_ZIP_SSIZE: + msg= "ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4"; + break; + case 4U << DICT_TF_POS_ZIP_SSIZE: + msg= "ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8"; + break; + case 5U << DICT_TF_POS_ZIP_SSIZE: + msg= "ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=16"; + break; + default: + msg= "strange KEY_BLOCK_SIZE"; + } + } + else if (m_flags & DICT_TF_MASK_ZIP_SSIZE) + msg= "ROW_FORMAT=COMPRESSED"; + else + goto uncompressed; + } + else + { + uncompressed: + msg= (m_flags & DICT_TF_MASK_ATOMIC_BLOBS) ? "ROW_FORMAT=DYNAMIC" + : (m_flags & DICT_TF_MASK_COMPACT) ? "ROW_FORMAT=COMPACT" + : "ROW_FORMAT=REDUNDANT"; + } + + ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, + "Table flags don't match, server table has 0x%x and the meta-data " + "file has 0x%zx; .cfg file uses %s", + m_table->flags, m_flags, msg); + + return DB_ERROR; +} + /** Check if the table (and index) schema that was read from the .cfg file matches the in memory table definition. @param thd MySQL session variable @@ -1282,60 +1342,7 @@ row_import::match_schema( { /* Do some simple checks. */ - if (ulint mismatch = (m_table->flags ^ m_flags) - & ~DICT_TF_MASK_DATA_DIR) { - const char* msg; - if (mismatch & DICT_TF_MASK_ZIP_SSIZE) { - if ((m_table->flags & DICT_TF_MASK_ZIP_SSIZE) - && (m_flags & DICT_TF_MASK_ZIP_SSIZE)) { - switch (m_flags & DICT_TF_MASK_ZIP_SSIZE) { - case 0U << DICT_TF_POS_ZIP_SSIZE: - goto uncompressed; - case 1U << DICT_TF_POS_ZIP_SSIZE: - msg = "ROW_FORMAT=COMPRESSED" - " KEY_BLOCK_SIZE=1"; - break; - case 2U << DICT_TF_POS_ZIP_SSIZE: - msg = "ROW_FORMAT=COMPRESSED" - " KEY_BLOCK_SIZE=2"; - break; - case 3U << DICT_TF_POS_ZIP_SSIZE: - msg = "ROW_FORMAT=COMPRESSED" - " KEY_BLOCK_SIZE=4"; - break; - case 4U << DICT_TF_POS_ZIP_SSIZE: - msg = "ROW_FORMAT=COMPRESSED" - " KEY_BLOCK_SIZE=8"; - break; - case 5U << DICT_TF_POS_ZIP_SSIZE: - msg = "ROW_FORMAT=COMPRESSED" - " KEY_BLOCK_SIZE=16"; - break; - default: - msg = "strange KEY_BLOCK_SIZE"; - } - } else if (m_flags & DICT_TF_MASK_ZIP_SSIZE) { - msg = "ROW_FORMAT=COMPRESSED"; - } else { - goto uncompressed; - } - } else { -uncompressed: - msg = (m_flags & DICT_TF_MASK_ATOMIC_BLOBS) - ? "ROW_FORMAT=DYNAMIC" - : (m_flags & DICT_TF_MASK_COMPACT) - ? "ROW_FORMAT=COMPACT" - : "ROW_FORMAT=REDUNDANT"; - } - - ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, - "Table flags don't match, server table has 0x%x" - " and the meta-data file has 0x" ULINTPFx ";" - " .cfg file uses %s", - m_table->flags, m_flags, msg); - - return(DB_ERROR); - } else if (m_table->n_cols != m_n_cols) { + if (m_table->n_cols != m_n_cols) { ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, "Number of columns don't match, table has %u " "columns but the tablespace meta-data file has " @@ -1957,40 +1964,7 @@ PageConverter::update_index_page( if (dict_index_is_clust(m_index->m_srv_index)) { dict_index_t* index = const_cast( m_index->m_srv_index); - if (block->page.id.page_no() == index->page) { - /* Preserve the PAGE_ROOT_AUTO_INC. */ - if (index->table->supports_instant()) { - if (btr_cur_instant_root_init(index, page)) { - return(DB_CORRUPTION); - } - - if (index->n_core_fields > index->n_fields) { - /* Some columns have been dropped. - Refuse to IMPORT TABLESPACE for now. - - NOTE: This is not an accurate check. - Columns could have been both - added and dropped instantly. - For an accurate check, we must read - the metadata BLOB page pointed to - by the leftmost leaf page. - - But we would have to read - those pages in a special way, - bypassing the buffer pool! */ - return DB_UNSUPPORTED; - } - - /* Provisionally set all instantly - added columns to be DEFAULT NULL. */ - for (unsigned i = index->n_core_fields; - i < index->n_fields; i++) { - dict_col_t* col = index->fields[i].col; - col->def_val.len = UNIV_SQL_NULL; - col->def_val.data = NULL; - } - } - } else { + if (block->page.id.page_no() != index->page) { /* Clear PAGE_MAX_TRX_ID so that it can be used for other purposes in the future. IMPORT in MySQL 5.6, 5.7 and MariaDB 10.0 and 10.1 @@ -3131,6 +3105,371 @@ row_import_read_meta_data( return(DB_ERROR); } +#define BTR_BLOB_HDR_PART_LEN 0 /*!< BLOB part len on this page */ +#define BTR_BLOB_HDR_NEXT_PAGE_NO 4 /*!< next BLOB part page no, + FIL_NULL if none */ +#define BTR_BLOB_HDR_SIZE 8 /*!< Size of a BLOB part header, in bytes */ + +/* decrypt and decompress page if needed */ +static dberr_t decrypt_decompress(fil_space_crypt_t *space_crypt, + size_t space_flags, span page, + size_t space_id, byte *page_compress_buf) +{ + auto *data= page.data(); + + if (space_crypt && space_crypt->should_encrypt()) + { + if (!buf_page_verify_crypt_checksum(data, space_flags)) + return DB_CORRUPTION; + + dberr_t err; + if (!fil_space_decrypt(space_id, space_crypt, data, page.size(), + space_flags, data, &err)) + return err ? err : DB_CORRUPTION; + } + else if (fil_page_is_compressed_encrypted(data)) + return DB_CORRUPTION; + + const bool is_full_crc32_compressed= + fil_space_t::is_full_crc32_compressed(space_flags); + + const bool page_actually_compressed= + (is_full_crc32_compressed && + buf_page_is_compressed(data, space_flags)) || + fil_page_is_compressed_encrypted(data) || fil_page_is_compressed(data); + + if (page_actually_compressed) + { + if (!is_full_crc32_compressed && !fil_space_t::is_compressed(space_flags)) + return DB_CORRUPTION; + + auto compress_length= + fil_page_decompress(page_compress_buf, data, space_flags); + ut_ad(compress_length != srv_page_size); + + if (compress_length == 0) + return DB_CORRUPTION; + } + + return DB_SUCCESS; +} + +static size_t get_buf_size() +{ + return srv_page_size +#ifdef HAVE_LZO + + LZO1X_1_15_MEM_COMPRESS +#elif defined HAVE_SNAPPY + + snappy_max_compressed_length(srv_page_size) +#endif + ; +} + +/* find, parse instant metadata, performing variaous checks, +and apply it to dict_table_t +@return DB_SUCCESS or some error */ +static dberr_t handle_instant_metadata(dict_table_t *table, + const row_import &cfg) +{ + dict_get_and_save_data_dir_path(table, false); + + char *filepath; + if (DICT_TF_HAS_DATA_DIR(table->flags)) + { + ut_a(table->data_dir_path); + + filepath= + fil_make_filepath(table->data_dir_path, table->name.m_name, IBD, true); + } + else + filepath= fil_make_filepath(nullptr, table->name.m_name, IBD, false); + + if (!filepath) + return DB_OUT_OF_MEMORY; + + SCOPE_EXIT([filepath]() { ut_free(filepath); }); + + bool success; + auto file= os_file_create_simple_no_error_handling( + innodb_data_file_key, filepath, OS_FILE_OPEN, OS_FILE_READ_WRITE, false, + &success); + if (!success) + return DB_IO_ERROR; + + if (os_file_get_size(file) < srv_page_size * 4) + return DB_CORRUPTION; + + SCOPE_EXIT([&file]() { os_file_close(file); }); + + std::unique_ptr first_page( + static_cast(aligned_malloc(srv_page_size, srv_page_size)), + &aligned_free); + + if (dberr_t err= os_file_read_no_error_handling(IORequest(IORequest::READ), + file, first_page.get(), 0, + srv_page_size, nullptr)) + return err; + + auto space_flags= fsp_header_get_flags(first_page.get()); + + if (!fil_space_t::is_valid_flags(space_flags, true)) + { + auto cflags= fsp_flags_convert_from_101(space_flags); + if (cflags == ULINT_UNDEFINED) + { + ib::error() << "Invalid FSP_SPACE_FLAGS=" << ib::hex(space_flags); + return DB_CORRUPTION; + } + space_flags= cflags; + } + + if (!cfg.m_missing) + { + if (dberr_t err= cfg.match_flags(current_thd)) + return err; + } + + const auto zip_size= fil_space_t::zip_size(space_flags); + const uint64_t physical_size= zip_size ? zip_size : srv_page_size; + ut_ad(physical_size <= UNIV_PAGE_SIZE_MAX); + const auto space_id= page_get_space_id(first_page.get()); + + auto *space_crypt= fil_space_read_crypt_data(zip_size, first_page.get()); + SCOPE_EXIT([&space_crypt]() { + if (space_crypt) + fil_space_destroy_crypt_data(&space_crypt); + }); + + std::unique_ptr page( + static_cast( + aligned_malloc(UNIV_PAGE_SIZE_MAX, UNIV_PAGE_SIZE_MAX)), + &aligned_free); + + if (dberr_t err= os_file_read_no_error_handling( + IORequest(IORequest::READ), file, page.get(), 3 * physical_size, + physical_size, nullptr)) + return err; + + std::unique_ptr page_compress_buf(new byte[get_buf_size()]); + + if (dberr_t err= + decrypt_decompress(space_crypt, space_flags, + {page.get(), static_cast(physical_size)}, + space_id, page_compress_buf.get())) + return err; + + if (table->supports_instant()) + { + dict_index_t *index= dict_table_get_first_index(table); + + auto tmp1= table->space_id; + table->space_id= page_get_space_id(page.get()); + SCOPE_EXIT([tmp1, table]() { table->space_id= tmp1; }); + + auto tmp2= index->page; + index->page= page_get_page_no(page.get()); + SCOPE_EXIT([tmp2, index]() { index->page= tmp2; }); + + if (!page_is_comp(page.get()) != !dict_table_is_comp(table)) + { + ib_errf(current_thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, + "ROW_FORMAT mismatch"); + return DB_CORRUPTION; + } + + if (btr_cur_instant_root_init(index, page.get())) + return DB_ERROR; + + ut_ad(index->n_core_null_bytes != dict_index_t::NO_CORE_NULL_BYTES); + + if (fil_page_get_type(page.get()) == FIL_PAGE_INDEX) + { + ut_ad(!index->is_instant()); + return DB_SUCCESS; + } + + mem_heap_t *heap= NULL; + SCOPE_EXIT([&heap]() { mem_heap_free(heap); }); + + while (btr_page_get_level(page.get()) != 0) + { + const rec_t *rec= page_rec_get_next(page_get_infimum_rec(page.get())); + + /* Relax the assertion in rec_init_offsets(). */ + ut_ad(!index->in_instant_init); + ut_d(index->in_instant_init= true); + rec_offs *offsets= + rec_get_offsets(rec, index, nullptr, 0, ULINT_UNDEFINED, &heap); + ut_d(index->in_instant_init= false); + + uint64_t child_page_no= btr_node_ptr_get_child_page_no(rec, offsets); + + if (dberr_t err= os_file_read_no_error_handling( + IORequest(IORequest::READ), file, page.get(), + child_page_no * physical_size, physical_size, nullptr)) + return err; + + if (dberr_t err= decrypt_decompress( + space_crypt, space_flags, + {page.get(), static_cast(physical_size)}, space_id, + page_compress_buf.get())) + return err; + } + + const auto *rec= page_rec_get_next(page_get_infimum_rec(page.get())); + const auto comp= dict_table_is_comp(index->table); + const auto info_bits= rec_get_info_bits(rec, comp); + + if (page_rec_is_supremum(rec) || !(info_bits & REC_INFO_MIN_REC_FLAG)) + { + ib::error() << "Table " << index->table->name + << " is missing instant ALTER metadata"; + index->table->corrupted= true; + return DB_CORRUPTION; + } + + if ((info_bits & ~REC_INFO_DELETED_FLAG) != REC_INFO_MIN_REC_FLAG || + (comp && rec_get_status(rec) != REC_STATUS_INSTANT)) + { + incompatible: + ib::error() << "Table " << index->table->name + << " contains unrecognizable instant ALTER metadata"; + index->table->corrupted= true; + return DB_CORRUPTION; + } + + if (info_bits & REC_INFO_DELETED_FLAG) + { + ulint trx_id_offset= index->trx_id_offset; + ut_ad(index->n_uniq); + + if (trx_id_offset) + { + } + else if (index->table->not_redundant()) + { + + for (uint i= index->n_uniq; i--;) + trx_id_offset+= index->fields[i].fixed_len; + } + else if (rec_get_1byte_offs_flag(rec)) + { + trx_id_offset= rec_1_get_field_end_info(rec, index->n_uniq - 1); + ut_ad(!(trx_id_offset & REC_1BYTE_SQL_NULL_MASK)); + trx_id_offset&= ~REC_1BYTE_SQL_NULL_MASK; + } + else + { + trx_id_offset= rec_2_get_field_end_info(rec, index->n_uniq - 1); + ut_ad(!(trx_id_offset & REC_2BYTE_SQL_NULL_MASK)); + trx_id_offset&= ~REC_2BYTE_SQL_NULL_MASK; + } + + const byte *ptr= + rec + trx_id_offset + (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN); + + if (mach_read_from_4(ptr + BTR_EXTERN_LEN)) + goto incompatible; + + uint len= mach_read_from_4(ptr + BTR_EXTERN_LEN + 4); + if (!len || mach_read_from_4(ptr + BTR_EXTERN_OFFSET) != FIL_PAGE_DATA) + goto incompatible; + + std::unique_ptr second_page( + static_cast(aligned_malloc(physical_size, physical_size)), + &aligned_free); + + if (dberr_t err= os_file_read_no_error_handling( + IORequest(IORequest::READ), file, second_page.get(), + mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO) * physical_size, + srv_page_size, nullptr)) + return err; + + if (dberr_t err= decrypt_decompress( + space_crypt, space_flags, + {second_page.get(), static_cast(physical_size)}, + space_id, page_compress_buf.get())) + return err; + + if (fil_page_get_type(second_page.get()) != FIL_PAGE_TYPE_BLOB || + mach_read_from_4( + &second_page[FIL_PAGE_DATA + BTR_BLOB_HDR_NEXT_PAGE_NO]) != + FIL_NULL || + mach_read_from_4( + &second_page[FIL_PAGE_DATA + BTR_BLOB_HDR_PART_LEN]) != len) + goto incompatible; + + /* The unused part of the BLOB page should be zero-filled. */ + for (const byte * + b= second_page.get() + (FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE) + + len, + *const end= second_page.get() + srv_page_size - BTR_EXTERN_LEN; + b < end;) + { + if (*b++) + goto incompatible; + } + + if (index->table->deserialise_columns( + &second_page[FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE], len)) + goto incompatible; + } + + rec_offs *offsets= rec_get_offsets( + rec, index, nullptr, index->n_core_fields, ULINT_UNDEFINED, &heap); + if (rec_offs_any_default(offsets)) + { + inconsistent: + goto incompatible; + } + + /* In fact, because we only ever append fields to the metadata + record, it is also OK to perform READ UNCOMMITTED and + then ignore any extra fields, provided that + trx_sys.is_registered(DB_TRX_ID). */ + if (rec_offs_n_fields(offsets) > + ulint(index->n_fields) + !!index->table->instant && + !trx_sys.is_registered(current_trx(), + row_get_rec_trx_id(rec, index, offsets))) + goto inconsistent; + + for (unsigned i= index->n_core_fields; i < index->n_fields; i++) + { + dict_col_t *col= index->fields[i].col; + const unsigned o= i + !!index->table->instant; + ulint len; + const byte *data= rec_get_nth_field(rec, offsets, o, &len); + ut_ad(!col->is_added()); + ut_ad(!col->def_val.data); + col->def_val.len= len; + switch (len) { + case UNIV_SQL_NULL: + continue; + case 0: + col->def_val.data= field_ref_zero; + continue; + } + ut_ad(len != UNIV_SQL_DEFAULT); + if (!rec_offs_nth_extern(offsets, o)) + col->def_val.data= mem_heap_dup(index->table->heap, data, len); + else if (len < BTR_EXTERN_FIELD_REF_SIZE || + !memcmp(data + len - BTR_EXTERN_FIELD_REF_SIZE, field_ref_zero, + BTR_EXTERN_FIELD_REF_SIZE)) + { + col->def_val.len= UNIV_SQL_DEFAULT; + goto inconsistent; + } + else + { + col->def_val.data= btr_copy_externally_stored_field( + &col->def_val.len, data, srv_page_size, len, index->table->heap); + } + } + } + + return DB_SUCCESS; +} + /** Read the contents of the .cfg file. @return DB_SUCCESS or error code. */ @@ -3441,14 +3780,7 @@ dberr_t FetchIndexRootPages::run(const fil_iterator_t& iter, { const unsigned zip_size= fil_space_t::zip_size(m_space_flags); const unsigned size= zip_size ? zip_size : unsigned(srv_page_size); - const ulint buf_size= -#ifdef HAVE_LZO - LZO1X_1_15_MEM_COMPRESS+ -#elif defined HAVE_SNAPPY - snappy_max_compressed_length(srv_page_size) + -#endif - srv_page_size; - byte* page_compress_buf = static_cast(malloc(buf_size)); + byte* page_compress_buf= static_cast(malloc(get_buf_size())); const bool full_crc32 = fil_space_t::full_crc32(m_space_flags); bool skip_checksum_check = false; ut_ad(!srv_read_only_mode); @@ -3541,14 +3873,7 @@ static dberr_t fil_iterate( const ulint size = callback.physical_size(); ulint n_bytes = iter.n_io_buffers * size; - const ulint buf_size = srv_page_size -#ifdef HAVE_LZO - + LZO1X_1_15_MEM_COMPRESS -#elif defined HAVE_SNAPPY - + snappy_max_compressed_length(srv_page_size) -#endif - ; - byte* page_compress_buf = static_cast(malloc(buf_size)); + byte* page_compress_buf= static_cast(malloc(get_buf_size())); ut_ad(!srv_read_only_mode); if (!page_compress_buf) { @@ -4122,6 +4447,11 @@ row_import_for_mysql( if (err == DB_SUCCESS) { + if (dberr_t err = handle_instant_metadata(table, cfg)) { + rw_lock_s_unlock(&dict_sys.latch); + return row_import_error(prebuilt, trx, err); + } + /* We have a schema file, try and match it with our data dictionary. */ @@ -4179,6 +4509,15 @@ row_import_for_mysql( if (err == DB_SUCCESS) { err = cfg.set_root_by_heuristic(); + + if (err == DB_SUCCESS) { + if (dberr_t err = + handle_instant_metadata(table, + cfg)) { + return row_import_error( + prebuilt, trx, err); + } + } } } From e97b785d764f85009412947600195001be01a706 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 22 Oct 2021 18:41:35 +0400 Subject: [PATCH 7/8] MDEV-22380: Assertion `name.length == strlen(name.str)' failed ... Also fixes: MDEV-25399 Assertion `name.length == strlen(name.str)' failed in Item_func_sp::make_send_field Also fixes a problem that in this scenario: SET NAMES binary; SELECT 'some not well-formed utf8 string'; the auto-generated column name copied the binary string value directly to the Item name, without checking utf8 well-formedness. After this change auto-generated column names work as follows: - Zero bytes 0x00 are copied to the name using HEX notation - In case of "SET NAMES binary", all bytes sequences that do not make well-formed utf8 characters are copied to the name using HEX notation. --- mysql-test/main/alias.result | 151 ++++++++++++++++++ mysql-test/main/alias.test | 83 ++++++++++ mysql-test/main/cast.result | 2 +- mysql-test/main/ctype_big5.result | 2 +- mysql-test/main/ctype_cp932_binlog_stm.result | 2 +- mysql-test/main/ctype_gbk.result | 2 +- mysql-test/main/ctype_latin1.result | 20 +-- mysql-test/main/ctype_sjis.result | 2 +- mysql-test/main/ctype_utf8.result | 8 +- mysql-test/main/ctype_utf8mb4.result | 8 +- mysql-test/main/ctype_utf8mb4_heap.result | 8 +- mysql-test/main/ctype_utf8mb4_innodb.result | 8 +- mysql-test/main/ctype_utf8mb4_myisam.result | 8 +- mysql-test/main/plugin.result | 2 +- sql/item.cc | 96 ++++++++--- 15 files changed, 346 insertions(+), 56 deletions(-) diff --git a/mysql-test/main/alias.result b/mysql-test/main/alias.result index defd44f2548..9ec442bd4db 100644 --- a/mysql-test/main/alias.result +++ b/mysql-test/main/alias.result @@ -218,3 +218,154 @@ DELETE ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 't1 WHERE 1=1' at line 1 connection default; disconnect c1; +# +# MDEV-25399 Assertion `name.length == strlen(name.str)' failed in Item_func_sp::make_send_field +# +SET sql_mode=''; +CREATE FUNCTION f(i INT) RETURNS INT RETURN 1; +PREPARE s FROM "SELECT f('\0')"; +EXECUTE s; +f('\x00') +1 +DROP FUNCTION f; +SET sql_mode=DEFAULT; +# +# MDEV-22380: Assertion `name.length == strlen(name.str)' failed +# in Item::print_item_w_name on SELECT w/ optimizer_trace enabled +# +SELECT '' LIMIT 0; + +CREATE TABLE t1 AS SELECT ''; +ERROR 42000: Incorrect column name '' +CREATE PROCEDURE test_inject(arg TEXT CHARACTER SET latin1) +BEGIN +SET @stmt=CONCAT('SELECT ''', arg, ''', CONCAT(''', arg, ''') LIMIT 0'); +PREPARE stmt FROM @stmt; +EXECUTE stmt; +SET @stmt=CONCAT('CREATE TABLE t1 AS ', @stmt); +PREPARE stmt FROM @stmt; +EXECUTE stmt; +SHOW CREATE TABLE t1; +DROP TABLE t1; +END; +$$ +SELECT x'FF32', CONCAT(x'FF32') LIMIT 0; +x'FF32' CONCAT(x'FF32') +CREATE TABLE t1 AS SELECT x'FF32', CONCAT(x'FF32'); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `x'FF32'` varbinary(2) NOT NULL, + `CONCAT(x'FF32')` varbinary(2) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CALL test_inject(x'FF32'); +ÿ2 CONCAT('ÿ2') +Table Create Table +t1 CREATE TABLE `t1` ( + `ÿ2` varchar(2) NOT NULL, + `CONCAT('ÿ2')` varchar(2) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT x'32FF', CONCAT(x'32FF') LIMIT 0; +x'32FF' CONCAT(x'32FF') +CREATE TABLE t1 AS SELECT x'32FF', CONCAT(x'32FF'); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `x'32FF'` varbinary(2) NOT NULL, + `CONCAT(x'32FF')` varbinary(2) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CALL test_inject(x'32FF'); +2ÿ CONCAT('2ÿ') +Table Create Table +t1 CREATE TABLE `t1` ( + `2ÿ` varchar(2) NOT NULL, + `CONCAT('2ÿ')` varchar(2) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT x'0032', CONCAT(x'0032') LIMIT 0; +x'0032' CONCAT(x'0032') +CREATE TABLE t1 AS SELECT x'0032', CONCAT(x'0032'); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `x'0032'` varbinary(2) NOT NULL, + `CONCAT(x'0032')` varbinary(2) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CALL test_inject(x'0032'); +2 CONCAT('\x002') +Table Create Table +t1 CREATE TABLE `t1` ( + `2` varchar(2) NOT NULL, + `CONCAT('\x002')` varchar(2) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT x'3200', CONCAT(x'3200') LIMIT 0; +x'3200' CONCAT(x'3200') +CREATE TABLE t1 AS SELECT x'3200', CONCAT(x'3200'); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `x'3200'` varbinary(2) NOT NULL, + `CONCAT(x'3200')` varbinary(2) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CALL test_inject(x'3200'); +2\x00 CONCAT('2\x00') +Table Create Table +t1 CREATE TABLE `t1` ( + `2\x00` varchar(2) NOT NULL, + `CONCAT('2\x00')` varchar(2) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT '0\a', CONCAT('0\a') LIMIT 0; +0a CONCAT('0\a') +CREATE TABLE t1 AS SELECT '0\a', CONCAT('0\a'); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `0a` varchar(2) NOT NULL, + `CONCAT('0\a')` varchar(2) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CALL test_inject('0\a'); +0a CONCAT('0a') +Table Create Table +t1 CREATE TABLE `t1` ( + `0a` varchar(2) NOT NULL, + `CONCAT('0a')` varchar(2) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT 'a\0', CONCAT('a\0') LIMIT 0; +a\x00 CONCAT('a\0') +CREATE TABLE t1 AS SELECT 'a\0', CONCAT('a\0'); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a\x00` varchar(2) NOT NULL, + `CONCAT('a\0')` varchar(2) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CALL test_inject('a\0'); +a\x00 CONCAT('a\x00') +Table Create Table +t1 CREATE TABLE `t1` ( + `a\x00` varchar(2) NOT NULL, + `CONCAT('a\x00')` varchar(2) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT 'a\0b', CONCAT('a\0b') LIMIT 0; +a\x00b CONCAT('a\0b') +CREATE TABLE t1 AS SELECT 'a\0b', CONCAT('a\0b'); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a\x00b` varchar(3) NOT NULL, + `CONCAT('a\0b')` varchar(3) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CALL test_inject('a\0b'); +a\x00b CONCAT('a\x00b') +Table Create Table +t1 CREATE TABLE `t1` ( + `a\x00b` varchar(3) NOT NULL, + `CONCAT('a\x00b')` varchar(3) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP PROCEDURE test_inject; diff --git a/mysql-test/main/alias.test b/mysql-test/main/alias.test index c02ebe2f5ff..f6c44accff3 100644 --- a/mysql-test/main/alias.test +++ b/mysql-test/main/alias.test @@ -226,3 +226,86 @@ connection c1; DELETE ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZROM t1 WHERE 1=1; connection default; disconnect c1; + + +--echo # +--echo # MDEV-25399 Assertion `name.length == strlen(name.str)' failed in Item_func_sp::make_send_field +--echo # + +SET sql_mode=''; +CREATE FUNCTION f(i INT) RETURNS INT RETURN 1; +PREPARE s FROM "SELECT f('\0')"; +--disable_warnings +EXECUTE s; +--enable_warnings +DROP FUNCTION f; +SET sql_mode=DEFAULT; + +--echo # +--echo # MDEV-22380: Assertion `name.length == strlen(name.str)' failed +--echo # in Item::print_item_w_name on SELECT w/ optimizer_trace enabled +--echo # + +SELECT '' LIMIT 0; +--error ER_WRONG_COLUMN_NAME +CREATE TABLE t1 AS SELECT ''; + +DELIMITER $$; +CREATE PROCEDURE test_inject(arg TEXT CHARACTER SET latin1) +BEGIN + SET @stmt=CONCAT('SELECT ''', arg, ''', CONCAT(''', arg, ''') LIMIT 0'); + PREPARE stmt FROM @stmt; + EXECUTE stmt; + + SET @stmt=CONCAT('CREATE TABLE t1 AS ', @stmt); + PREPARE stmt FROM @stmt; + EXECUTE stmt; + SHOW CREATE TABLE t1; + DROP TABLE t1; +END; +$$ +DELIMITER ;$$ + +SELECT x'FF32', CONCAT(x'FF32') LIMIT 0; +CREATE TABLE t1 AS SELECT x'FF32', CONCAT(x'FF32'); +SHOW CREATE TABLE t1; +DROP TABLE t1; +CALL test_inject(x'FF32'); + +SELECT x'32FF', CONCAT(x'32FF') LIMIT 0; +CREATE TABLE t1 AS SELECT x'32FF', CONCAT(x'32FF'); +SHOW CREATE TABLE t1; +DROP TABLE t1; +CALL test_inject(x'32FF'); + +SELECT x'0032', CONCAT(x'0032') LIMIT 0; +CREATE TABLE t1 AS SELECT x'0032', CONCAT(x'0032'); +SHOW CREATE TABLE t1; +DROP TABLE t1; +CALL test_inject(x'0032'); + +SELECT x'3200', CONCAT(x'3200') LIMIT 0; +CREATE TABLE t1 AS SELECT x'3200', CONCAT(x'3200'); +SHOW CREATE TABLE t1; +DROP TABLE t1; +CALL test_inject(x'3200'); + +SELECT '0\a', CONCAT('0\a') LIMIT 0; +CREATE TABLE t1 AS SELECT '0\a', CONCAT('0\a'); +SHOW CREATE TABLE t1; +DROP TABLE t1; +CALL test_inject('0\a'); + +SELECT 'a\0', CONCAT('a\0') LIMIT 0; +CREATE TABLE t1 AS SELECT 'a\0', CONCAT('a\0'); +SHOW CREATE TABLE t1; +DROP TABLE t1; +CALL test_inject('a\0'); + +SELECT 'a\0b', CONCAT('a\0b') LIMIT 0; +CREATE TABLE t1 AS SELECT 'a\0b', CONCAT('a\0b'); +SHOW CREATE TABLE t1; +DROP TABLE t1; +CALL test_inject('a\0b'); + +DROP PROCEDURE test_inject; diff --git a/mysql-test/main/cast.result b/mysql-test/main/cast.result index 208fe8d9686..9758ad64d4a 100644 --- a/mysql-test/main/cast.result +++ b/mysql-test/main/cast.result @@ -411,7 +411,7 @@ select cast(_latin1'test' as char character set latin2); cast(_latin1'test' as char character set latin2) test select cast(_koi8r'ÔÅÓÔ' as char character set cp1251); -cast(_koi8r'ÔÅÓÔ' as char character set cp1251) +cast(_koi8r'\xD4\xC5\xD3\xD4' as char character set cp1251) òåñò create table t1 select cast(_koi8r'ÔÅÓÔ' as char character set cp1251) as t; show create table t1; diff --git a/mysql-test/main/ctype_big5.result b/mysql-test/main/ctype_big5.result index 8895e2d89df..14e0d4ac78e 100644 --- a/mysql-test/main/ctype_big5.result +++ b/mysql-test/main/ctype_big5.result @@ -4710,7 +4710,7 @@ SELECT @@character_set_client, @@character_set_connection, @@character_set_resul @@character_set_client @@character_set_connection @@character_set_results binary big5 binary SELECT HEX('à\['), HEX('\à\['); -HEX('à\[') HEX('\à\[') +HEX('\xE0\[') HEX('\\xE0\[') E05B E05B CREATE TABLE t1 AS SELECT REPEAT(' ', 10) AS a LIMIT 0; SHOW CREATE TABLE t1; diff --git a/mysql-test/main/ctype_cp932_binlog_stm.result b/mysql-test/main/ctype_cp932_binlog_stm.result index 089820d628a..c583564f7c2 100644 --- a/mysql-test/main/ctype_cp932_binlog_stm.result +++ b/mysql-test/main/ctype_cp932_binlog_stm.result @@ -20418,7 +20418,7 @@ SELECT @@character_set_client, @@character_set_connection, @@character_set_resul @@character_set_client @@character_set_connection @@character_set_results binary cp932 binary SELECT HEX('à\['), HEX('\à\['); -HEX('à\[') HEX('\à\[') +HEX('\xE0\[') HEX('\\xE0\[') E05B E05B CREATE TABLE t1 AS SELECT REPEAT(' ', 10) AS a LIMIT 0; SHOW CREATE TABLE t1; diff --git a/mysql-test/main/ctype_gbk.result b/mysql-test/main/ctype_gbk.result index 8dcc5e12d0b..bf7928eb2c9 100644 --- a/mysql-test/main/ctype_gbk.result +++ b/mysql-test/main/ctype_gbk.result @@ -5054,7 +5054,7 @@ SELECT @@character_set_client, @@character_set_connection, @@character_set_resul @@character_set_client @@character_set_connection @@character_set_results binary gbk binary SELECT HEX('à\['), HEX('\à\['); -HEX('à\[') HEX('\à\[') +HEX('\xE0\[') HEX('\\xE0\[') E05B E05B CREATE TABLE t1 AS SELECT REPEAT(' ', 10) AS a LIMIT 0; SHOW CREATE TABLE t1; diff --git a/mysql-test/main/ctype_latin1.result b/mysql-test/main/ctype_latin1.result index eee7b4c866a..d4d4423220e 100644 --- a/mysql-test/main/ctype_latin1.result +++ b/mysql-test/main/ctype_latin1.result @@ -7963,37 +7963,37 @@ SELECT ' ? ? SELECT HEX('Â'); -HEX('Â') +HEX('\xC2') 3F SELECT HEX(CAST('Â' AS CHAR CHARACTER SET utf8)); -HEX(CAST('Â' AS CHAR CHARACTER SET utf8)) +HEX(CAST('\xC2' AS CHAR CHARACTER SET utf8)) 3F SELECT HEX(CAST('Â' AS CHAR CHARACTER SET latin1)); -HEX(CAST('Â' AS CHAR CHARACTER SET latin1)) +HEX(CAST('\xC2' AS CHAR CHARACTER SET latin1)) 3F SELECT HEX(CONVERT('Â' USING utf8)); -HEX(CONVERT('Â' USING utf8)) +HEX(CONVERT('\xC2' USING utf8)) 3F SELECT HEX(CONVERT('Â' USING latin1)); -HEX(CONVERT('Â' USING latin1)) +HEX(CONVERT('\xC2' USING latin1)) 3F SELECT 'Âx'; ?x ?x SELECT HEX('Âx'); -HEX('Âx') +HEX('\xC2x') 3F78 SELECT HEX(CAST('Âx' AS CHAR CHARACTER SET utf8)); -HEX(CAST('Âx' AS CHAR CHARACTER SET utf8)) +HEX(CAST('\xC2x' AS CHAR CHARACTER SET utf8)) 3F78 SELECT HEX(CAST('Âx' AS CHAR CHARACTER SET latin1)); -HEX(CAST('Âx' AS CHAR CHARACTER SET latin1)) +HEX(CAST('\xC2x' AS CHAR CHARACTER SET latin1)) 3F78 SELECT HEX(CONVERT('Âx' USING utf8)); -HEX(CONVERT('Âx' USING utf8)) +HEX(CONVERT('\xC2x' USING utf8)) 3F78 SELECT HEX(CONVERT('Âx' USING latin1)); -HEX(CONVERT('Âx' USING latin1)) +HEX(CONVERT('\xC2x' USING latin1)) 3F78 SET NAMES utf8; CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1); diff --git a/mysql-test/main/ctype_sjis.result b/mysql-test/main/ctype_sjis.result index c897268b204..fdb24fdc0e5 100644 --- a/mysql-test/main/ctype_sjis.result +++ b/mysql-test/main/ctype_sjis.result @@ -18682,7 +18682,7 @@ SELECT @@character_set_client, @@character_set_connection, @@character_set_resul @@character_set_client @@character_set_connection @@character_set_results binary sjis binary SELECT HEX('à\['), HEX('\à\['); -HEX('à\[') HEX('\à\[') +HEX('\xE0\[') HEX('\\xE0\[') E05B E05B CREATE TABLE t1 AS SELECT REPEAT(' ', 10) AS a LIMIT 0; SHOW CREATE TABLE t1; diff --git a/mysql-test/main/ctype_utf8.result b/mysql-test/main/ctype_utf8.result index d643ccc0082..3efa008abe8 100644 --- a/mysql-test/main/ctype_utf8.result +++ b/mysql-test/main/ctype_utf8.result @@ -67,13 +67,13 @@ select _utf8 0xD0B0D0B1D0B2 like concat(_utf8'%',_utf8 0xD0B1,_utf8 '%'); _utf8 0xD0B0D0B1D0B2 like concat(_utf8'%',_utf8 0xD0B1,_utf8 '%') 1 select convert(_latin1'Günter André' using utf8) like CONVERT(_latin1'GÜNTER%' USING utf8); -convert(_latin1'Günter André' using utf8) like CONVERT(_latin1'GÜNTER%' USING utf8) +convert(_latin1'G\xFCnter Andr\xE9' using utf8) like CONVERT(_latin1'G\xDCNTER%' USING utf8) 1 select CONVERT(_koi8r'×ÁÓÑ' USING utf8) LIKE CONVERT(_koi8r'÷áóñ' USING utf8); -CONVERT(_koi8r'×ÁÓÑ' USING utf8) LIKE CONVERT(_koi8r'÷áóñ' USING utf8) +CONVERT(_koi8r'\xD7\xC1\xD3\xD1' USING utf8) LIKE CONVERT(_koi8r'\xF7\xE1\xF3\xF1' USING utf8) 1 select CONVERT(_koi8r'÷áóñ' USING utf8) LIKE CONVERT(_koi8r'×ÁÓÑ' USING utf8); -CONVERT(_koi8r'÷áóñ' USING utf8) LIKE CONVERT(_koi8r'×ÁÓÑ' USING utf8) +CONVERT(_koi8r'\xF7\xE1\xF3\xF1' USING utf8) LIKE CONVERT(_koi8r'\xD7\xC1\xD3\xD1' USING utf8) 1 SELECT 'a' = 'a '; 'a' = 'a ' @@ -1295,7 +1295,7 @@ concat(concat(_latin1'->',f1),_latin1'<-') -><- drop table t1; select convert(_koi8r'É' using utf8) < convert(_koi8r'Ê' using utf8); -convert(_koi8r'É' using utf8) < convert(_koi8r'Ê' using utf8) +convert(_koi8r'\xC9' using utf8) < convert(_koi8r'\xCA' using utf8) 1 set names latin1; create table t1 (a varchar(10)) character set utf8; diff --git a/mysql-test/main/ctype_utf8mb4.result b/mysql-test/main/ctype_utf8mb4.result index 2762873b9c7..71fb13afc18 100644 --- a/mysql-test/main/ctype_utf8mb4.result +++ b/mysql-test/main/ctype_utf8mb4.result @@ -67,13 +67,13 @@ select _utf8mb4 0xD0B0D0B1D0B2 like concat(_utf8mb4'%',_utf8mb4 0xD0B1,_utf8mb4 _utf8mb4 0xD0B0D0B1D0B2 like concat(_utf8mb4'%',_utf8mb4 0xD0B1,_utf8mb4 '%') 1 select convert(_latin1'Günter André' using utf8mb4) like CONVERT(_latin1'GÜNTER%' USING utf8mb4); -convert(_latin1'G?nter Andr?' using utf8mb4) like CONVERT(_latin1'G?NTER%' USING utf8mb4) +convert(_latin1'G\xFCnter Andr\xE9' using utf8mb4) like CONVERT(_latin1'G\xDCNTER%' USING utf8mb4) 1 select CONVERT(_koi8r'×ÁÓÑ' USING utf8mb4) LIKE CONVERT(_koi8r'÷áóñ' USING utf8mb4); -CONVERT(_koi8r'????' USING utf8mb4) LIKE CONVERT(_koi8r'????' USING utf8mb4) +CONVERT(_koi8r'\xD7\xC1\xD3\xD1' USING utf8mb4) LIKE CONVERT(_koi8r'\xF7\xE1\xF3\xF1' USING utf8mb4) 1 select CONVERT(_koi8r'÷áóñ' USING utf8mb4) LIKE CONVERT(_koi8r'×ÁÓÑ' USING utf8mb4); -CONVERT(_koi8r'????' USING utf8mb4) LIKE CONVERT(_koi8r'????' USING utf8mb4) +CONVERT(_koi8r'\xF7\xE1\xF3\xF1' USING utf8mb4) LIKE CONVERT(_koi8r'\xD7\xC1\xD3\xD1' USING utf8mb4) 1 SELECT 'a' = 'a '; 'a' = 'a ' @@ -1316,7 +1316,7 @@ concat(concat(_latin1'->',f1),_latin1'<-') -><- drop table t1; select convert(_koi8r'É' using utf8mb4) < convert(_koi8r'Ê' using utf8mb4); -convert(_koi8r'?' using utf8mb4) < convert(_koi8r'?' using utf8mb4) +convert(_koi8r'\xC9' using utf8mb4) < convert(_koi8r'\xCA' using utf8mb4) 1 set names latin1; create table t1 (a varchar(10)) character set utf8mb4; diff --git a/mysql-test/main/ctype_utf8mb4_heap.result b/mysql-test/main/ctype_utf8mb4_heap.result index 9eb7d48370f..d18d1939aa9 100644 --- a/mysql-test/main/ctype_utf8mb4_heap.result +++ b/mysql-test/main/ctype_utf8mb4_heap.result @@ -67,13 +67,13 @@ select _utf8mb4 0xD0B0D0B1D0B2 like concat(_utf8mb4'%',_utf8mb4 0xD0B1,_utf8mb4 _utf8mb4 0xD0B0D0B1D0B2 like concat(_utf8mb4'%',_utf8mb4 0xD0B1,_utf8mb4 '%') 1 select convert(_latin1'Günter André' using utf8mb4) like CONVERT(_latin1'GÜNTER%' USING utf8mb4); -convert(_latin1'G?nter Andr?' using utf8mb4) like CONVERT(_latin1'G?NTER%' USING utf8mb4) +convert(_latin1'G\xFCnter Andr\xE9' using utf8mb4) like CONVERT(_latin1'G\xDCNTER%' USING utf8mb4) 1 select CONVERT(_koi8r'×ÁÓÑ' USING utf8mb4) LIKE CONVERT(_koi8r'÷áóñ' USING utf8mb4); -CONVERT(_koi8r'????' USING utf8mb4) LIKE CONVERT(_koi8r'????' USING utf8mb4) +CONVERT(_koi8r'\xD7\xC1\xD3\xD1' USING utf8mb4) LIKE CONVERT(_koi8r'\xF7\xE1\xF3\xF1' USING utf8mb4) 1 select CONVERT(_koi8r'÷áóñ' USING utf8mb4) LIKE CONVERT(_koi8r'×ÁÓÑ' USING utf8mb4); -CONVERT(_koi8r'????' USING utf8mb4) LIKE CONVERT(_koi8r'????' USING utf8mb4) +CONVERT(_koi8r'\xF7\xE1\xF3\xF1' USING utf8mb4) LIKE CONVERT(_koi8r'\xD7\xC1\xD3\xD1' USING utf8mb4) 1 SELECT 'a' = 'a '; 'a' = 'a ' @@ -1215,7 +1215,7 @@ concat(concat(_latin1'->',f1),_latin1'<-') -><- drop table t1; select convert(_koi8r'É' using utf8mb4) < convert(_koi8r'Ê' using utf8mb4); -convert(_koi8r'?' using utf8mb4) < convert(_koi8r'?' using utf8mb4) +convert(_koi8r'\xC9' using utf8mb4) < convert(_koi8r'\xCA' using utf8mb4) 1 set names latin1; create table t1 (a varchar(10)) character set utf8mb4 engine heap; diff --git a/mysql-test/main/ctype_utf8mb4_innodb.result b/mysql-test/main/ctype_utf8mb4_innodb.result index fc2a368f3f0..c04f62f3cb0 100644 --- a/mysql-test/main/ctype_utf8mb4_innodb.result +++ b/mysql-test/main/ctype_utf8mb4_innodb.result @@ -67,13 +67,13 @@ select _utf8mb4 0xD0B0D0B1D0B2 like concat(_utf8mb4'%',_utf8mb4 0xD0B1,_utf8mb4 _utf8mb4 0xD0B0D0B1D0B2 like concat(_utf8mb4'%',_utf8mb4 0xD0B1,_utf8mb4 '%') 1 select convert(_latin1'Günter André' using utf8mb4) like CONVERT(_latin1'GÜNTER%' USING utf8mb4); -convert(_latin1'G?nter Andr?' using utf8mb4) like CONVERT(_latin1'G?NTER%' USING utf8mb4) +convert(_latin1'G\xFCnter Andr\xE9' using utf8mb4) like CONVERT(_latin1'G\xDCNTER%' USING utf8mb4) 1 select CONVERT(_koi8r'×ÁÓÑ' USING utf8mb4) LIKE CONVERT(_koi8r'÷áóñ' USING utf8mb4); -CONVERT(_koi8r'????' USING utf8mb4) LIKE CONVERT(_koi8r'????' USING utf8mb4) +CONVERT(_koi8r'\xD7\xC1\xD3\xD1' USING utf8mb4) LIKE CONVERT(_koi8r'\xF7\xE1\xF3\xF1' USING utf8mb4) 1 select CONVERT(_koi8r'÷áóñ' USING utf8mb4) LIKE CONVERT(_koi8r'×ÁÓÑ' USING utf8mb4); -CONVERT(_koi8r'????' USING utf8mb4) LIKE CONVERT(_koi8r'????' USING utf8mb4) +CONVERT(_koi8r'\xF7\xE1\xF3\xF1' USING utf8mb4) LIKE CONVERT(_koi8r'\xD7\xC1\xD3\xD1' USING utf8mb4) 1 SELECT 'a' = 'a '; 'a' = 'a ' @@ -1278,7 +1278,7 @@ concat(concat(_latin1'->',f1),_latin1'<-') -><- drop table t1; select convert(_koi8r'É' using utf8mb4) < convert(_koi8r'Ê' using utf8mb4); -convert(_koi8r'?' using utf8mb4) < convert(_koi8r'?' using utf8mb4) +convert(_koi8r'\xC9' using utf8mb4) < convert(_koi8r'\xCA' using utf8mb4) 1 set names latin1; create table t1 (a varchar(10)) character set utf8mb4 engine InnoDB; diff --git a/mysql-test/main/ctype_utf8mb4_myisam.result b/mysql-test/main/ctype_utf8mb4_myisam.result index ee2bd4431fc..a8b740305c6 100644 --- a/mysql-test/main/ctype_utf8mb4_myisam.result +++ b/mysql-test/main/ctype_utf8mb4_myisam.result @@ -67,13 +67,13 @@ select _utf8mb4 0xD0B0D0B1D0B2 like concat(_utf8mb4'%',_utf8mb4 0xD0B1,_utf8mb4 _utf8mb4 0xD0B0D0B1D0B2 like concat(_utf8mb4'%',_utf8mb4 0xD0B1,_utf8mb4 '%') 1 select convert(_latin1'Günter André' using utf8mb4) like CONVERT(_latin1'GÜNTER%' USING utf8mb4); -convert(_latin1'G?nter Andr?' using utf8mb4) like CONVERT(_latin1'G?NTER%' USING utf8mb4) +convert(_latin1'G\xFCnter Andr\xE9' using utf8mb4) like CONVERT(_latin1'G\xDCNTER%' USING utf8mb4) 1 select CONVERT(_koi8r'×ÁÓÑ' USING utf8mb4) LIKE CONVERT(_koi8r'÷áóñ' USING utf8mb4); -CONVERT(_koi8r'????' USING utf8mb4) LIKE CONVERT(_koi8r'????' USING utf8mb4) +CONVERT(_koi8r'\xD7\xC1\xD3\xD1' USING utf8mb4) LIKE CONVERT(_koi8r'\xF7\xE1\xF3\xF1' USING utf8mb4) 1 select CONVERT(_koi8r'÷áóñ' USING utf8mb4) LIKE CONVERT(_koi8r'×ÁÓÑ' USING utf8mb4); -CONVERT(_koi8r'????' USING utf8mb4) LIKE CONVERT(_koi8r'????' USING utf8mb4) +CONVERT(_koi8r'\xF7\xE1\xF3\xF1' USING utf8mb4) LIKE CONVERT(_koi8r'\xD7\xC1\xD3\xD1' USING utf8mb4) 1 SELECT 'a' = 'a '; 'a' = 'a ' @@ -1281,7 +1281,7 @@ concat(concat(_latin1'->',f1),_latin1'<-') -><- drop table t1; select convert(_koi8r'É' using utf8mb4) < convert(_koi8r'Ê' using utf8mb4); -convert(_koi8r'?' using utf8mb4) < convert(_koi8r'?' using utf8mb4) +convert(_koi8r'\xC9' using utf8mb4) < convert(_koi8r'\xCA' using utf8mb4) 1 set names latin1; create table t1 (a varchar(10)) character set utf8mb4 engine MyISAM; diff --git a/mysql-test/main/plugin.result b/mysql-test/main/plugin.result index 04931001901..a4fb475981c 100644 --- a/mysql-test/main/plugin.result +++ b/mysql-test/main/plugin.result @@ -320,7 +320,7 @@ select plugin_name from information_schema.plugins where plugin_library like 'ha plugin_name set names utf8; select convert('adminðŒ†' using utf8); -convert('adminðŒ†' using utf8) +convert('admin\xF0\x9D\x8C\x86' using utf8) admin???? Warnings: Warning 1300 Invalid utf8 character string: '\xF0\x9D\x8C\x86' diff --git a/sql/item.cc b/sql/item.cc index c79e706d875..1319d5c4b62 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1217,6 +1217,80 @@ bool Item::check_type_scalar(const char *opname) const } +extern "C" { + +/* + All values greater than MY_NAME_BINARY_VALUE are + interpreted as binary bytes. + The exact constant value does not matter, + but it must be greater than 0x10FFFF, + which is the maximum possible character in Unicode. +*/ +#define MY_NAME_BINARY_VALUE 0x200000 + +/* + Print all binary bytes as well as zero character U+0000 in hex notation. + Print other characters normally. +*/ +static int +my_wc_mb_item_name(CHARSET_INFO *cs, my_wc_t wc, uchar *str, uchar *end) +{ + if (wc == 0 || wc >= MY_NAME_BINARY_VALUE) + { + if (str + 4 >= end) + return MY_CS_TOOSMALL3; + str[0]= '\\'; + str[1]= 'x'; + str[2]= _dig_vec_upper[(uchar) (wc >> 4)]; + str[3]= _dig_vec_upper[(uchar) wc & 0x0F]; + return 4; + } + return my_charset_utf8_handler.wc_mb(cs, wc, str, end); +} + + +/* + Scan characters and mark all illegal sequences as binary byte values, + to have my_wc_mb_utf8_escape_name() print them using HEX notation. +*/ +static int +my_mb_wc_item_name(CHARSET_INFO *cs, my_wc_t *pwc, + const uchar *str, const uchar *end) +{ + int rc= cs->cset->mb_wc(cs, pwc, str, end); + if (rc == MY_CS_ILSEQ) + { + *pwc= MY_NAME_BINARY_VALUE + *str; + return 1; + } + return rc; +} + +} + + +static LEX_CSTRING +make_name(THD *thd, + const char *str, size_t length, CHARSET_INFO *cs, + size_t max_octet_length) +{ + uint errors; + size_t dst_nbytes= length * system_charset_info->mbmaxlen; + set_if_smaller(dst_nbytes, max_octet_length); + char *dst= (char*) thd->alloc(dst_nbytes + 1); + if (!dst) + return null_clex_str; + uint32 cnv_length= my_convert_using_func(dst, dst_nbytes, system_charset_info, + my_wc_mb_item_name, + str, length, + cs == &my_charset_bin ? + system_charset_info : cs, + my_mb_wc_item_name, &errors); + dst[cnv_length]= '\0'; + return Lex_cstring(dst, cnv_length); +} + + void Item::set_name(THD *thd, const char *str, size_t length, CHARSET_INFO *cs) { if (!length) @@ -1267,32 +1341,14 @@ void Item::set_name(THD *thd, const char *str, size_t length, CHARSET_INFO *cs) ER_REMOVED_SPACES, ER_THD(thd, ER_REMOVED_SPACES), buff); } - if (!my_charset_same(cs, system_charset_info)) - { - size_t res_length; - name.str= sql_strmake_with_convert(thd, str, length, cs, - MAX_ALIAS_NAME, system_charset_info, - &res_length); - name.length= res_length; - } - else - name.str= thd->strmake(str, (name.length= MY_MIN(length,MAX_ALIAS_NAME))); + name= make_name(thd, str, length, cs, MAX_ALIAS_NAME - 1); } void Item::set_name_no_truncate(THD *thd, const char *str, uint length, CHARSET_INFO *cs) { - if (!my_charset_same(cs, system_charset_info)) - { - size_t res_length; - name.str= sql_strmake_with_convert(thd, str, length, cs, - UINT_MAX, system_charset_info, - &res_length); - name.length= res_length; - } - else - name.str= thd->strmake(str, (name.length= length)); + name= make_name(thd, str, length, cs, UINT_MAX - 1); } From 05a0eae335ebdd1f9ac7540c263b870a17d69b9f Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 27 Oct 2021 07:21:34 +0400 Subject: [PATCH 8/8] MDEV-22380 Assertion `name.length == strlen(name.str)' failed .. w/optimizer_trace enabled Adding 10.4 specific tests. --- mysql-test/main/opt_trace.result | 35 ++++++++++++++++++++++++++++++++ mysql-test/main/opt_trace.test | 9 ++++++++ 2 files changed, 44 insertions(+) diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result index 0ced5f19e14..c16df0da0b2 100644 --- a/mysql-test/main/opt_trace.result +++ b/mysql-test/main/opt_trace.result @@ -8599,5 +8599,40 @@ select count(*) from information_schema.optimizer_trace; select * from information_schema.optimizer_trace; set max_session_mem_used=default; # +# MDEV-22380 Assertion `name.length == strlen(name.str)' failed in Item::print_item_w_name on SELECT w/ optimizer_trace enabled +# +SET optimizer_trace="enabled=on"; +SELECT 'a\0' LIMIT 0; +a\x00 +SELECT query, trace FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +query trace +SELECT 'a\0' LIMIT 0 { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "select 'a\0' AS `a\x00` limit 0" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} +SET optimizer_trace=DEFAULT; +# # End of 10.4 tests # diff --git a/mysql-test/main/opt_trace.test b/mysql-test/main/opt_trace.test index 3fae7f34750..1dfb7e5ce8a 100644 --- a/mysql-test/main/opt_trace.test +++ b/mysql-test/main/opt_trace.test @@ -634,6 +634,15 @@ select * from information_schema.optimizer_trace; --enable_result_log set max_session_mem_used=default; +--echo # +--echo # MDEV-22380 Assertion `name.length == strlen(name.str)' failed in Item::print_item_w_name on SELECT w/ optimizer_trace enabled +--echo # + +SET optimizer_trace="enabled=on"; +SELECT 'a\0' LIMIT 0; +SELECT query, trace FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +SET optimizer_trace=DEFAULT; + --echo # --echo # End of 10.4 tests --echo #