From 74e4cf70d09bbe7a0a530bc50895820e04466194 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 12 Jun 2017 18:43:23 +0000 Subject: [PATCH 1/9] MDEV-13059 XtraDB hangs on Windows due to failing to release block->lock X-latch in innodb_read_only mode. The reason for the hang is that there was no notification received about completed read io. File handles are bound to completion_port, and there were no background "write" threads that would be waiting on completion_port, only 2 "read" threads waiting on read_completion_port were active. The fix is to use a single IO completion port for all IOs, if innodb_read_only is set. --- mysql-test/suite/innodb/t/row_format_redundant.test | 10 ---------- storage/xtradb/os/os0file.cc | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/mysql-test/suite/innodb/t/row_format_redundant.test b/mysql-test/suite/innodb/t/row_format_redundant.test index 974588d11eb..b17b365651a 100644 --- a/mysql-test/suite/innodb/t/row_format_redundant.test +++ b/mysql-test/suite/innodb/t/row_format_redundant.test @@ -2,16 +2,6 @@ # Embedded mode doesn't allow restarting --source include/not_embedded.inc -# MDEV-13059 XtraDB hangs on Windows due to failing to release -# block->lock X-latch in innodb_read_only mode -if (`SELECT count(*) FROM information_schema.plugins WHERE - plugin_name = 'innodb' AND plugin_status = 'active' AND - plugin_description LIKE '%xtradb%'`){ - if (`SELECT @@version_compile_os IN ('Win32','Win64','Windows')`) { - skip MDEV-13059 XtraDB hangs on Windows in innodb_read_only mode; - } -} - create table t1 (a int not null, d varchar(15) not null, b varchar(198) not null, c char(156), fulltext ftsic(c)) engine=InnoDB diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc index 5e67d2473f0..9be9c64b759 100644 --- a/storage/xtradb/os/os0file.cc +++ b/storage/xtradb/os/os0file.cc @@ -4163,7 +4163,7 @@ os_aio_init( #ifdef _WIN32 ut_a(completion_port == 0 && read_completion_port == 0); completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); - read_completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); + read_completion_port = srv_read_only_mode? completion_port : CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); ut_a(completion_port && read_completion_port); #endif From 1d5a306e3884ff0b159402f1f83dee2fb87d93f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 13 Jun 2017 16:20:21 +0300 Subject: [PATCH 2/9] MDEV-12873 InnoDB SYS_TABLES.TYPE incompatibility for PAGE_COMPRESSION in MariaDB 10.2.2 to 10.2.6 Add a test case for corrupting SYS_TABLES.TYPE, and for ROW_FORMAT=REDUNDANT, the unused field SYS_TABLES.MIX_LEN that must be ignored (InnoDB before MySQL 5.5 wrote uninitialized garbage to this column). MariaDB 10.0 appears to validate the SYS_TABLES.TYPE properly. This is a test-only change. --- .../suite/innodb/r/table_flags,4k.rdiff | 83 ++++++++ .../suite/innodb/r/table_flags,8k.rdiff | 83 ++++++++ mysql-test/suite/innodb/r/table_flags.result | 175 ++++++++++++++++ .../suite/innodb/t/row_format_redundant.test | 4 +- mysql-test/suite/innodb/t/table_flags.test | 190 ++++++++++++++++++ 5 files changed, 532 insertions(+), 3 deletions(-) create mode 100644 mysql-test/suite/innodb/r/table_flags,4k.rdiff create mode 100644 mysql-test/suite/innodb/r/table_flags,8k.rdiff create mode 100644 mysql-test/suite/innodb/r/table_flags.result create mode 100644 mysql-test/suite/innodb/t/table_flags.test diff --git a/mysql-test/suite/innodb/r/table_flags,4k.rdiff b/mysql-test/suite/innodb/r/table_flags,4k.rdiff new file mode 100644 index 00000000000..faa8a408c65 --- /dev/null +++ b/mysql-test/suite/innodb/r/table_flags,4k.rdiff @@ -0,0 +1,83 @@ +--- suite/innodb/r/table_flags.result ++++ suite/innodb/r/table_flags,4k.reject +@@ -13,7 +13,7 @@ + header=0x01000003016e (NAME=0x696e66696d756d00) + header=0x00002815008d (NAME='SYS_DATAFILES', + DB_TRX_ID=0x000000000301, +- DB_ROLL_PTR=0x81000001320194, ++ DB_ROLL_PTR=0x81000003260194, + ID=0x000000000000000e, + N_COLS=0x00000002, + TYPE=0x00000001, +@@ -23,7 +23,7 @@ + SPACE=0x00000000) + header=0x0000101500d5 (NAME='SYS_FOREIGN', + DB_TRX_ID=0x000000000300, +- DB_ROLL_PTR=0x800000012d0110, ++ DB_ROLL_PTR=0x80000003200110, + ID=0x000000000000000b, + N_COLS=0x00000004, + TYPE=0x00000001, +@@ -33,7 +33,7 @@ + SPACE=0x00000000) + header=0x000018150122 (NAME='SYS_FOREIGN_COLS', + DB_TRX_ID=0x000000000300, +- DB_ROLL_PTR=0x800000012d0201, ++ DB_ROLL_PTR=0x80000003200201, + ID=0x000000000000000c, + N_COLS=0x00000004, + TYPE=0x00000001, +@@ -43,7 +43,7 @@ + SPACE=0x00000000) + header=0x0400201501fc (NAME='SYS_TABLESPACES', + DB_TRX_ID=0x000000000301, +- DB_ROLL_PTR=0x81000001320110, ++ DB_ROLL_PTR=0x81000003260110, + ID=0x000000000000000d, + N_COLS=0x00000003, + TYPE=0x00000001, +@@ -53,7 +53,7 @@ + SPACE=0x00000000) + header=0x000038150240 (NAME='test/tc', + DB_TRX_ID=0x000000000303, +- DB_ROLL_PTR=0x83000001360110, ++ DB_ROLL_PTR=0x830000032b0110, + ID=0x0000000000000010, + N_COLS=0x80000001, + TYPE=0x00000001, +@@ -63,7 +63,7 @@ + SPACE=0x00000002) + header=0x0000401502c8 (NAME='test/td', + DB_TRX_ID=0x000000000304, +- DB_ROLL_PTR=0x84000001370110, ++ DB_ROLL_PTR=0x840000032c0110, + ID=0x0000000000000011, + N_COLS=0x80000001, + TYPE=0x00000021, +@@ -73,7 +73,7 @@ + SPACE=0x00000003) + header=0x0000501501b8 (NAME='test/tp', + DB_TRX_ID=0x000000000306, +- DB_ROLL_PTR=0x86000001390110, ++ DB_ROLL_PTR=0x860000032e0110, + ID=0x0000000000000013, + N_COLS=0x80000001, + TYPE=0x00000021, +@@ -83,7 +83,7 @@ + SPACE=0x00000005) + header=0x000030150284 (NAME='test/tr', + DB_TRX_ID=0x000000000302, +- DB_ROLL_PTR=0x82000001350110, ++ DB_ROLL_PTR=0x820000032a0110, + ID=0x000000000000000f, + N_COLS=0x00000001, + TYPE=0x00000001, +@@ -93,7 +93,7 @@ + SPACE=0x00000001) + header=0x000048150074 (NAME='test/tz', + DB_TRX_ID=0x000000000305, +- DB_ROLL_PTR=0x85000001380110, ++ DB_ROLL_PTR=0x850000032d0110, + ID=0x0000000000000012, + N_COLS=0x80000001, + TYPE=0x00000023, diff --git a/mysql-test/suite/innodb/r/table_flags,8k.rdiff b/mysql-test/suite/innodb/r/table_flags,8k.rdiff new file mode 100644 index 00000000000..ba3439fc6cf --- /dev/null +++ b/mysql-test/suite/innodb/r/table_flags,8k.rdiff @@ -0,0 +1,83 @@ +--- suite/innodb/r/table_flags.result ++++ suite/innodb/r/table_flags,8k.reject +@@ -13,7 +13,7 @@ + header=0x01000003016e (NAME=0x696e66696d756d00) + header=0x00002815008d (NAME='SYS_DATAFILES', + DB_TRX_ID=0x000000000301, +- DB_ROLL_PTR=0x81000001320194, ++ DB_ROLL_PTR=0x81000001d70194, + ID=0x000000000000000e, + N_COLS=0x00000002, + TYPE=0x00000001, +@@ -23,7 +23,7 @@ + SPACE=0x00000000) + header=0x0000101500d5 (NAME='SYS_FOREIGN', + DB_TRX_ID=0x000000000300, +- DB_ROLL_PTR=0x800000012d0110, ++ DB_ROLL_PTR=0x80000001d10110, + ID=0x000000000000000b, + N_COLS=0x00000004, + TYPE=0x00000001, +@@ -33,7 +33,7 @@ + SPACE=0x00000000) + header=0x000018150122 (NAME='SYS_FOREIGN_COLS', + DB_TRX_ID=0x000000000300, +- DB_ROLL_PTR=0x800000012d0201, ++ DB_ROLL_PTR=0x80000001d10201, + ID=0x000000000000000c, + N_COLS=0x00000004, + TYPE=0x00000001, +@@ -43,7 +43,7 @@ + SPACE=0x00000000) + header=0x0400201501fc (NAME='SYS_TABLESPACES', + DB_TRX_ID=0x000000000301, +- DB_ROLL_PTR=0x81000001320110, ++ DB_ROLL_PTR=0x81000001d70110, + ID=0x000000000000000d, + N_COLS=0x00000003, + TYPE=0x00000001, +@@ -53,7 +53,7 @@ + SPACE=0x00000000) + header=0x000038150240 (NAME='test/tc', + DB_TRX_ID=0x000000000303, +- DB_ROLL_PTR=0x83000001360110, ++ DB_ROLL_PTR=0x83000001db0110, + ID=0x0000000000000010, + N_COLS=0x80000001, + TYPE=0x00000001, +@@ -63,7 +63,7 @@ + SPACE=0x00000002) + header=0x0000401502c8 (NAME='test/td', + DB_TRX_ID=0x000000000304, +- DB_ROLL_PTR=0x84000001370110, ++ DB_ROLL_PTR=0x84000001dc0110, + ID=0x0000000000000011, + N_COLS=0x80000001, + TYPE=0x00000021, +@@ -73,7 +73,7 @@ + SPACE=0x00000003) + header=0x0000501501b8 (NAME='test/tp', + DB_TRX_ID=0x000000000306, +- DB_ROLL_PTR=0x86000001390110, ++ DB_ROLL_PTR=0x86000001de0110, + ID=0x0000000000000013, + N_COLS=0x80000001, + TYPE=0x00000021, +@@ -83,7 +83,7 @@ + SPACE=0x00000005) + header=0x000030150284 (NAME='test/tr', + DB_TRX_ID=0x000000000302, +- DB_ROLL_PTR=0x82000001350110, ++ DB_ROLL_PTR=0x82000001da0110, + ID=0x000000000000000f, + N_COLS=0x00000001, + TYPE=0x00000001, +@@ -93,7 +93,7 @@ + SPACE=0x00000001) + header=0x000048150074 (NAME='test/tz', + DB_TRX_ID=0x000000000305, +- DB_ROLL_PTR=0x85000001380110, ++ DB_ROLL_PTR=0x85000001dd0110, + ID=0x0000000000000012, + N_COLS=0x80000001, + TYPE=0x00000023, diff --git a/mysql-test/suite/innodb/r/table_flags.result b/mysql-test/suite/innodb/r/table_flags.result new file mode 100644 index 00000000000..8d79439764c --- /dev/null +++ b/mysql-test/suite/innodb/r/table_flags.result @@ -0,0 +1,175 @@ +SET GLOBAL innodb_file_per_table=1; +CREATE TABLE tr(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +CREATE TABLE tc(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=COMPACT; +CREATE TABLE td(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +CREATE TABLE tz(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=COMPRESSED +KEY_BLOCK_SIZE=1; +CREATE TABLE tp(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=DYNAMIC +PAGE_COMPRESSED=1 PAGE_COMPRESSION_LEVEL=9; +ERROR HY000: Unknown option 'PAGE_COMPRESSED' +CREATE TABLE tp(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +SYS_TABLES clustered index root page (8): +N_RECS=9; LEVEL=0; INDEX_ID=0x0000000000000001 +header=0x01000003016e (NAME=0x696e66696d756d00) +header=0x00002815008d (NAME='SYS_DATAFILES', + DB_TRX_ID=0x000000000301, + DB_ROLL_PTR=0x81000001320194, + ID=0x000000000000000e, + N_COLS=0x00000002, + TYPE=0x00000001, + MIX_ID=0x0000000000000000, + MIX_LEN=0x00000040, + CLUSTER_NAME=NULL(0 bytes), + SPACE=0x00000000) +header=0x0000101500d5 (NAME='SYS_FOREIGN', + DB_TRX_ID=0x000000000300, + DB_ROLL_PTR=0x800000012d0110, + ID=0x000000000000000b, + N_COLS=0x00000004, + TYPE=0x00000001, + MIX_ID=0x0000000000000000, + MIX_LEN=0x00000040, + CLUSTER_NAME=NULL(0 bytes), + SPACE=0x00000000) +header=0x000018150122 (NAME='SYS_FOREIGN_COLS', + DB_TRX_ID=0x000000000300, + DB_ROLL_PTR=0x800000012d0201, + ID=0x000000000000000c, + N_COLS=0x00000004, + TYPE=0x00000001, + MIX_ID=0x0000000000000000, + MIX_LEN=0x00000040, + CLUSTER_NAME=NULL(0 bytes), + SPACE=0x00000000) +header=0x0400201501fc (NAME='SYS_TABLESPACES', + DB_TRX_ID=0x000000000301, + DB_ROLL_PTR=0x81000001320110, + ID=0x000000000000000d, + N_COLS=0x00000003, + TYPE=0x00000001, + MIX_ID=0x0000000000000000, + MIX_LEN=0x00000040, + CLUSTER_NAME=NULL(0 bytes), + SPACE=0x00000000) +header=0x000038150240 (NAME='test/tc', + DB_TRX_ID=0x000000000303, + DB_ROLL_PTR=0x83000001360110, + ID=0x0000000000000010, + N_COLS=0x80000001, + TYPE=0x00000001, + MIX_ID=0x0000000000000000, + MIX_LEN=0x00000050, + CLUSTER_NAME=NULL(0 bytes), + SPACE=0x00000002) +header=0x0000401502c8 (NAME='test/td', + DB_TRX_ID=0x000000000304, + DB_ROLL_PTR=0x84000001370110, + ID=0x0000000000000011, + N_COLS=0x80000001, + TYPE=0x00000021, + MIX_ID=0x0000000000000000, + MIX_LEN=0x00000050, + CLUSTER_NAME=NULL(0 bytes), + SPACE=0x00000003) +header=0x0000501501b8 (NAME='test/tp', + DB_TRX_ID=0x000000000306, + DB_ROLL_PTR=0x86000001390110, + ID=0x0000000000000013, + N_COLS=0x80000001, + TYPE=0x00000021, + MIX_ID=0x0000000000000000, + MIX_LEN=0x00000050, + CLUSTER_NAME=NULL(0 bytes), + SPACE=0x00000005) +header=0x000030150284 (NAME='test/tr', + DB_TRX_ID=0x000000000302, + DB_ROLL_PTR=0x82000001350110, + ID=0x000000000000000f, + N_COLS=0x00000001, + TYPE=0x00000001, + MIX_ID=0x0000000000000000, + MIX_LEN=0x00000050, + CLUSTER_NAME=NULL(0 bytes), + SPACE=0x00000001) +header=0x000048150074 (NAME='test/tz', + DB_TRX_ID=0x000000000305, + DB_ROLL_PTR=0x85000001380110, + ID=0x0000000000000012, + N_COLS=0x80000001, + TYPE=0x00000023, + MIX_ID=0x0000000000000000, + MIX_LEN=0x00000050, + CLUSTER_NAME=NULL(0 bytes), + SPACE=0x00000004) +header=0x060008030000 (NAME=0x73757072656d756d00) +SHOW CREATE TABLE tr; +Table Create Table +tr CREATE TABLE `tr` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT +INSERT INTO tr VALUES(42); +SHOW CREATE TABLE tc; +ERROR 42S02: Table 'test.tc' doesn't exist in engine +SHOW CREATE TABLE td; +ERROR 42S02: Table 'test.td' doesn't exist in engine +SHOW CREATE TABLE tz; +ERROR 42S02: Table 'test.tz' doesn't exist in engine +SHOW CREATE TABLE tp; +ERROR 42S02: Table 'test.tp' doesn't exist in engine +FOUND /InnoDB: Table '.test.\..t[cdzp].' in InnoDB data dictionary has unknown type (81|f21|8a1|3023)/ in mysqld.1.err +FOUND /InnoDB: Cannot open table test/t[cdzp] from the internal data dictionary of InnoDB/ in mysqld.1.err +Restoring SYS_TABLES clustered index root page (8) +SHOW CREATE TABLE tr; +Table Create Table +tr CREATE TABLE `tr` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT +SHOW CREATE TABLE tc; +Table Create Table +tc CREATE TABLE `tc` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT +SHOW CREATE TABLE td; +Table Create Table +td CREATE TABLE `td` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +SHOW CREATE TABLE tz; +Table Create Table +tz CREATE TABLE `tz` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 +SHOW CREATE TABLE tp; +Table Create Table +tp CREATE TABLE `tp` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +BEGIN; +INSERT INTO tr VALUES(1); +INSERT INTO tc VALUES(1); +INSERT INTO td VALUES(1); +INSERT INTO tz VALUES(1); +INSERT INTO tp VALUES(1); +ROLLBACK; +SELECT * FROM tr; +a +42 +SELECT * FROM tc; +a +SELECT * FROM td; +a +SELECT * FROM tz; +a +SELECT * FROM tp; +a +DROP TABLE tr,tc,td,tz,tp; +ib_logfile0 +ib_logfile1 +ibdata1 +sys_tables.bin diff --git a/mysql-test/suite/innodb/t/row_format_redundant.test b/mysql-test/suite/innodb/t/row_format_redundant.test index b17b365651a..d10121c75c6 100644 --- a/mysql-test/suite/innodb/t/row_format_redundant.test +++ b/mysql-test/suite/innodb/t/row_format_redundant.test @@ -1,4 +1,4 @@ ---source include/innodb_page_size.inc +--source include/have_innodb.inc # Embedded mode doesn't allow restarting --source include/not_embedded.inc @@ -60,6 +60,4 @@ TRUNCATE TABLE t1; TRUNCATE TABLE t2; TRUNCATE TABLE t3; -# TODO: Shutdown, corrupt the SYS_TABLES.TYPE of the tables, restart - DROP TABLE t1,t2,t3; diff --git a/mysql-test/suite/innodb/t/table_flags.test b/mysql-test/suite/innodb/t/table_flags.test new file mode 100644 index 00000000000..4d3afcb2dec --- /dev/null +++ b/mysql-test/suite/innodb/t/table_flags.test @@ -0,0 +1,190 @@ +--source include/innodb_page_size.inc +# Embedded server tests do not support restarting +--source include/not_embedded.inc + +--disable_query_log +call mtr.add_suppression("InnoDB: New log files created, LSN="); +call mtr.add_suppression("InnoDB: Creating foreign key constraint system tables"); +call mtr.add_suppression("InnoDB: Error: .*innodb_table_stats. not found"); +call mtr.add_suppression("InnoDB: Table '.test.\\..t[cdzp].' in InnoDB data dictionary has unknown type (81|f21|8a1|3023)"); +call mtr.add_suppression("InnoDB: Cannot open table test/t[cdzp] from the internal data dictionary of InnoDB"); +call mtr.add_suppression("InnoDB: Error: table 'test/t[cdzp]'"); +FLUSH TABLES; +--enable_query_log + +let INNODB_PAGE_SIZE=`select @@innodb_page_size`; +let MYSQLD_DATADIR=`select @@datadir`; + +let bugdir= $MYSQLTEST_VARDIR/tmp/table_flags; +--mkdir $bugdir +--let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err + +--let $d=--innodb-data-home-dir=$bugdir --innodb-log-group-home-dir=$bugdir +--let $d=$d --innodb-data-file-path=ibdata1:10M:autoextend +--let $d=$d --innodb-undo-tablespaces=0 +--let $restart_parameters=$d --innodb-stats-persistent=0 --innodb-file-format=1 +--source include/restart_mysqld.inc + +SET GLOBAL innodb_file_per_table=1; +CREATE TABLE tr(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +CREATE TABLE tc(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=COMPACT; +CREATE TABLE td(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +CREATE TABLE tz(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=COMPRESSED +KEY_BLOCK_SIZE=1; +# PAGE_COMPRESSED is supported starting with MariaDB 10.1.0 +--error ER_UNKNOWN_OPTION +CREATE TABLE tp(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=DYNAMIC +PAGE_COMPRESSED=1 PAGE_COMPRESSION_LEVEL=9; +CREATE TABLE tp(a INT PRIMARY KEY)ENGINE=InnoDB ROW_FORMAT=DYNAMIC; + +--source include/shutdown_mysqld.inc +--perl +use strict; +my $ps= $ENV{INNODB_PAGE_SIZE}; +my $file= "$ENV{bugdir}/ibdata1"; +open(FILE, "+<", $file) || die "Unable to open $file\n"; +# Read DICT_HDR_TABLES, the root page number of CLUST_IND (SYS_TABLES.NAME). +sysseek(FILE, 7*$ps+38+32, 0) || die "Unable to seek $file"; +die "Unable to read $file" unless sysread(FILE, $_, 4) == 4; +my $sys_tables_root = unpack("N", $_); +my $page; +print "SYS_TABLES clustered index root page ($sys_tables_root):\n"; +sysseek(FILE, $sys_tables_root*$ps, 0) || die "Unable to seek $file"; +die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps; +open(BACKUP, ">$ENV{bugdir}/sys_tables.bin") || die "Unable to open backup\n"; +syswrite(BACKUP, $page, $ps)==$ps || die "Unable to write backup\n"; +close(BACKUP) || die "Unable to close backup\n"; +print "N_RECS=", unpack("n", substr($page,38+16,2)); +print "; LEVEL=", unpack("n", substr($page,38+26,2)); +print "; INDEX_ID=0x", unpack("H*", substr($page,38+28,8)), "\n"; +my @fields=("NAME","DB_TRX_ID","DB_ROLL_PTR", + "ID","N_COLS","TYPE","MIX_ID","MIX_LEN","CLUSTER_NAME","SPACE"); +for (my $offset= 0x65; $offset; + $offset= unpack("n", substr($page,$offset-2,2))) +{ + print "header=0x", unpack("H*",substr($page,$offset-6,6)), " ("; + my $n_fields= unpack("n", substr($page,$offset-4,2)) >> 1 & 0x3ff; + my $start= 0; + my $name; + for (my $i= 0; $i < $n_fields; $i++) { + my $end= unpack("C", substr($page, $offset-7-$i, 1)); + print ",\n " if $i; + print "$fields[$i]="; + if ($end & 0x80) { + print "NULL(", ($end & 0x7f) - $start, " bytes)" + } elsif ($n_fields > 1 && $i == 0) { + $name= substr($page,$offset+$start,$end-$start); + print "'$name'" + } else { + print "0x", unpack("H*", substr($page,$offset+$start,$end-$start)) + } + # Corrupt SYS_TABLES.TYPE + if ($i == 5) + { + my $flags= 0; + if ($name eq 'test/tr') { +# $flags= 0x40 # DATA_DIR mismatch causes 10.0 crash! + } elsif ($name eq 'test/tc') { + $flags= 0x80 # 10.1 PAGE_COMPRESSED + } elsif ($name eq 'test/td') { + $flags= 0xf00 # 10.1 PAGE_COMPRESSION_LEVEL=15 (0..9 is valid) + } elsif ($name eq 'test/tz') { + $flags= 0x3000 # 10.1 ATOMIC_WRITES=3 (0..2 is valid) + } elsif ($name eq 'test/tp') { + $flags= 0x880 # 10.1 PAGE_COMPRESSED, PAGE_COMPRESSION_LEVEL=8 + # (in 10.1, this leaves PAGE_COMPRESSION_LEVEL=1 + # without PAGE_COMPRESSED, which should be invalid) + } + + substr($page,$offset+$start,$end-$start)= pack( + "N", $flags ^ + unpack("N", substr($page,$offset+$start,$end-$start))) + if $flags; + } + # Corrupt SYS_TABLES.MIX_LEN (ignored for ROW_FORMAT=REDUNDANT) + if ($i == 7 && $name eq 'test/tr') + { + substr($page,$offset+$start,$end-$start)= chr(255) x 4; + } + $start= $end & 0x7f; + } + print ")\n"; +} +substr($page,0,4)=pack("N",0xdeadbeef); +substr($page,$ps-8,4)=pack("N",0xdeadbeef); +sysseek(FILE, $sys_tables_root*$ps, 0) || die "Unable to seek $file"; +syswrite(FILE, $page, $ps)==$ps || die "Unable to write $file\n"; +close(FILE) || die "Unable to close $file\n"; +EOF +--source include/start_mysqld.inc + +SHOW CREATE TABLE tr; +INSERT INTO tr VALUES(42); +--error ER_NO_SUCH_TABLE_IN_ENGINE +SHOW CREATE TABLE tc; +--error ER_NO_SUCH_TABLE_IN_ENGINE +SHOW CREATE TABLE td; +--error ER_NO_SUCH_TABLE_IN_ENGINE +SHOW CREATE TABLE tz; +--error ER_NO_SUCH_TABLE_IN_ENGINE +SHOW CREATE TABLE tp; + +--source include/shutdown_mysqld.inc + +let SEARCH_RANGE= -50000; +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; +--let SEARCH_PATTERN= InnoDB: Table '.test.\..t[cdzp].' in InnoDB data dictionary has unknown type (81|f21|8a1|3023) +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN= InnoDB: Cannot open table test/t[cdzp] from the internal data dictionary of InnoDB +--source include/search_pattern_in_file.inc + +# Restore the backup of the corrupted SYS_TABLES clustered index root page +--perl +use strict; +my $ps= $ENV{INNODB_PAGE_SIZE}; +my $file= "$ENV{bugdir}/ibdata1"; +open(FILE, "+<", $file) || die "Unable to open $file\n"; +open(BACKUP, "<$ENV{bugdir}/sys_tables.bin") || die "Unable to open backup\n"; +# Read DICT_HDR_TABLES, the root page number of CLUST_IND (SYS_TABLES.NAME). +sysseek(FILE, 7*$ps+38+32, 0) || die "Unable to seek $file"; +die "Unable to read $file\n" unless sysread(FILE, $_, 4) == 4; +my $sys_tables_root = unpack("N", $_); +print "Restoring SYS_TABLES clustered index root page ($sys_tables_root)\n"; +sysseek(FILE, $sys_tables_root*$ps, 0) || die "Unable to seek $file"; +die "Unable to read backup\n" unless sysread(BACKUP, $_, $ps) == $ps; +die "Unable to restore backup\n" unless syswrite(FILE, $_, $ps) == $ps; +close(BACKUP); +close(FILE) || die "Unable to close $file\n"; +EOF +--source include/start_mysqld.inc + +SHOW CREATE TABLE tr; +SHOW CREATE TABLE tc; +SHOW CREATE TABLE td; +SHOW CREATE TABLE tz; +SHOW CREATE TABLE tp; + +BEGIN; +INSERT INTO tr VALUES(1); +INSERT INTO tc VALUES(1); +INSERT INTO td VALUES(1); +INSERT INTO tz VALUES(1); +INSERT INTO tp VALUES(1); +ROLLBACK; + +SELECT * FROM tr; +SELECT * FROM tc; +SELECT * FROM td; +SELECT * FROM tz; +SELECT * FROM tp; + +DROP TABLE tr,tc,td,tz,tp; + +--source include/shutdown_mysqld.inc + +--let $restart_parameters= +--source include/start_mysqld.inc + +--list_files $bugdir +--remove_files_wildcard $bugdir +--rmdir $bugdir From 9f0ed6c67e96e9b7fa4222c2c36640c0f691f43d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 13 Jun 2017 17:21:15 +0300 Subject: [PATCH 3/9] MDEV-13009 10.1.24 does not compile on architectures without 64-bit atomics Add a missing #include "sync0types.h" that was removed in MDEV-12674. --- storage/innobase/include/srv0mon.h | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/innobase/include/srv0mon.h b/storage/innobase/include/srv0mon.h index 2d5ff22cc21..316a467b6ff 100644 --- a/storage/innobase/include/srv0mon.h +++ b/storage/innobase/include/srv0mon.h @@ -644,6 +644,7 @@ Use MONITOR_DEC if appropriate mutex protection exists. # define srv_mon_create() ((void) 0) # define srv_mon_free() ((void) 0) #else /* HAVE_ATOMIC_BUILTINS_64 */ +# include "sync0types.h" /** Mutex protecting atomic operations on platforms that lack built-in operations for atomic memory access */ extern ib_mutex_t monitor_mutex; From 91ae1258ee29405c0e7c6c196aef2e870c11ec01 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Fri, 7 Apr 2017 15:38:01 +0200 Subject: [PATCH 4/9] MDEV-12471: BULK Command BULK execution moved to a new command. --- include/mysql.h.pp | 3 +- include/mysql_com.h | 13 +- mysql-test/r/mysqld--help.result | 2 +- .../sys_vars/r/sysvars_server_embedded.result | 4 +- .../r/sysvars_server_notembedded.result | 4 +- sql/item.cc | 2 +- sql/item.h | 4 +- sql/sql_insert.cc | 10 +- sql/sql_parse.cc | 7 +- sql/sql_prepare.cc | 224 +++++++++++++----- sql/sql_prepare.h | 3 +- 11 files changed, 192 insertions(+), 84 deletions(-) diff --git a/include/mysql.h.pp b/include/mysql.h.pp index 517516aeb30..9c5d9fa4303 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -12,7 +12,8 @@ enum enum_server_command COM_UNIMPLEMENTED, COM_RESET_CONNECTION, COM_MDB_GAP_BEG, - COM_MDB_GAP_END=250, + COM_MDB_GAP_END=249, + COM_STMT_BULK_EXECUTE=250, COM_SLAVE_WORKER=251, COM_SLAVE_IO=252, COM_SLAVE_SQL=253, diff --git a/include/mysql_com.h b/include/mysql_com.h index ace54767b06..0ca40dd0418 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -115,7 +115,8 @@ enum enum_server_command COM_RESET_CONNECTION, /* don't forget to update const char *command_name[] in sql_parse.cc */ COM_MDB_GAP_BEG, - COM_MDB_GAP_END=250, + COM_MDB_GAP_END=249, + COM_STMT_BULK_EXECUTE=250, COM_SLAVE_WORKER=251, COM_SLAVE_IO=252, COM_SLAVE_SQL=253, @@ -136,6 +137,13 @@ enum enum_indicator_type STMT_INDICATOR_IGNORE }; +/* + bulk PS flags +*/ +#define STMT_BULK_FLAG_CLIENT_SEND_TYPES 128 +#define STMT_BULK_FLAG_INSERT_ID_REQUEST 64 + + /* sql type stored in .frm files for virtual fields */ #define MYSQL_TYPE_VIRTUAL 245 /* @@ -311,7 +319,8 @@ enum enum_indicator_type CLIENT_SESSION_TRACK |\ CLIENT_DEPRECATE_EOF |\ CLIENT_CONNECT_ATTRS |\ - MARIADB_CLIENT_COM_MULTI) + MARIADB_CLIENT_COM_MULTI |\ + MARIADB_CLIENT_STMT_BULK_OPERATIONS) /* To be added later: diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index cfd2ede6ef9..24827da53be 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1396,7 +1396,7 @@ performance-schema-max-rwlock-instances -1 performance-schema-max-socket-classes 10 performance-schema-max-socket-instances -1 performance-schema-max-stage-classes 150 -performance-schema-max-statement-classes 187 +performance-schema-max-statement-classes 188 performance-schema-max-table-handles -1 performance-schema-max-table-instances -1 performance-schema-max-thread-classes 50 diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 8880c9f8ca9..bf5e267bf44 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -2867,9 +2867,9 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES SESSION_VALUE NULL -GLOBAL_VALUE 187 +GLOBAL_VALUE 188 GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 187 +DEFAULT_VALUE 188 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Maximum number of statement instruments. diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 11d6594ee80..8b062075db8 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -3063,9 +3063,9 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES SESSION_VALUE NULL -GLOBAL_VALUE 187 +GLOBAL_VALUE 188 GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 187 +DEFAULT_VALUE 188 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Maximum number of statement instruments. diff --git a/sql/item.cc b/sql/item.cc index afdef1ac57c..8db5cfc6442 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3347,7 +3347,7 @@ Item_param::Item_param(THD *thd, uint pos_in_query_arg): state(NO_VALUE), /* Don't pretend to be a literal unless value for this item is set. */ item_type(PARAM_ITEM), - indicators(0), indicator(STMT_INDICATOR_NONE), + indicator(STMT_INDICATOR_NONE), set_param_func(default_set_param_func), m_out_param_info(NULL), /* diff --git a/sql/item.h b/sql/item.h index 42e9fd94331..5ed3e8acb82 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2873,10 +2873,8 @@ public: }; /* - Used for bulk protocol. Indicates if we should expect - indicators byte before value of the parameter + Used for bulk protocol only. */ - my_bool indicators; enum enum_indicator_type indicator; /* diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 8e5dfb4f69c..24e4c07fdb9 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -697,9 +697,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, bool using_bulk_insert= 0; uint value_count; ulong counter = 1; - ulong iteration= 0; + /* counter of iteration in bulk PS operation*/ + ulonglong iteration= 0; ulonglong id; - ulong bulk_iterations= bulk_parameters_iterations(thd); COPY_INFO info; TABLE *table= 0; List_iterator_fast its(values_list); @@ -767,7 +767,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, DBUG_RETURN(TRUE); value_count= values->elements; - DBUG_ASSERT(bulk_iterations > 0); if (mysql_prepare_insert(thd, table_list, table, fields, values, update_fields, update_values, duplic, &unused_conds, FALSE)) @@ -939,6 +938,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, } do { + DBUG_PRINT("info", ("iteration %llu", iteration)); if (iteration && bulk_parameters_set(thd)) goto abort; @@ -1059,7 +1059,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, } its.rewind(); iteration++; - } while (iteration < bulk_iterations); + } while (bulk_parameters_iterations(thd)); values_loop_end: free_underlaid_joins(thd, &thd->lex->select_lex); @@ -1206,7 +1206,7 @@ values_loop_end: retval= thd->lex->explain->send_explain(thd); goto abort; } - if ((bulk_iterations * values_list.elements) == 1 && (!(thd->variables.option_bits & OPTION_WARNINGS) || + if ((iteration * values_list.elements) == 1 && (!(thd->variables.option_bits & OPTION_WARNINGS) || !thd->cuted_fields)) { my_ok(thd, info.copied + info.deleted + diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e97871e3dcf..412cd1dac70 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -391,7 +391,7 @@ const LEX_STRING command_name[257]={ { 0, 0 }, //247 { 0, 0 }, //248 { 0, 0 }, //249 - { 0, 0 }, //250 + { C_STRING_WITH_LEN("Bulk_execute") }, //250 { C_STRING_WITH_LEN("Slave_worker") }, //251 { C_STRING_WITH_LEN("Slave_IO") }, //252 { C_STRING_WITH_LEN("Slave_SQL") }, //253 @@ -1749,6 +1749,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } break; } + case COM_STMT_BULK_EXECUTE: + { + mysqld_stmt_bulk_execute(thd, packet, packet_length); + break; + } case COM_STMT_EXECUTE: { mysqld_stmt_execute(thd, packet, packet_length); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index cd330d8ee26..11274fbbaa2 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -164,7 +164,6 @@ public: Server_side_cursor *cursor; uchar *packet; uchar *packet_end; - ulong iterations; uint param_count; uint last_errno; uint flags; @@ -183,7 +182,9 @@ public: */ uint select_number_after_prepare; char last_error[MYSQL_ERRMSG_SIZE]; + my_bool iterations; my_bool start_param; + my_bool read_types; #ifndef EMBEDDED_LIBRARY bool (*set_params)(Prepared_statement *st, uchar *data, uchar *data_end, uchar *read_pos, String *expanded_query); @@ -213,11 +214,10 @@ public: uchar *packet_arg, uchar *packet_end_arg); bool execute_bulk_loop(String *expanded_query, bool open_cursor, - uchar *packet_arg, uchar *packet_end_arg, - ulong iterations); + uchar *packet_arg, uchar *packet_end_arg); bool execute_server_runnable(Server_runnable *server_runnable); my_bool set_bulk_parameters(bool reset); - ulong bulk_iterations(); + bool bulk_iterations() { return iterations; }; /* Destroy this statement */ void deallocate(); bool execute_immediate(const char *query, uint query_length); @@ -935,6 +935,7 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array, for (Item_param **it= begin; it < end; ++it) { Item_param *param= *it; + param->indicator= STMT_INDICATOR_NONE; // only for bulk parameters if (!param->has_long_data_value()) { if (is_param_null(null_array, (uint) (it - begin))) @@ -979,10 +980,7 @@ static bool insert_bulk_params(Prepared_statement *stmt, param->reset(); if (!param->has_long_data_value()) { - if (param->indicators) - param->indicator= (enum_indicator_type) *((*read_pos)++); - else - param->indicator= STMT_INDICATOR_NONE; + param->indicator= (enum_indicator_type) *((*read_pos)++); if ((*read_pos) > data_end) DBUG_RETURN(1); switch (param->indicator) @@ -993,6 +991,8 @@ static bool insert_bulk_params(Prepared_statement *stmt, param->set_param_func(param, read_pos, (uint) (data_end - (*read_pos))); if (param->has_no_value()) DBUG_RETURN(1); + if (param->convert_str_value(stmt->thd)) + DBUG_RETURN(1); /* out of memory */ break; case STMT_INDICATOR_NULL: param->set_null(); @@ -1011,6 +1011,36 @@ static bool insert_bulk_params(Prepared_statement *stmt, DBUG_RETURN(0); } +static bool set_conversion_functions(Prepared_statement *stmt, + uchar **data, uchar *data_end) +{ + uchar *read_pos= *data; + const uint signed_bit= 1 << 15; + DBUG_ENTER("set_conversion_functions"); + /* + First execute or types altered by the client, setup the + conversion routines for all parameters (one time) + */ + Item_param **it= stmt->param_array; + Item_param **end= it + stmt->param_count; + THD *thd= stmt->thd; + for (; it < end; ++it) + { + ushort typecode; + + if (read_pos >= data_end) + DBUG_RETURN(1); + + typecode= sint2korr(read_pos); + read_pos+= 2; + (**it).unsigned_flag= MY_TEST(typecode & signed_bit); + setup_one_conversion_function(thd, *it, (uchar) (typecode & 0xff)); + } + *data= read_pos; + DBUG_RETURN(0); +} + + static bool setup_conversion_functions(Prepared_statement *stmt, uchar **data, uchar *data_end, bool bulk_protocol= 0) @@ -1024,30 +1054,9 @@ static bool setup_conversion_functions(Prepared_statement *stmt, if (*read_pos++) //types supplied / first execute { - /* - First execute or types altered by the client, setup the - conversion routines for all parameters (one time) - */ - Item_param **it= stmt->param_array; - Item_param **end= it + stmt->param_count; - THD *thd= stmt->thd; - for (; it < end; ++it) - { - ushort typecode; - const uint signed_bit= 1 << 15; - const uint indicators_bit= 1 << 14; - - if (read_pos >= data_end) - DBUG_RETURN(1); - - typecode= sint2korr(read_pos); - read_pos+= 2; - (**it).unsigned_flag= MY_TEST(typecode & signed_bit); - if (bulk_protocol) - (**it).indicators= MY_TEST(typecode & indicators_bit); - setup_one_conversion_function(thd, *it, - (uchar) (typecode & 0xff)); - } + *data= read_pos; + bool res= set_conversion_functions(stmt, data, data_end); + DBUG_RETURN(res); } *data= read_pos; DBUG_RETURN(0); @@ -3032,6 +3041,14 @@ static void reset_stmt_params(Prepared_statement *stmt) } +static void mysql_stmt_execute_common(THD *thd, + ulong stmt_id, + uchar *packet, + uchar *packet_end, + ulong cursor_flags, + bool iteration, + bool types); + /** COM_STMT_EXECUTE handler: execute a previously prepared statement. @@ -3054,21 +3071,92 @@ void mysqld_stmt_execute(THD *thd, char *packet_arg, uint packet_length) uchar *packet= (uchar*)packet_arg; // GCC 4.0.1 workaround ulong stmt_id= uint4korr(packet); ulong flags= (ulong) packet[4]; -#ifndef EMBEDDED_LIBRARY - ulong iterations= uint4korr(packet + 5); -#else - ulong iterations= 0; // no support -#endif - /* Query text for binary, general or slow log, if any of them is open */ - String expanded_query; uchar *packet_end= packet + packet_length; - Prepared_statement *stmt; - Protocol *save_protocol= thd->protocol; - bool open_cursor; DBUG_ENTER("mysqld_stmt_execute"); packet+= 9; /* stmt_id + 5 bytes of flags */ + mysql_stmt_execute_common(thd, stmt_id, packet, packet_end, flags, FALSE, + FALSE); + DBUG_VOID_RETURN; +} + + +/** + COM_STMT_BULK_EXECUTE handler: execute a previously prepared statement. + + If there are any parameters, then replace parameter markers with the + data supplied from the client, and then execute the statement. + This function uses binary protocol to send a possible result set + to the client. + + @param thd current thread + @param packet_arg parameter types and data, if any + @param packet_length packet length, including the terminator character. + + @return + none: in case of success OK packet or a result set is sent to the + client, otherwise an error message is set in THD. +*/ + +void mysqld_stmt_bulk_execute(THD *thd, char *packet_arg, uint packet_length) +{ + uchar *packet= (uchar*)packet_arg; // GCC 4.0.1 workaround + ulong stmt_id= uint4korr(packet); + uint flags= (uint) uint2korr(packet + 4); + uchar *packet_end= packet + packet_length; + DBUG_ENTER("mysqld_stmt_execute_bulk"); + + if (!(thd->client_capabilities & + MARIADB_CLIENT_STMT_BULK_OPERATIONS)) + { + DBUG_PRINT("error", + ("An attempt to execute bulk operation without support")); + my_error(ER_UNSUPPORTED_PS, MYF(0)); + } + /* Check for implemented parameters */ + if (flags & (~STMT_BULK_FLAG_CLIENT_SEND_TYPES)) + { + DBUG_PRINT("error", ("unsupported bulk execute flags %x", flags)); + my_error(ER_UNSUPPORTED_PS, MYF(0)); + } + + /* stmt id and two bytes of flags */ + packet+= 4 + 2; + mysql_stmt_execute_common(thd, stmt_id, packet, packet_end, 0, TRUE, + (flags & STMT_BULK_FLAG_CLIENT_SEND_TYPES)); + DBUG_VOID_RETURN; +} + + +/** + Common part of prepared statement execution + + @param thd THD handle + @param stmt_id id of the prepared statement + @param paket packet with parameters to bind + @param packet_end pointer to the byte after parameters end + @param cursor_flags cursor flags + @param bulk_op id it bulk operation + @param read_types flag say that types muast been read +*/ + +static void mysql_stmt_execute_common(THD *thd, + ulong stmt_id, + uchar *packet, + uchar *packet_end, + ulong cursor_flags, + bool bulk_op, + bool read_types) +{ + /* Query text for binary, general or slow log, if any of them is open */ + String expanded_query; + Prepared_statement *stmt; + Protocol *save_protocol= thd->protocol; + bool open_cursor; + DBUG_ENTER("mysqld_stmt_execute_common"); + DBUG_ASSERT((!read_types) || (read_types && bulk_op)); + /* First of all clear possible warnings from the previous command */ thd->reset_for_next_command(); @@ -3079,21 +3167,21 @@ void mysqld_stmt_execute(THD *thd, char *packet_arg, uint packet_length) llstr(stmt_id, llbuf), "mysqld_stmt_execute"); DBUG_VOID_RETURN; } + stmt->read_types= read_types; #if defined(ENABLED_PROFILING) thd->profiling.set_query_source(stmt->query(), stmt->query_length()); #endif DBUG_PRINT("exec_query", ("%s", stmt->query())); - DBUG_PRINT("info",("stmt: %p iterations: %lu", stmt, iterations)); + DBUG_PRINT("info",("stmt: %p bulk_op %d", stmt, bulk_op)); - open_cursor= MY_TEST(flags & (ulong) CURSOR_TYPE_READ_ONLY); + open_cursor= MY_TEST(cursor_flags & (ulong) CURSOR_TYPE_READ_ONLY); thd->protocol= &thd->protocol_binary; - if (iterations <= 1) + if (!bulk_op) stmt->execute_loop(&expanded_query, open_cursor, packet, packet_end); else - stmt->execute_bulk_loop(&expanded_query, open_cursor, packet, packet_end, - iterations); + stmt->execute_bulk_loop(&expanded_query, open_cursor, packet, packet_end); thd->protocol= save_protocol; sp_cache_enforce_limit(thd->sp_proc_cache, stored_program_cache_size); @@ -3600,11 +3688,12 @@ Prepared_statement::Prepared_statement(THD *thd_arg) cursor(0), packet(0), packet_end(0), - iterations(0), param_count(0), last_errno(0), flags((uint) IS_IN_USE), + iterations(0), start_param(0), + read_types(0), m_sql_mode(thd->variables.sql_mode) { init_sql_alloc(&main_mem_root, thd_arg->variables.query_alloc_block_size, @@ -3641,7 +3730,7 @@ void Prepared_statement::setup_set_params() set_params_from_actual_params= insert_params_from_actual_params_with_log; #ifndef EMBEDDED_LIBRARY set_params= insert_params_with_log; - set_bulk_params= insert_bulk_params; // TODO: add binlog support + set_bulk_params= insert_bulk_params; // RBR is on for bulk operation #else //TODO: add bulk support for bulk parameters set_params_data= emb_insert_params_with_log; @@ -4023,7 +4112,7 @@ Prepared_statement::execute_loop(String *expanded_query, Reprepare_observer reprepare_observer; bool error; int reprepare_attempt= 0; - iterations= 0; + iterations= FALSE; /* - In mysql_sql_stmt_execute() we hide all "external" Items @@ -4126,11 +4215,11 @@ my_bool bulk_parameters_set(THD *thd) DBUG_RETURN(FALSE); } -ulong bulk_parameters_iterations(THD *thd) +my_bool bulk_parameters_iterations(THD *thd) { Prepared_statement *stmt= (Prepared_statement *) thd->bulk_param; if (!stmt) - return 1; + return FALSE; return stmt->bulk_iterations(); } @@ -4138,7 +4227,8 @@ ulong bulk_parameters_iterations(THD *thd) my_bool Prepared_statement::set_bulk_parameters(bool reset) { DBUG_ENTER("Prepared_statement::set_bulk_parameters"); - DBUG_PRINT("info", ("iteration: %lu", iterations)); + DBUG_PRINT("info", ("iteration: %d", iterations)); + if (iterations) { #ifndef EMBEDDED_LIBRARY @@ -4152,31 +4242,24 @@ my_bool Prepared_statement::set_bulk_parameters(bool reset) reset_stmt_params(this); DBUG_RETURN(true); } - iterations--; + if (packet >= packet_end) + iterations= FALSE; } start_param= 0; DBUG_RETURN(false); } -ulong Prepared_statement::bulk_iterations() -{ - if (iterations) - return iterations; - return start_param ? 1 : 0; -} - bool Prepared_statement::execute_bulk_loop(String *expanded_query, bool open_cursor, uchar *packet_arg, - uchar *packet_end_arg, - ulong iterations_arg) + uchar *packet_end_arg) { Reprepare_observer reprepare_observer; bool error= 0; packet= packet_arg; packet_end= packet_end_arg; - iterations= iterations_arg; + iterations= TRUE; start_param= true; #ifndef DBUG_OFF Item *free_list_state= thd->free_list; @@ -4190,16 +4273,26 @@ Prepared_statement::execute_bulk_loop(String *expanded_query, thd->set_bulk_execution(0); return TRUE; } + /* Check for non zero parameter count*/ + if (param_count == 0) + { + DBUG_PRINT("error", ("Statement with no parameters for bulk execution.")); + my_error(ER_UNSUPPORTED_PS, MYF(0)); + thd->set_bulk_execution(0); + return TRUE; + } if (!(sql_command_flags[lex->sql_command] & CF_SP_BULK_SAFE)) { + DBUG_PRINT("error", ("Command is not supported in bulk execution.")); my_error(ER_UNSUPPORTED_PS, MYF(0)); thd->set_bulk_execution(0); return TRUE; } #ifndef EMBEDDED_LIBRARY - if (setup_conversion_functions(this, &packet, packet_end, TRUE)) + if (read_types && + set_conversion_functions(this, &packet, packet_end)) #else // bulk parameters are not supported for embedded, so it will an error #endif @@ -4210,6 +4303,7 @@ Prepared_statement::execute_bulk_loop(String *expanded_query, thd->set_bulk_execution(0); return true; } + read_types= FALSE; #ifdef NOT_YET_FROM_MYSQL_5_6 if (unlikely(thd->security_ctx->password_expired && diff --git a/sql/sql_prepare.h b/sql/sql_prepare.h index 820cb43e6d5..203b37b3b26 100644 --- a/sql/sql_prepare.h +++ b/sql/sql_prepare.h @@ -72,6 +72,7 @@ private: void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length); void mysqld_stmt_execute(THD *thd, char *packet, uint packet_length); +void mysqld_stmt_execute_bulk(THD *thd, char *packet, uint packet_length); void mysqld_stmt_bulk_execute(THD *thd, char *packet, uint packet_length); void mysqld_stmt_close(THD *thd, char *packet); void mysql_sql_stmt_prepare(THD *thd); @@ -83,7 +84,7 @@ void mysqld_stmt_reset(THD *thd, char *packet); void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length); void reinit_stmt_before_use(THD *thd, LEX *lex); -ulong bulk_parameters_iterations(THD *thd); +my_bool bulk_parameters_iterations(THD *thd); my_bool bulk_parameters_set(THD *thd); /** Execute a fragment of server code in an isolated context, so that From 227bfe44668602858f084bf9942d4f89228799ea Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 14 Jun 2017 14:39:51 +0200 Subject: [PATCH 5/9] new connector version which correspond BULK command --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index 467a193b399..ff4bfdf1caf 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit 467a193b399dfda41d87368a898e9550d754fa14 +Subproject commit ff4bfdf1caf2e0a47382fdbe6d796d0e63ec1062 From 88b961816e90c57b0f6f166e6c7650a1ae540751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 15 Jun 2017 12:40:24 +0300 Subject: [PATCH 6/9] Re-record a failing test, likely related to MDEV-12610 --- .../encryption/r/innodb_lotoftables.result | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/mysql-test/suite/encryption/r/innodb_lotoftables.result b/mysql-test/suite/encryption/r/innodb_lotoftables.result index b7cfdd2db9d..86ab60e7836 100644 --- a/mysql-test/suite/encryption/r/innodb_lotoftables.result +++ b/mysql-test/suite/encryption/r/innodb_lotoftables.result @@ -12,13 +12,13 @@ create database innodb_encrypted_1; use innodb_encrypted_1; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 3 set autocommit=0; set autocommit=1; commit work; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 3 # should be 100 SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE NAME LIKE 'innodb_encrypted%'; COUNT(*) @@ -88,47 +88,47 @@ Innodb_pages0_read 3 # Restart Success! show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 3 show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 3 use test; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 3 use innodb_encrypted_1; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 3 use innodb_encrypted_2; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 3 use innodb_encrypted_3; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 3 use innodb_encrypted_1; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 3 show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 101 +Innodb_pages0_read 103 use innodb_encrypted_2; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 101 +Innodb_pages0_read 103 show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 201 +Innodb_pages0_read 203 use innodb_encrypted_3; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 201 +Innodb_pages0_read 203 show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 301 +Innodb_pages0_read 303 SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 AND NAME LIKE 'innodb_encrypted%'; COUNT(*) 100 From 58f87a41bd8de7370cc05c41977fadc685826c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 15 Jun 2017 12:41:02 +0300 Subject: [PATCH 7/9] Remove some fields from dict_table_t dict_table_t::thd: Remove. This was only used by btr_root_block_get() for reporting decryption failures, and it was only assigned by ha_innobase::open(), and never cleared. This could mean that if a connection is closed, the pointer would become stale, and the server could crash while trying to report the error. It could also mean that an error is being reported to the wrong client. It is better to use current_thd in this case, even though it could mean that if the code is invoked from an InnoDB background operation, there would be no connection to which to send the error message. Remove dict_table_t::crypt_data and dict_table_t::page_0_read. These fields were never read. fil_open_single_table_tablespace(): Remove the parameter "table". --- storage/innobase/btr/btr0btr.cc | 3 ++- storage/innobase/dict/dict0load.cc | 4 ++-- storage/innobase/fil/fil0fil.cc | 18 +----------------- storage/innobase/handler/ha_innodb.cc | 2 -- storage/innobase/include/dict0mem.h | 4 ---- storage/innobase/include/fil0fil.h | 3 +-- storage/innobase/row/row0import.cc | 2 +- storage/innobase/row/row0mysql.cc | 12 ------------ storage/xtradb/btr/btr0btr.cc | 3 ++- storage/xtradb/dict/dict0load.cc | 4 ++-- storage/xtradb/fil/fil0fil.cc | 18 +----------------- storage/xtradb/handler/ha_innodb.cc | 2 -- storage/xtradb/include/dict0mem.h | 4 ---- storage/xtradb/include/fil0fil.h | 3 +-- storage/xtradb/row/row0import.cc | 2 +- storage/xtradb/row/row0mysql.cc | 12 ------------ 16 files changed, 14 insertions(+), 82 deletions(-) diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index b7afcf12b39..c519baef58c 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -740,7 +740,8 @@ btr_root_block_get( if (index && index->table) { index->table->file_unreadable = true; - ib_push_warning(index->table->thd, DB_DECRYPTION_FAILED, + ib_push_warning( + static_cast(NULL), DB_DECRYPTION_FAILED, "Table %s in tablespace %lu is encrypted but encryption service or" " used key_id is not available. " " Can't continue reading table.", diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index a1d18690476..4a2b6d43bbd 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -1173,7 +1173,7 @@ loop: dberr_t err = fil_open_single_table_tablespace( read_page_0, srv_read_only_mode ? false : true, space_id, dict_tf_to_fsp_flags(flags), - name, filepath, NULL); + name, filepath); if (err != DB_SUCCESS) { ib_logf(IB_LOG_LEVEL_ERROR, @@ -2415,7 +2415,7 @@ err_exit: err = fil_open_single_table_tablespace( true, false, table->space, dict_tf_to_fsp_flags(table->flags), - name, filepath, table); + name, filepath); if (err != DB_SUCCESS) { /* We failed to find a sensible diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index ffb01312fdb..d78a8b20f33 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -4036,8 +4036,7 @@ fil_open_single_table_tablespace( ulint flags, /*!< in: expected FSP_SPACE_FLAGS */ const char* tablename, /*!< in: table name in the databasename/tablename format */ - const char* path_in, /*!< in: tablespace filepath */ - dict_table_t* table) /*!< in: table */ + const char* path_in) /*!< in: table */ { dberr_t err = DB_SUCCESS; bool dict_filepath_same_as_default = false; @@ -4147,11 +4146,6 @@ fil_open_single_table_tablespace( #endif /* UNIV_LOG_ARCHIVE */ NULL, &def.crypt_data); - if (table) { - table->crypt_data = def.crypt_data; - table->page_0_read = true; - } - def.valid = !def.check_msg && def.id == id && fsp_flags_match(flags, def.flags); @@ -4174,11 +4168,6 @@ fil_open_single_table_tablespace( #endif /* UNIV_LOG_ARCHIVE */ NULL, &remote.crypt_data); - if (table) { - table->crypt_data = remote.crypt_data; - table->page_0_read = true; - } - /* Validate this single-table-tablespace with SYS_TABLES. */ remote.valid = !remote.check_msg && remote.id == id && fsp_flags_match(flags, remote.flags); @@ -4203,11 +4192,6 @@ fil_open_single_table_tablespace( #endif /* UNIV_LOG_ARCHIVE */ NULL, &dict.crypt_data); - if (table) { - table->crypt_data = dict.crypt_data; - table->page_0_read = true; - } - /* Validate this single-table-tablespace with SYS_TABLES. */ dict.valid = !dict.check_msg && dict.id == id && fsp_flags_match(flags, dict.flags); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index bd89744c1f0..6c43e637318 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5860,8 +5860,6 @@ table_opened: innobase_copy_frm_flags_from_table_share(ib_table, table->s); - ib_table->thd = (void*)thd; - /* No point to init any statistics if tablespace is still encrypted. */ if (ib_table->is_readable()) { dict_stats_init(ib_table); diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index cea75d6ab47..1c0f4d73006 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -1032,10 +1032,6 @@ struct dict_table_t{ table_id_t id; /*!< id of the table */ mem_heap_t* heap; /*!< memory heap */ char* name; /*!< table name */ - void* thd; /*!< thd */ - bool page_0_read; /*!< true if page 0 has - been already read */ - fil_space_crypt_t *crypt_data; /*!< crypt data if present */ const char* dir_path_of_temp_table;/*!< NULL or the directory path where a TEMPORARY table that was explicitly created by a user should be placed if diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index e16c7cb102e..8033d0cc839 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1045,8 +1045,7 @@ fil_open_single_table_tablespace( ulint flags, /*!< in: expected FSP_SPACE_FLAGS */ const char* tablename, /*!< in: table name in the databasename/tablename format */ - const char* filepath, /*!< in: tablespace filepath */ - dict_table_t* table) /*!< in: table */ + const char* filepath) /*!< in: tablespace filepath */ __attribute__((nonnull(5), warn_unused_result)); #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index f0db79be17e..43830725978 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -3617,7 +3617,7 @@ row_import_for_mysql( err = fil_open_single_table_tablespace( true, true, table->space, dict_tf_to_fsp_flags(table->flags), - table->name, filepath, table); + table->name, filepath); DBUG_EXECUTE_IF("ib_import_open_tablespace_failure", err = DB_TABLESPACE_NOT_FOUND;); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 82938995e93..1d64d66cd49 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -4242,18 +4242,6 @@ row_drop_table_for_mysql( rw_lock_x_unlock(dict_index_get_lock(index)); } - /* If table has not yet have crypt_data, try to read it to - make freeing the table easier. */ - if (!table->crypt_data) { - - if (fil_space_t* space = fil_space_acquire_silent(table->space)) { - /* We use crypt data in dict_table_t in ha_innodb.cc - to push warnings to user thread. */ - table->crypt_data = space->crypt_data; - fil_space_release(space); - } - } - /* We use the private SQL parser of Innobase to generate the query graphs needed in deleting the dictionary data from system tables in Innobase. Deleting a row from SYS_INDEXES table also diff --git a/storage/xtradb/btr/btr0btr.cc b/storage/xtradb/btr/btr0btr.cc index e66599e206d..85a083aaee0 100644 --- a/storage/xtradb/btr/btr0btr.cc +++ b/storage/xtradb/btr/btr0btr.cc @@ -745,7 +745,8 @@ btr_root_block_get( if (index && index->table) { index->table->file_unreadable = true; - ib_push_warning(index->table->thd, DB_DECRYPTION_FAILED, + ib_push_warning( + static_cast(NULL), DB_DECRYPTION_FAILED, "Table %s in tablespace %lu is encrypted but encryption service or" " used key_id is not available. " " Can't continue reading table.", diff --git a/storage/xtradb/dict/dict0load.cc b/storage/xtradb/dict/dict0load.cc index dc3f9c85bba..6171bbd80d0 100644 --- a/storage/xtradb/dict/dict0load.cc +++ b/storage/xtradb/dict/dict0load.cc @@ -1193,7 +1193,7 @@ loop: dberr_t err = fil_open_single_table_tablespace( read_page_0, srv_read_only_mode ? false : true, space_id, dict_tf_to_fsp_flags(flags), - name, filepath, NULL); + name, filepath); if (err != DB_SUCCESS) { ib_logf(IB_LOG_LEVEL_ERROR, @@ -2437,7 +2437,7 @@ err_exit: err = fil_open_single_table_tablespace( true, false, table->space, dict_tf_to_fsp_flags(table->flags), - name, filepath, table); + name, filepath); if (err != DB_SUCCESS) { /* We failed to find a sensible diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index 12048bc479f..fdd09a6034e 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -4229,8 +4229,7 @@ fil_open_single_table_tablespace( ulint flags, /*!< in: expected FSP_SPACE_FLAGS */ const char* tablename, /*!< in: table name in the databasename/tablename format */ - const char* path_in, /*!< in: tablespace filepath */ - dict_table_t* table) /*!< in: table */ + const char* path_in) /*!< in: table */ { dberr_t err = DB_SUCCESS; bool dict_filepath_same_as_default = false; @@ -4339,11 +4338,6 @@ fil_open_single_table_tablespace( def.file, false, &def.flags, &def.id, NULL, &def.crypt_data); - if (table) { - table->crypt_data = def.crypt_data; - table->page_0_read = true; - } - def.valid = !def.check_msg && def.id == id && fsp_flags_match(flags, def.flags); @@ -4363,11 +4357,6 @@ fil_open_single_table_tablespace( remote.file, false, &remote.flags, &remote.id, NULL, &remote.crypt_data); - if (table) { - table->crypt_data = remote.crypt_data; - table->page_0_read = true; - } - /* Validate this single-table-tablespace with SYS_TABLES. */ remote.valid = !remote.check_msg && remote.id == id && fsp_flags_match(flags, remote.flags); @@ -4389,11 +4378,6 @@ fil_open_single_table_tablespace( dict.file, false, &dict.flags, &dict.id, NULL, &dict.crypt_data); - if (table) { - table->crypt_data = dict.crypt_data; - table->page_0_read = true; - } - /* Validate this single-table-tablespace with SYS_TABLES. */ dict.valid = !dict.check_msg && dict.id == id && fsp_flags_match(flags, dict.flags); diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index ee1e306b441..eb02ed6699e 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -6429,8 +6429,6 @@ table_opened: innobase_copy_frm_flags_from_table_share(ib_table, table->s); - ib_table->thd = (void*)thd; - /* No point to init any statistics if tablespace is still encrypted. */ if (ib_table->is_readable()) { dict_stats_init(ib_table); diff --git a/storage/xtradb/include/dict0mem.h b/storage/xtradb/include/dict0mem.h index a32581a0e90..2a4422fc18b 100644 --- a/storage/xtradb/include/dict0mem.h +++ b/storage/xtradb/include/dict0mem.h @@ -1048,10 +1048,6 @@ struct dict_table_t{ table_id_t id; /*!< id of the table */ mem_heap_t* heap; /*!< memory heap */ char* name; /*!< table name */ - void* thd; /*!< thd */ - bool page_0_read; /*!< true if page 0 has - been already read */ - fil_space_crypt_t *crypt_data; /*!< crypt data if present */ const char* dir_path_of_temp_table;/*!< NULL or the directory path where a TEMPORARY table that was explicitly created by a user should be placed if diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h index a09833c3a73..6eab5db6883 100644 --- a/storage/xtradb/include/fil0fil.h +++ b/storage/xtradb/include/fil0fil.h @@ -1043,8 +1043,7 @@ fil_open_single_table_tablespace( ulint flags, /*!< in: expected FSP_SPACE_FLAGS */ const char* tablename, /*!< in: table name in the databasename/tablename format */ - const char* filepath, /*!< in: tablespace filepath */ - dict_table_t* table) /*!< in: table */ + const char* filepath) /*!< in: tablespace filepath */ __attribute__((nonnull(5), warn_unused_result)); #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/xtradb/row/row0import.cc b/storage/xtradb/row/row0import.cc index 2f7aece665a..86b2d782b7b 100644 --- a/storage/xtradb/row/row0import.cc +++ b/storage/xtradb/row/row0import.cc @@ -3618,7 +3618,7 @@ row_import_for_mysql( err = fil_open_single_table_tablespace( true, true, table->space, dict_tf_to_fsp_flags(table->flags), - table->name, filepath, table); + table->name, filepath); DBUG_EXECUTE_IF("ib_import_open_tablespace_failure", err = DB_TABLESPACE_NOT_FOUND;); diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc index 59568f5c91b..0079fc79a0e 100644 --- a/storage/xtradb/row/row0mysql.cc +++ b/storage/xtradb/row/row0mysql.cc @@ -4272,18 +4272,6 @@ row_drop_table_for_mysql( rw_lock_x_unlock(dict_index_get_lock(index)); } - /* If table has not yet have crypt_data, try to read it to - make freeing the table easier. */ - if (!table->crypt_data) { - - if (fil_space_t* space = fil_space_acquire_silent(table->space)) { - /* We use crypt data in dict_table_t in ha_innodb.cc - to push warnings to user thread. */ - table->crypt_data = space->crypt_data; - fil_space_release(space); - } - } - /* We use the private SQL parser of Innobase to generate the query graphs needed in deleting the dictionary data from system tables in Innobase. Deleting a row from SYS_INDEXES table also From 72378a25830184f91005be7e80cfb28381c79f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 14 Jun 2017 14:08:49 +0300 Subject: [PATCH 8/9] MDEV-12873 InnoDB SYS_TABLES.TYPE incompatibility for PAGE_COMPRESSED=YES in MariaDB 10.2.2 to 10.2.6 Remove the SHARED_SPACE flag that was erroneously introduced in MariaDB 10.2.2, and shift the SYS_TABLES.TYPE flags back to where they were before MariaDB 10.2.2. While doing this, ensure that tables created with affected MariaDB versions can be loaded, and also ensure that tables created with MySQL 5.7 using the TABLESPACE attribute cannot be loaded. MariaDB 10.2.2 picked the SHARED_SPACE flag from MySQL 5.7, shifting the MariaDB 10.1 flags PAGE_COMPRESSION, PAGE_COMPRESSION_LEVEL, ATOMIC_WRITES by one bit. The SHARED_SPACE flag would always be written as 0 by MariaDB, because MariaDB does not support CREATE TABLESPACE or CREATE TABLE...TABLESPACE for InnoDB. So, instead of the bits AALLLLCxxxxxxx we would have AALLLLC0xxxxxxx if the table was created with MariaDB 10.2.2 to 10.2.6. (AA=ATOMIC_WRITES, LLLL=PAGE_COMPRESSION_LEVEL, C=PAGE_COMPRESSED, xxxxxxx=7 bits that were not moved.) PAGE_COMPRESSED=NO implies LLLLC=00000. That is not a problem. If someone created a table in MariaDB 10.2.2 or 10.2.3 with the attribute ATOMIC_WRITES=OFF (value 2; AA=10) and without PAGE_COMPRESSED=YES or PAGE_COMPRESSION_LEVEL, the table should be rejected. We ignore this problem, because it should be unlikely for anyone to specify ATOMIC_WRITES=OFF, and because 10.2.2 and 10.2.2 were not mature releases. The value ATOMIC_WRITES=ON (1) would be interpreted as ATOMIC_WRITES=OFF, but starting with MariaDB 10.2.4 the ATOMIC_WRITES attribute is ignored. PAGE_COMPRESSED=YES implies that PAGE_COMPRESSION_LEVEL be between 1 and 9 and that ROW_FORMAT be COMPACT or DYNAMIC. Thus, the affected wrong bit pattern in SYS_TABLES.TYPE is of the form AALLLL10DB00001 where D signals the presence of a DATA DIRECTORY attribute and B is 1 for ROW_FORMAT=DYNAMIC and 0 for ROW_FORMAT=COMPACT. We must interpret this bit pattern as AALLLL1DB00001 (discarding the extraneous 0 bit). dict_sys_tables_rec_read(): Adjust the affected bit pattern when reading the SYS_TABLES.TYPE column. In case of invalid flags, report both SYS_TABLES.TYPE (after possible adjustment) and SYS_TABLES.MIX_LEN. dict_load_table_one(): Replace an unreachable condition on !dict_tf2_is_valid() with a debug assertion. The flags will already have been validated by dict_sys_tables_rec_read(); if that validation fails, dict_load_table_low() will have failed. fil_ibd_create(): Shorten an error message about a file pre-existing. Datafile::validate_to_dd(): Clarify an error message about tablespace flags mismatch. ha_innobase::open(): Remove an unnecessary warning message. dict_tf_is_valid(): Simplify and stricten the logic. Validate the values of PAGE_COMPRESSION. Remove error log output; let the callers handle that. DICT_TF_BITS: Remove ATOMIC_WRITES, PAGE_ENCRYPTION, PAGE_ENCRYPTION_KEY. The ATOMIC_WRITES is ignored once the SYS_TABLES.TYPE has been validated; there is no need to store it in dict_table_t::flags. The PAGE_ENCRYPTION and PAGE_ENCRYPTION_KEY are unused since MariaDB 10.1.4 (the GA release was 10.1.8). DICT_TF_BIT_MASK: Remove (unused). FSP_FLAGS_MEM_ATOMIC_WRITES: Remove (the flags are never read). row_import_read_v1(): Display an error if dict_tf_is_valid() fails. --- .../innodb/r/row_format_redundant.result | 2 +- .../suite/innodb/t/row_format_redundant.test | 4 +- storage/innobase/dict/dict0load.cc | 98 +++++++++++++++---- storage/innobase/fil/fil0fil.cc | 10 +- storage/innobase/fsp/fsp0file.cc | 11 +-- storage/innobase/handler/ha_innodb.cc | 4 - storage/innobase/include/dict0dict.ic | 96 +++++++----------- storage/innobase/include/dict0mem.h | 50 +--------- storage/innobase/include/fsp0types.h | 12 +-- storage/innobase/row/row0import.cc | 20 ++-- 10 files changed, 140 insertions(+), 167 deletions(-) diff --git a/mysql-test/suite/innodb/r/row_format_redundant.result b/mysql-test/suite/innodb/r/row_format_redundant.result index 45dfdf01218..2bc8769092f 100644 --- a/mysql-test/suite/innodb/r/row_format_redundant.result +++ b/mysql-test/suite/innodb/r/row_format_redundant.result @@ -72,7 +72,7 @@ DROP TABLE t1; Warnings: Warning 1932 Table 'test.t1' doesn't exist in engine DROP TABLE t2,t3; -FOUND 49 /\[ERROR\] InnoDB: Table `test`\.`t1` in InnoDB data dictionary contains invalid flags\. SYS_TABLES.MIX_LEN=255\b/ in mysqld.1.err +FOUND 49 /\[ERROR\] InnoDB: Table `test`\.`t1` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=1 SYS_TABLES\.MIX_LEN=255\b/ in mysqld.1.err ib_buffer_pool ib_logfile0 ib_logfile1 diff --git a/mysql-test/suite/innodb/t/row_format_redundant.test b/mysql-test/suite/innodb/t/row_format_redundant.test index f8e25b373de..af3fe3b52cf 100644 --- a/mysql-test/suite/innodb/t/row_format_redundant.test +++ b/mysql-test/suite/innodb/t/row_format_redundant.test @@ -4,7 +4,7 @@ --disable_query_log call mtr.add_suppression("InnoDB: Table `mysql`\\.`innodb_table_stats` not found"); -call mtr.add_suppression("InnoDB: Table `test`.`t1` in InnoDB data dictionary contains invalid flags. SYS_TABLES.MIX_LEN=255"); +call mtr.add_suppression("InnoDB: Table `test`.`t1` in InnoDB data dictionary contains invalid flags. SYS_TABLES\\.TYPE=1 SYS_TABLES\\.MIX_LEN=255\\r?$"); call mtr.add_suppression("InnoDB: Parent table of FTS auxiliary table test/FTS_.* not found"); call mtr.add_suppression("InnoDB: Cannot open table test/t1 from the internal data dictionary"); call mtr.add_suppression("InnoDB: Table `test`.`t1` does not exist in the InnoDB internal data dictionary though MariaDB is trying to (rename|drop)"); @@ -141,7 +141,7 @@ RENAME TABLE t1 TO tee_one; DROP TABLE t1; DROP TABLE t2,t3; ---let SEARCH_PATTERN= \[ERROR\] InnoDB: Table `test`\.`t1` in InnoDB data dictionary contains invalid flags\. SYS_TABLES.MIX_LEN=255\b +--let SEARCH_PATTERN= \[ERROR\] InnoDB: Table `test`\.`t1` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=1 SYS_TABLES\.MIX_LEN=255\b --source include/search_pattern_in_file.inc --let $restart_parameters= diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 0ca9ebfc622..5c8449512e6 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -1170,6 +1170,80 @@ dict_sys_tables_rec_read( ut_a(len == 4); type = mach_read_from_4(field); + /* Handle MDEV-12873 InnoDB SYS_TABLES.TYPE incompatibility + for PAGE_COMPRESSED=YES in MariaDB 10.2.2 to 10.2.6. + + MariaDB 10.2.2 introduced the SHARED_SPACE flag from MySQL 5.7, + shifting the flags PAGE_COMPRESSION, PAGE_COMPRESSION_LEVEL, + ATOMIC_WRITES by one bit. The SHARED_SPACE flag would always + be written as 0 by MariaDB, because MariaDB does not support + CREATE TABLESPACE or CREATE TABLE...TABLESPACE for InnoDB. + + So, instead of the bits AALLLLCxxxxxxx we would have + AALLLLC0xxxxxxx if the table was created with MariaDB 10.2.2 + to 10.2.6. (AA=ATOMIC_WRITES, LLLL=PAGE_COMPRESSION_LEVEL, + C=PAGE_COMPRESSED, xxxxxxx=7 bits that were not moved.) + + The case LLLLC=00000 is not a problem. The problem is the case + AALLLL10DB00001 where D is the (mostly ignored) DATA_DIRECTORY + flag and B is the ATOMIC_BLOBS flag (1 for ROW_FORMAT=DYNAMIC + and 0 for ROW_FORMAT=COMPACT in this case). Other low-order + bits must be so, because PAGE_COMPRESSED=YES is only allowed + for ROW_FORMAT=DYNAMIC and ROW_FORMAT=COMPACT, not for + ROW_FORMAT=REDUNDANT or ROW_FORMAT=COMPRESSED. + + Starting with MariaDB 10.2.4, the flags would be + 00LLLL10DB00001, because ATOMIC_WRITES is always written as 0. + + We will concentrate on the PAGE_COMPRESSION_LEVEL and + PAGE_COMPRESSED=YES. PAGE_COMPRESSED=NO implies + PAGE_COMPRESSION_LEVEL=0, and in that case all the affected + bits will be 0. For PAGE_COMPRESSED=YES, the values 1..9 are + allowed for PAGE_COMPRESSION_LEVEL. That is, we must interpret + the bits AALLLL10DB00001 as AALLLL1DB00001. + + If someone created a table in MariaDB 10.2.2 or 10.2.3 with + the attribute ATOMIC_WRITES=OFF (value 2) and without + PAGE_COMPRESSED=YES or PAGE_COMPRESSION_LEVEL, that should be + rejected. The value ATOMIC_WRITES=ON (1) would look like + ATOMIC_WRITES=OFF, but it would be ignored starting with + MariaDB 10.2.4. */ + compile_time_assert(DICT_TF_POS_PAGE_COMPRESSION == 7); + compile_time_assert(DICT_TF_POS_UNUSED == 14); + + if ((type & 0x19f) != 0x101) { + /* The table cannot have been created with MariaDB + 10.2.2 to 10.2.6, because they would write the + low-order bits of SYS_TABLES.TYPE as 0b10xx00001 for + PAGE_COMPRESSED=YES. No adjustment is applicable. */ + } else if (type >= 3 << 13) { + /* 10.2.2 and 10.2.3 write ATOMIC_WRITES less than 3, + and no other flags above that can be set for the + SYS_TABLES.TYPE to be in the 10.2.2..10.2.6 format. + This would in any case be invalid format for 10.2 and + earlier releases. */ + ut_ad(ULINT_UNDEFINED == dict_sys_tables_type_validate( + type, DICT_N_COLS_COMPACT)); + } else { + /* SYS_TABLES.TYPE is of the form AALLLL10DB00001. We + must still validate that the LLLL bits are between 0 + and 9 before we can discard the extraneous 0 bit. */ + ut_ad(!DICT_TF_GET_PAGE_COMPRESSION(type)); + + if ((((type >> 9) & 0xf) - 1) < 9) { + ut_ad(DICT_TF_GET_PAGE_COMPRESSION_LEVEL(type) & 1); + + type = (type & 0x7fU) | (type >> 1 & ~0x7fU); + + ut_ad(DICT_TF_GET_PAGE_COMPRESSION(type)); + ut_ad(DICT_TF_GET_PAGE_COMPRESSION_LEVEL(type) >= 1); + ut_ad(DICT_TF_GET_PAGE_COMPRESSION_LEVEL(type) <= 9); + } else { + ut_ad(ULINT_UNDEFINED == dict_sys_tables_type_validate( + type, DICT_N_COLS_COMPACT)); + } + } + /* The low order bit of SYS_TABLES.TYPE is always set to 1. But in dict_table_t::flags the low order bit is used to determine if the row format is Redundant (0) or Compact (1) when the format is Antelope. @@ -1211,7 +1285,8 @@ dict_sys_tables_rec_read( if (!dict_tf2_is_valid(*flags, *flags2)) { ib::error() << "Table " << table_name << " in InnoDB" " data dictionary contains invalid flags." - " SYS_TABLES.MIX_LEN=" << *flags2; + " SYS_TABLES.TYPE=" << type + << " SYS_TABLES.MIX_LEN=" << *flags2; return(false); } @@ -2541,8 +2616,7 @@ dict_load_table_low(table_name_t& name, const rec_t* rec, dict_table_t** table) ulint flags2; ulint n_v_col; - const char* error_text = dict_sys_tables_rec_check(rec); - if (error_text != NULL) { + if (const char* error_text = dict_sys_tables_rec_check(rec)) { return(error_text); } @@ -2802,7 +2876,6 @@ dict_load_table_one( const rec_t* rec; const byte* field; ulint len; - const char* err_msg; mtr_t mtr; DBUG_ENTER("dict_load_table_one"); @@ -2859,9 +2932,7 @@ err_exit: goto err_exit; } - err_msg = dict_load_table_low(name, rec, &table); - - if (err_msg) { + if (const char* err_msg = dict_load_table_low(name, rec, &table)) { if (err_msg != dict_load_table_flags) { ib::error() << err_msg; } @@ -2885,6 +2956,8 @@ err_exit: mem_heap_empty(heap); + ut_ad(dict_tf2_is_valid(table->flags, table->flags2)); + /* If there is no tablespace for the table then we only need to load the index definitions. So that we can IMPORT the tablespace later. When recovering table locks for resurrected incomplete @@ -2920,17 +2993,6 @@ err_exit: } } - if (!dict_tf2_is_valid(table->flags, table->flags2)) { - ib::error() << "Table " << table->name << " in InnoDB" - " data dictionary contains invalid flags." - " SYS_TABLES.MIX_LEN=" << table->flags2; - table->flags2 &= ~DICT_TF2_TEMPORARY; - dict_table_remove_from_cache(table); - table = NULL; - err = DB_FAIL; - goto func_exit; - } - /* Initialize table foreign_child value. Its value could be changed when dict_load_foreigns() is called below */ table->fk_max_recusive_level = 0; diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 2cbc863102c..cc03524dbbc 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -3819,18 +3819,12 @@ fil_ibd_create( ib::error() << "Cannot create file '" << path << "'"; if (error == OS_FILE_ALREADY_EXISTS) { - ib::error() << "The file '" << path << "'" + ib::info() << "The file '" << path << "'" " already exists though the" " corresponding table did not exist" " in the InnoDB data dictionary." - " Have you moved InnoDB .ibd files" - " around without using the SQL commands" - " DISCARD TABLESPACE and IMPORT TABLESPACE," - " or did mysqld crash in the middle of" - " CREATE TABLE?" " You can resolve the problem by removing" - " the file '" << path - << "' under the 'datadir' of MySQL."; + " the file."; return(DB_TABLESPACE_EXISTS); } diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index b8ad49a254f..346962567d6 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -425,13 +425,10 @@ Datafile::validate_to_dd(ulint space_id, ulint flags) /* else do not use this tablespace. */ m_is_valid = false; - ib::error() << "In file '" << m_filepath << "', tablespace id and" - " flags are " << m_space_id << " and " << ib::hex(m_flags) - << ", but in the InnoDB data dictionary they are " - << space_id << " and " << ib::hex(flags) - << ". Have you moved InnoDB .ibd files around without" - " using the commands DISCARD TABLESPACE and IMPORT TABLESPACE?" - " " << TROUBLESHOOT_DATADICT_MSG; + ib::error() << "Refusing to load '" << m_filepath << "' (id=" + << m_space_id << ", flags=" << ib::hex(m_flags) + << "); dictionary contains id=" + << space_id << ", flags=" << ib::hex(flags); return(DB_ERROR); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 23edecda245..670e170e9cc 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6624,10 +6624,6 @@ ha_innobase::open( norm_name); } - ib::warn() << "Cannot open table " << norm_name << " from the" - " internal data dictionary of InnoDB though the .frm" - " file for the table exists. " << TROUBLESHOOTING_MSG; - free_share(m_share); set_my_errno(ENOENT); diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index e9507302e66..deb48d0cd31 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -646,74 +646,54 @@ bool dict_tf_is_valid( ulint flags) { - bool compact = DICT_TF_GET_COMPACT(flags); - ulint zip_ssize = DICT_TF_GET_ZIP_SSIZE(flags); - bool atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(flags); - bool data_dir = DICT_TF_HAS_DATA_DIR(flags); - ulint unused = DICT_TF_GET_UNUSED(flags); - bool page_compression = DICT_TF_GET_PAGE_COMPRESSION(flags); - ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(flags); - bool flags_corrupt = false; - /* Make sure there are no bits that we do not know about. */ - if (unused != 0) { - flags_corrupt = true; + if (flags >= 1U << DICT_TF_BITS) { + return(false); } - if (atomic_blobs) { - /* Barracuda row formats COMPRESSED and DYNAMIC both use + const bool not_redundant = DICT_TF_GET_COMPACT(flags); + const bool atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(flags); + + if (atomic_blobs && !not_redundant) { + /* ROW_FORMAT=COMPRESSED and ROW_FORMAT=DYNAMIC both use atomic_blobs, which build on the page structure introduced - for the COMPACT row format by allowing keys in secondary + for ROW_FORMAT=COMPACT by allowing keys in secondary indexes to be made from data stored off-page in the clustered index. */ - - if (!compact) { - flags_corrupt = true; - } - - } else if (zip_ssize) { - /* Antelope does not support COMPRESSED row format. */ - flags_corrupt = true; + return(false); } - if (zip_ssize) { + ulint zip_ssize = DICT_TF_GET_ZIP_SSIZE(flags); - /* COMPRESSED row format must have compact and atomic_blobs - bits set and validate the number is within allowed range. */ - - if (!compact - || !atomic_blobs - || zip_ssize > PAGE_ZIP_SSIZE_MAX) { - flags_corrupt = true; - } + if (!zip_ssize) { + /* Not ROW_FORMAT=COMPRESSED */ + } else if (!atomic_blobs) { + /* ROW_FORMAT=COMPRESSED implies ROW_FORMAT=DYNAMIC + for the uncompressed page format */ + return(false); + } else if (zip_ssize > PAGE_ZIP_SSIZE_MAX + || zip_ssize > UNIV_PAGE_SIZE_SHIFT + || UNIV_PAGE_SIZE_SHIFT > UNIV_ZIP_SIZE_SHIFT_MAX) { + /* KEY_BLOCK_SIZE is out of bounds, or + ROW_FORMAT=COMPRESSED is not supported with this + innodb_page_size (only up to 16KiB) */ + return(false); } - if (page_compression || page_compression_level) { - /* Page compression format must have compact and - atomic_blobs and page_compression_level requires - page_compression */ - if (!compact - || !page_compression - || !atomic_blobs) { - flags_corrupt = true; - } - } - - - if (flags_corrupt) { - ib::error() - << "InnoDB: Error: table unused flags are:" << flags - << " in the data dictionary and are corrupted:" - << " compact:" << compact - << " atomic_blobs:" << atomic_blobs - << " unused:" << unused - << " data_dir:" << data_dir - << " zip_ssize:" << zip_ssize - << " page_compression:" << page_compression - << " page_compression_level:" << page_compression_level; - return (false); - } else { - return(true); + switch (DICT_TF_GET_PAGE_COMPRESSION_LEVEL(flags)) { + case 0: + /* PAGE_COMPRESSION_LEVEL=0 should imply PAGE_COMPRESSED=NO */ + return(!DICT_TF_GET_PAGE_COMPRESSION(flags)); + case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: + /* PAGE_COMPRESSION_LEVEL requires + ROW_FORMAT=COMPACT or ROW_FORMAT=DYNAMIC + (not ROW_FORMAT=COMPRESSED or ROW_FORMAT=REDUNDANT) + and PAGE_COMPRESSED=YES */ + return(!zip_ssize && not_redundant + && DICT_TF_GET_PAGE_COMPRESSION(flags)); + default: + /* Invalid PAGE_COMPRESSION_LEVEL value */ + return(false); } } @@ -978,7 +958,6 @@ dict_tf_to_fsp_flags(ulint table_flags) ulint fsp_flags; ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL( table_flags); - ulint atomic_writes = DICT_TF_GET_ATOMIC_WRITES(table_flags); ut_ad((DICT_TF_GET_PAGE_COMPRESSION(table_flags) == 0) == (page_compression_level == 0)); @@ -1005,7 +984,6 @@ dict_tf_to_fsp_flags(ulint table_flags) fsp_flags |= 1U << FSP_FLAGS_MEM_DATA_DIR; } - fsp_flags |= atomic_writes << FSP_FLAGS_MEM_ATOMIC_WRITES; fsp_flags |= page_compression_level << FSP_FLAGS_MEM_COMPRESSION_LEVEL; return(fsp_flags); diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 42396f089b2..eb2b7b9d785 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -137,22 +137,12 @@ This flag prevents older engines from attempting to open the table and allows InnoDB to update_create_info() accordingly. */ #define DICT_TF_WIDTH_DATA_DIR 1 -/** Width of the SHARED tablespace flag (Oracle MYSQL 5.7). -Not supported by MariaDB. */ -#define DICT_TF_WIDTH_SHARED_SPACE 1 - /** Width of the page compression flag */ #define DICT_TF_WIDTH_PAGE_COMPRESSION 1 #define DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL 4 -/** -Width of the page encryption flag -*/ -#define DICT_TF_WIDTH_PAGE_ENCRYPTION 1 -#define DICT_TF_WIDTH_PAGE_ENCRYPTION_KEY 8 - /** Width of atomic writes flag DEFAULT=0, ON = 1, OFF = 2 @@ -164,15 +154,8 @@ DEFAULT=0, ON = 1, OFF = 2 + DICT_TF_WIDTH_ZIP_SSIZE \ + DICT_TF_WIDTH_ATOMIC_BLOBS \ + DICT_TF_WIDTH_DATA_DIR \ - + DICT_TF_WIDTH_SHARED_SPACE \ + DICT_TF_WIDTH_PAGE_COMPRESSION \ - + DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL \ - + DICT_TF_WIDTH_ATOMIC_WRITES \ - + DICT_TF_WIDTH_PAGE_ENCRYPTION \ - + DICT_TF_WIDTH_PAGE_ENCRYPTION_KEY) - -/** A mask of all the known/used bits in table flags */ -#define DICT_TF_BIT_MASK (~(~0U << DICT_TF_BITS)) + + DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL) /** Zero relative shift position of the COMPACT field */ #define DICT_TF_POS_COMPACT 0 @@ -185,26 +168,17 @@ DEFAULT=0, ON = 1, OFF = 2 /** Zero relative shift position of the DATA_DIR field */ #define DICT_TF_POS_DATA_DIR (DICT_TF_POS_ATOMIC_BLOBS \ + DICT_TF_WIDTH_ATOMIC_BLOBS) -/** Zero relative shift position of the SHARED TABLESPACE field */ -#define DICT_TF_POS_SHARED_SPACE (DICT_TF_POS_DATA_DIR \ - + DICT_TF_WIDTH_DATA_DIR) /** Zero relative shift position of the PAGE_COMPRESSION field */ -#define DICT_TF_POS_PAGE_COMPRESSION (DICT_TF_POS_SHARED_SPACE \ - + DICT_TF_WIDTH_SHARED_SPACE) +#define DICT_TF_POS_PAGE_COMPRESSION (DICT_TF_POS_DATA_DIR \ + + DICT_TF_WIDTH_DATA_DIR) /** Zero relative shift position of the PAGE_COMPRESSION_LEVEL field */ #define DICT_TF_POS_PAGE_COMPRESSION_LEVEL (DICT_TF_POS_PAGE_COMPRESSION \ + DICT_TF_WIDTH_PAGE_COMPRESSION) /** Zero relative shift position of the ATOMIC_WRITES field */ #define DICT_TF_POS_ATOMIC_WRITES (DICT_TF_POS_PAGE_COMPRESSION_LEVEL \ + DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL) -/** Zero relative shift position of the PAGE_ENCRYPTION field */ -#define DICT_TF_POS_PAGE_ENCRYPTION (DICT_TF_POS_ATOMIC_WRITES \ +#define DICT_TF_POS_UNUSED (DICT_TF_POS_ATOMIC_WRITES \ + DICT_TF_WIDTH_ATOMIC_WRITES) -/** Zero relative shift position of the PAGE_ENCRYPTION_KEY field */ -#define DICT_TF_POS_PAGE_ENCRYPTION_KEY (DICT_TF_POS_PAGE_ENCRYPTION \ - + DICT_TF_WIDTH_PAGE_ENCRYPTION) -#define DICT_TF_POS_UNUSED (DICT_TF_POS_PAGE_ENCRYPTION_KEY \ - + DICT_TF_WIDTH_PAGE_ENCRYPTION_KEY) /** Bit mask of the COMPACT field */ #define DICT_TF_MASK_COMPACT \ @@ -234,14 +208,6 @@ DEFAULT=0, ON = 1, OFF = 2 #define DICT_TF_MASK_ATOMIC_WRITES \ ((~(~0U << DICT_TF_WIDTH_ATOMIC_WRITES)) \ << DICT_TF_POS_ATOMIC_WRITES) -/** Bit mask of the PAGE_ENCRYPTION field */ -#define DICT_TF_MASK_PAGE_ENCRYPTION \ - ((~(~0U << DICT_TF_WIDTH_PAGE_ENCRYPTION)) \ - << DICT_TF_POS_PAGE_ENCRYPTION) -/** Bit mask of the PAGE_ENCRYPTION_KEY field */ -#define DICT_TF_MASK_PAGE_ENCRYPTION_KEY \ - ((~(~0U << DICT_TF_WIDTH_PAGE_ENCRYPTION_KEY)) \ - << DICT_TF_POS_PAGE_ENCRYPTION_KEY) /** Return the value of the COMPACT field */ #define DICT_TF_GET_COMPACT(flags) \ @@ -271,14 +237,6 @@ DEFAULT=0, ON = 1, OFF = 2 #define DICT_TF_GET_ATOMIC_WRITES(flags) \ ((flags & DICT_TF_MASK_ATOMIC_WRITES) \ >> DICT_TF_POS_ATOMIC_WRITES) -/** Return the contents of the PAGE_ENCRYPTION field */ -#define DICT_TF_GET_PAGE_ENCRYPTION(flags) \ - ((flags & DICT_TF_MASK_PAGE_ENCRYPTION) \ - >> DICT_TF_POS_PAGE_ENCRYPTION) -/** Return the contents of the PAGE_ENCRYPTION KEY field */ -#define DICT_TF_GET_PAGE_ENCRYPTION_KEY(flags) \ - ((flags & DICT_TF_MASK_PAGE_ENCRYPTION_KEY) \ - >> DICT_TF_POS_PAGE_ENCRYPTION_KEY) /** Return the contents of the UNUSED bits */ #define DICT_TF_GET_UNUSED(flags) \ diff --git a/storage/innobase/include/fsp0types.h b/storage/innobase/include/fsp0types.h index cd2a07af4f0..129fd102f0f 100644 --- a/storage/innobase/include/fsp0types.h +++ b/storage/innobase/include/fsp0types.h @@ -278,10 +278,8 @@ The flags below only exist in fil_space_t::flags, not in FSP_SPACE_FLAGS: /** Zero relative shift position of the DATA_DIR flag */ #define FSP_FLAGS_MEM_DATA_DIR 25 -/** Zero relative shift position of the ATOMIC_WRITES field */ -#define FSP_FLAGS_MEM_ATOMIC_WRITES 26 /** Zero relative shift position of the COMPRESSION_LEVEL field */ -#define FSP_FLAGS_MEM_COMPRESSION_LEVEL 28 +#define FSP_FLAGS_MEM_COMPRESSION_LEVEL 26 /** Zero relative shift position of the POST_ANTELOPE field */ #define FSP_FLAGS_POS_POST_ANTELOPE 0 @@ -327,10 +325,6 @@ these are only used in MySQL 5.7 and used for compatibility. */ ((~(~0U << FSP_FLAGS_WIDTH_PAGE_COMPRESSION)) \ << FSP_FLAGS_POS_PAGE_COMPRESSION) -/** Bit mask of the in-memory ATOMIC_WRITES field */ -#define FSP_FLAGS_MASK_MEM_ATOMIC_WRITES \ - (3U << FSP_FLAGS_MEM_ATOMIC_WRITES) - /** Bit mask of the in-memory COMPRESSION_LEVEL field */ #define FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL \ (15U << FSP_FLAGS_MEM_COMPRESSION_LEVEL) @@ -371,10 +365,6 @@ these are only used in MySQL 5.7 and used for compatibility. */ #define FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags) \ ((flags & FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL) \ >> FSP_FLAGS_MEM_COMPRESSION_LEVEL) -/** @return the ATOMIC_WRITES field */ -#define FSP_FLAGS_GET_ATOMIC_WRITES(flags) \ - ((flags & FSP_FLAGS_MASK_MEM_ATOMIC_WRITES) \ - >> FSP_FLAGS_MEM_ATOMIC_WRITES) /* @} */ diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 82e17c6fb0a..9bbe6968de1 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -3002,21 +3002,19 @@ row_import_read_v1( cfg->m_n_cols = mach_read_from_4(ptr); if (!dict_tf_is_valid(cfg->m_flags)) { + ib_errf(thd, IB_LOG_LEVEL_ERROR, + ER_TABLE_SCHEMA_MISMATCH, + "Invalid table flags: " ULINTPF, cfg->m_flags); return(DB_CORRUPTION); - - } else if ((err = row_import_read_columns(file, thd, cfg)) - != DB_SUCCESS) { - - return(err); - - } else if ((err = row_import_read_indexes(file, thd, cfg)) - != DB_SUCCESS) { - - return(err); } - ut_a(err == DB_SUCCESS); + err = row_import_read_columns(file, thd, cfg); + + if (err == DB_SUCCESS) { + err = row_import_read_indexes(file, thd, cfg); + } + return(err); } From 6b71b3e3484818b667790b0f7426c37138fbbe53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 15 Jun 2017 17:42:49 +0300 Subject: [PATCH 9/9] Follow-up to MDEV-12873: Refactor SYS_TABLES.TYPE validation dict_sys_tables_type_to_tf(): Change the parameter n_cols to not_redundant. dict_tf_is_valid_not_redundant(): Refactored from dict_tf_is_valid(). dict_sys_tables_type_valid(): Replaces dict_sys_tables_type_validate(). Use the common function dict_tf_is_valid_not_redundant(), which validates PAGE_COMPRESSION_LEVEL more strictly. DICT_TF_GET_UNUSED(flags): Remove. --- storage/innobase/dict/dict0load.cc | 81 ++++++++++-- storage/innobase/include/dict0dict.ic | 177 +++++--------------------- storage/innobase/include/dict0mem.h | 3 - 3 files changed, 100 insertions(+), 161 deletions(-) diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 7572e7a00f5..3dc95b1956a 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -1129,6 +1129,71 @@ dict_sys_tablespaces_rec_read( return(true); } +/** Check if SYS_TABLES.TYPE is valid +@param[in] type SYS_TABLES.TYPE +@param[in] not_redundant whether ROW_FORMAT=REDUNDANT is not used +@return whether the SYS_TABLES.TYPE value is valid */ +static +bool +dict_sys_tables_type_valid(ulint type, bool not_redundant) +{ + /* The DATA_DIRECTORY flag can be assigned fully independently + of all other persistent table flags. */ + type &= ~DICT_TF_MASK_DATA_DIR; + + if (type == 1) { + return(true); /* ROW_FORMAT=REDUNDANT or ROW_FORMAT=COMPACT */ + } + + if (!(type & 1)) { + /* For ROW_FORMAT=REDUNDANT and ROW_FORMAT=COMPACT, + SYS_TABLES.TYPE=1. Else, it is the same as + dict_table_t::flags, and the least significant bit + would be set. So, the bit never can be 0. */ + return(false); + } + + if (!not_redundant) { + /* SYS_TABLES.TYPE must be 1 for ROW_FORMAT=REDUNDANT. */ + return(false); + } + + if (type >= 1U << DICT_TF_POS_UNUSED) { + /* Some unknown bits are set. */ + return(false); + } + + /* ATOMIC_WRITES cannot be 3; it is the 10.3 NO_ROLLBACK flag. */ + if (!(~type & DICT_TF_MASK_ATOMIC_WRITES)) { + return(false); + } + + return(dict_tf_is_valid_not_redundant(type)); +} + +/** Convert SYS_TABLES.TYPE to dict_table_t::flags. +@param[in] type SYS_TABLES.TYPE +@param[in] not_redundant whether ROW_FORMAT=REDUNDANT is not used +@return table flags */ +static +ulint +dict_sys_tables_type_to_tf(ulint type, bool not_redundant) +{ + ut_ad(dict_sys_tables_type_valid(type, not_redundant)); + ulint flags = not_redundant ? 1 : 0; + + /* ZIP_SSIZE, ATOMIC_BLOBS, DATA_DIR, PAGE_COMPRESSION, + PAGE_COMPRESSION_LEVEL are the same. */ + flags |= type & (DICT_TF_MASK_ZIP_SSIZE + | DICT_TF_MASK_ATOMIC_BLOBS + | DICT_TF_MASK_DATA_DIR + | DICT_TF_MASK_PAGE_COMPRESSION + | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL); + + ut_ad(dict_tf_is_valid(flags)); + return(flags); +} + /** Read and return 5 integer fields from a SYS_TABLES record. @param[in] rec A record of SYS_TABLES @param[in] name Table Name, the same as SYS_TABLES.NAME @@ -1222,8 +1287,7 @@ dict_sys_tables_rec_read( SYS_TABLES.TYPE to be in the 10.2.2..10.2.6 format. This would in any case be invalid format for 10.2 and earlier releases. */ - ut_ad(ULINT_UNDEFINED == dict_sys_tables_type_validate( - type, DICT_N_COLS_COMPACT)); + ut_ad(!dict_sys_tables_type_valid(type, true)); } else { /* SYS_TABLES.TYPE is of the form AALLLL10DB00001. We must still validate that the LLLL bits are between 0 @@ -1239,8 +1303,7 @@ dict_sys_tables_rec_read( ut_ad(DICT_TF_GET_PAGE_COMPRESSION_LEVEL(type) >= 1); ut_ad(DICT_TF_GET_PAGE_COMPRESSION_LEVEL(type) <= 9); } else { - ut_ad(ULINT_UNDEFINED == dict_sys_tables_type_validate( - type, DICT_N_COLS_COMPACT)); + ut_ad(!dict_sys_tables_type_valid(type, true)); } } @@ -1255,11 +1318,9 @@ dict_sys_tables_rec_read( ut_a(len == 4); *n_cols = mach_read_from_4(field); - /* This validation function also combines the DICT_N_COLS_COMPACT - flag in n_cols into the type field to effectively make it a - dict_table_t::flags. */ + const bool not_redundant = 0 != (*n_cols & DICT_N_COLS_COMPACT); - if (ULINT_UNDEFINED == dict_sys_tables_type_validate(type, *n_cols)) { + if (!dict_sys_tables_type_valid(type, not_redundant)) { ib::error() << "Table " << table_name << " in InnoDB" " data dictionary contains invalid flags." " SYS_TABLES.TYPE=" << type << @@ -1267,7 +1328,7 @@ dict_sys_tables_rec_read( return(false); } - *flags = dict_sys_tables_type_to_tf(type, *n_cols); + *flags = dict_sys_tables_type_to_tf(type, not_redundant); /* For tables created before MySQL 4.1, there may be garbage in SYS_TABLES.MIX_LEN where flags2 are found. Such tables @@ -1275,7 +1336,7 @@ dict_sys_tables_rec_read( high bit set in n_cols, and flags would be zero. MySQL 4.1 was the first version to support innodb_file_per_table, that is, *space_id != 0. */ - if (*flags != 0 || *space_id != 0 || *n_cols & DICT_N_COLS_COMPACT) { + if (not_redundant || *space_id != 0 || *n_cols & DICT_N_COLS_COMPACT) { /* Get flags2 from SYS_TABLES.MIX_LEN */ field = rec_get_nth_field_old( diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index 1200b62f92f..0244bb784e0 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -638,31 +638,15 @@ dict_table_has_fts_index( return(DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS)); } -/** Validate the table flags. -@param[in] flags Table flags -@return true if valid. */ -UNIV_INLINE +/** Validate the flags for tables that are not ROW_FORMAT=REDUNDANT. +@param[in] flags table flags +@return whether the flags are valid */ +inline bool -dict_tf_is_valid( - ulint flags) +dict_tf_is_valid_not_redundant(ulint flags) { - /* Make sure there are no bits that we do not know about. */ - if (flags >= 1U << DICT_TF_BITS) { - return(false); - } - - const bool not_redundant = DICT_TF_GET_COMPACT(flags); const bool atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(flags); - if (atomic_blobs && !not_redundant) { - /* ROW_FORMAT=COMPRESSED and ROW_FORMAT=DYNAMIC both use - atomic_blobs, which build on the page structure introduced - for ROW_FORMAT=COMPACT by allowing keys in secondary - indexes to be made from data stored off-page in the - clustered index. */ - return(false); - } - ulint zip_ssize = DICT_TF_GET_ZIP_SSIZE(flags); if (!zip_ssize) { @@ -689,14 +673,36 @@ dict_tf_is_valid( ROW_FORMAT=COMPACT or ROW_FORMAT=DYNAMIC (not ROW_FORMAT=COMPRESSED or ROW_FORMAT=REDUNDANT) and PAGE_COMPRESSED=YES */ - return(!zip_ssize && not_redundant - && DICT_TF_GET_PAGE_COMPRESSION(flags)); + return(!zip_ssize && DICT_TF_GET_PAGE_COMPRESSION(flags)); default: /* Invalid PAGE_COMPRESSION_LEVEL value */ return(false); } } +/** Validate the table flags. +@param[in] flags Table flags +@return true if valid. */ +UNIV_INLINE +bool +dict_tf_is_valid( + ulint flags) +{ + ut_ad(flags < 1U << DICT_TF_BITS); + /* The DATA_DIRECTORY flag can be assigned fully independently + of all other persistent table flags. */ + flags &= ~DICT_TF_MASK_DATA_DIR; + if (!(flags & 1)) { + /* Only ROW_FORMAT=REDUNDANT has 0 in the least significant + bit. For ROW_FORMAT=REDUNDANT, only the DATA_DIR flag + (which we cleared above) can be set. If any other flags + are set, the flags are invalid. */ + return(flags == 0); + } + + return(dict_tf_is_valid_not_redundant(flags)); +} + /** Validate both table flags and table flags2 and make sure they are compatible. @param[in] flags Table flags @@ -719,96 +725,6 @@ dict_tf2_is_valid( return(true); } -/********************************************************************//** -Validate a SYS_TABLES TYPE field and return it. -@return Same as input after validating it as a SYS_TABLES TYPE field. -If there is an error, return ULINT_UNDEFINED. */ -UNIV_INLINE -ulint -dict_sys_tables_type_validate( -/*==========================*/ - ulint type, /*!< in: SYS_TABLES.TYPE */ - ulint n_cols) /*!< in: SYS_TABLES.N_COLS */ -{ - ulint low_order_bit = DICT_TF_GET_COMPACT(type); - ulint redundant = !(n_cols & DICT_N_COLS_COMPACT); - ulint zip_ssize = DICT_TF_GET_ZIP_SSIZE(type); - ulint atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(type); - ulint unused = DICT_TF_GET_UNUSED(type); - bool page_compression = DICT_TF_GET_PAGE_COMPRESSION(type); - ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(type); - - /* The low order bit of SYS_TABLES.TYPE is always set to 1. - If the format is UNIV_FORMAT_B or higher, this field is the same - as dict_table_t::flags. Zero is not allowed here. */ - if (!low_order_bit) { - return(ULINT_UNDEFINED); - } - - if (redundant) { - if (zip_ssize || atomic_blobs) { - return(ULINT_UNDEFINED); - } - } - - /* Make sure there are no bits that we do not know about. */ - if (unused) { - return(ULINT_UNDEFINED); - } - - if (atomic_blobs) { - /* Barracuda row formats COMPRESSED and DYNAMIC build on - the page structure introduced for the COMPACT row format - by allowing keys in secondary indexes to be made from - data stored off-page in the clustered index. - - The DICT_N_COLS_COMPACT flag should be in N_COLS, - but we already know that. */ - } else if (zip_ssize) { - /* Antelope does not support COMPRESSED format. */ - return(ULINT_UNDEFINED); - } - - if (zip_ssize) { - /* COMPRESSED row format must have low_order_bit and - atomic_blobs bits set and the DICT_N_COLS_COMPACT flag - should be in N_COLS, but we already know about the - low_order_bit and DICT_N_COLS_COMPACT flags. */ - if (!atomic_blobs) { - return(ULINT_UNDEFINED); - } - - /* Validate that the number is within allowed range. */ - if (zip_ssize > PAGE_ZIP_SSIZE_MAX) { - return(ULINT_UNDEFINED); - } - } - - /* There is nothing to validate for the data_dir field. - CREATE TABLE ... DATA DIRECTORY is supported for any row - format, so the DATA_DIR flag is compatible with any other - table flags. However, it is not used with TEMPORARY tables. */ - - if (page_compression || page_compression_level) { - /* page compressed row format must have low_order_bit and - atomic_blobs bits set and the DICT_N_COLS_COMPACT flag - should be in N_COLS, but we already know about the - low_order_bit and DICT_N_COLS_COMPACT flags. */ - - if (!atomic_blobs || !page_compression) { - return(ULINT_UNDEFINED); - } - } - - /* Validate that the atomic writes number is within allowed range. */ - if (DICT_TF_GET_ATOMIC_WRITES(type) == 3) { - return(ULINT_UNDEFINED); - } - - /* Return the validated SYS_TABLES.TYPE. */ - return(type); -} - /********************************************************************//** Determine the file format from dict_table_t::flags The low order bit will be zero for REDUNDANT and 1 for COMPACT. For any @@ -973,41 +889,6 @@ dict_tf_to_fsp_flags(ulint table_flags) return(fsp_flags); } -/********************************************************************//** -Convert a 32 bit integer from SYS_TABLES.TYPE to dict_table_t::flags -The following chart shows the translation of the low order bit. -Other bits are the same. -========================= Low order bit ========================== - | REDUNDANT | COMPACT | COMPRESSED and DYNAMIC -SYS_TABLES.TYPE | 1 | 1 | 1 -dict_table_t::flags | 0 | 1 | 1 -================================================================== -@return ulint containing SYS_TABLES.TYPE */ -UNIV_INLINE -ulint -dict_sys_tables_type_to_tf( -/*=======================*/ - ulint type, /*!< in: SYS_TABLES.TYPE field */ - ulint n_cols) /*!< in: SYS_TABLES.N_COLS field */ -{ - ulint flags; - ulint redundant = !(n_cols & DICT_N_COLS_COMPACT); - - /* Adjust bit zero. */ - flags = redundant ? 0 : 1; - - /* ZIP_SSIZE, ATOMIC_BLOBS, DATA_DIR, PAGE_COMPRESSION, - PAGE_COMPRESSION_LEVEL are the same. */ - flags |= type & (DICT_TF_MASK_ZIP_SSIZE - | DICT_TF_MASK_ATOMIC_BLOBS - | DICT_TF_MASK_DATA_DIR - | DICT_TF_MASK_PAGE_COMPRESSION - | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL); - - ut_ad(!DICT_TF_GET_ZIP_SSIZE(flags) || DICT_TF_HAS_ATOMIC_BLOBS(flags)); - return(flags); -} - /********************************************************************//** Convert a 32 bit integer table flags to the 32bit integer that is written to a SYS_TABLES.TYPE field. The following chart shows the translation of diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index c4f5ab8a15c..daa5af95a71 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -238,9 +238,6 @@ DEFAULT=0, ON = 1, OFF = 2 ((flags & DICT_TF_MASK_ATOMIC_WRITES) \ >> DICT_TF_POS_ATOMIC_WRITES) -/** Return the contents of the UNUSED bits */ -#define DICT_TF_GET_UNUSED(flags) \ - (flags >> DICT_TF_POS_UNUSED) /* @} */ /** @brief Table Flags set number 2.