From c5a9a63293f868f074def37c985fe23a9c01c276 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Sat, 15 Sep 2018 14:28:19 -0700 Subject: [PATCH 1/8] MDEV-16917 Index affects query results The optimizer erroneously allowed to use join cache when joining a splittable materialized table together with splitting optimization. As a consequence in some rare cases the server returned wrong result sets for queries with materialized derived. This patch allows to use either join cache without usage of splitting technique for materialization of a splittable derived table or splitting without usage of join cache when joining such table. The costs the these alternatives are compared and the best variant is chosen. --- mysql-test/main/derived_split_innodb.result | 26 +++++++++++++++++++++ mysql-test/main/derived_split_innodb.test | 26 +++++++++++++++++++++ sql/opt_split.cc | 7 ++++++ sql/sql_select.cc | 7 +++++- sql/table.h | 1 + 5 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 mysql-test/main/derived_split_innodb.result create mode 100644 mysql-test/main/derived_split_innodb.test diff --git a/mysql-test/main/derived_split_innodb.result b/mysql-test/main/derived_split_innodb.result new file mode 100644 index 00000000000..6fa20b721e0 --- /dev/null +++ b/mysql-test/main/derived_split_innodb.result @@ -0,0 +1,26 @@ +# +# MDEV-16917: do not use splitting for derived with join cache +# +CREATE TABLE t1 ( +n1 int(10) NOT NULL, +n2 int(10) NOT NULL, +c1 char(1) NOT NULL, +KEY c1 (c1), +KEY n1_c1_n2 (n1,c1,n2) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES (0, 2, 'a'), (1, 3, 'a'); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +EXPLAIN SELECT t1.n1 FROM t1, (SELECT n1, n2 FROM t1 WHERE c1 = 'a' GROUP BY n1) as t +WHERE t.n1 = t1.n1 AND t.n2 = t1.n2 AND c1 = 'a' GROUP BY n1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index c1,n1_c1_n2 n1_c1_n2 9 NULL 2 Using where; Using index +1 PRIMARY ref key0 key0 8 test.t1.n1,test.t1.n2 2 +2 LATERAL DERIVED t1 ref c1,n1_c1_n2 n1_c1_n2 4 test.t1.n1 1 Using where; Using index +SELECT t1.n1 FROM t1, (SELECT n1, n2 FROM t1 WHERE c1 = 'a' GROUP BY n1) as t +WHERE t.n1 = t1.n1 AND t.n2 = t1.n2 AND c1 = 'a' GROUP BY n1; +n1 +0 +1 +DROP TABLE t1; diff --git a/mysql-test/main/derived_split_innodb.test b/mysql-test/main/derived_split_innodb.test new file mode 100644 index 00000000000..2abd6fa9f97 --- /dev/null +++ b/mysql-test/main/derived_split_innodb.test @@ -0,0 +1,26 @@ +--source include/have_innodb.inc + +--echo # +--echo # MDEV-16917: do not use splitting for derived with join cache +--echo # + +CREATE TABLE t1 ( + n1 int(10) NOT NULL, + n2 int(10) NOT NULL, + c1 char(1) NOT NULL, + KEY c1 (c1), + KEY n1_c1_n2 (n1,c1,n2) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES (0, 2, 'a'), (1, 3, 'a'); + +ANALYZE TABLE t1; + +Let $q= +SELECT t1.n1 FROM t1, (SELECT n1, n2 FROM t1 WHERE c1 = 'a' GROUP BY n1) as t + WHERE t.n1 = t1.n1 AND t.n2 = t1.n2 AND c1 = 'a' GROUP BY n1; + +eval EXPLAIN $q; +eval $q; + +DROP TABLE t1; + diff --git a/sql/opt_split.cc b/sql/opt_split.cc index 611e70376c8..c5e31ba5bcf 100644 --- a/sql/opt_split.cc +++ b/sql/opt_split.cc @@ -267,6 +267,13 @@ void TABLE::deny_splitting() } +double TABLE::get_materialization_cost() +{ + DBUG_ASSERT(spl_opt_info != NULL); + return spl_opt_info->unsplit_cost; +} + + /* This structure is auxiliary and used only in the function that follows it */ struct SplM_field_ext_info: public SplM_field_info { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7ff29bb081c..e97ea680d87 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7254,7 +7254,11 @@ best_access_path(JOIN *join, } } - tmp += s->startup_cost; + /* Splitting technique cannot be used with join cache */ + if (s->table->is_splittable()) + tmp+= s->table->get_materialization_cost(); + else + tmp+= s->startup_cost; /* We estimate the cost of evaluating WHERE clause for found records as record_count * rnd_records / TIME_FOR_COMPARE. This cost plus @@ -7276,6 +7280,7 @@ best_access_path(JOIN *join, best_ref_depends_map= 0; best_uses_jbuf= MY_TEST(!disable_jbuf && !((s->table->map & join->outer_join))); + spl_plan= 0; } } diff --git a/sql/table.h b/sql/table.h index 80f5e1283a3..a14a82e5cd2 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1507,6 +1507,7 @@ public: bool is_splittable() { return spl_opt_info != NULL; } void set_spl_opt_info(SplM_opt_info *spl_info); void deny_splitting(); + double get_materialization_cost(); // Now used only if is_splittable()==true void add_splitting_info_for_key_field(struct KEY_FIELD *key_field); /** From ac24289e6600403155127b1a36788ad8b4ead500 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 17 Sep 2018 14:22:30 +0300 Subject: [PATCH 2/8] =?UTF-8?q?MDEV-16328=20ALTER=20TABLE=E2=80=A6page=5Fc?= =?UTF-8?q?ompression=5Flevel=20should=20not=20rebuild=20table?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The table option page_compression_level is something that only affects future writes, not actually the data format. Therefore, we can allow instant changes of this option. Similarly, the table option page_compressed can be set on a previously uncompressed table without rebuilding the table, because an uncompressed page would be considered valid when reading a page_compressed table. Removing the page_compressed option will continue to require the table to be rebuilt. ha_innobase_inplace_ctx::page_compression_level: The requested page_compression_level at the start of ALTER TABLE, or 0 if page_compressed=OFF. alter_options_need_rebuild(): Renamed from create_option_need_rebuild(). Allow page_compression_level and page_compressed to be changed as above, without rebuilding the table. ha_innobase::check_if_supported_inplace_alter(): Allow ALGORITHM=INSTANT for ALTER_OPTIONS if the table is not to be rebuilt. If rebuild is needed, set ha_alter_info->unsupported_reason. innobase_page_compression_try(): Update SYS_TABLES.TYPE according to the table flags, for an instant change of page_compression_level or page_compressed. commit_cache_norebuild(): Adjust dict_table_t::flags, fil_space_t::flags and (if needed) FSP_SPACE_FLAGS if page_compression_level was specified. --- .../suite/innodb/r/alter_algorithm,COPY.rdiff | 92 -------- .../innodb/r/alter_algorithm,INPLACE.rdiff | 67 ++++-- .../innodb/r/alter_algorithm,INSTANT.rdiff | 59 +++--- .../innodb/r/alter_algorithm,NOCOPY.rdiff | 92 ++++++++ .../suite/innodb/r/alter_algorithm.result | 51 +++-- .../r/innodb-page_compression_bzip2.result | 8 +- .../r/innodb-page_compression_lz4.result | 7 +- .../r/innodb-page_compression_lzma.result | 8 +- .../r/innodb-page_compression_lzo.result | 8 +- .../r/innodb-page_compression_tables.result | 8 +- .../r/innodb-page_compression_zip.result | 7 +- .../suite/innodb/t/alter_algorithm.test | 2 +- .../t/innodb-page_compression_bzip2.test | 15 +- .../innodb/t/innodb-page_compression_lz4.test | 14 +- .../t/innodb-page_compression_lzma.test | 15 +- .../innodb/t/innodb-page_compression_lzo.test | 15 +- .../t/innodb-page_compression_tables.test | 8 +- .../innodb/t/innodb-page_compression_zip.test | 14 +- sql/share/errmsg-utf8.txt | 2 + storage/innobase/handler/handler0alter.cc | 197 ++++++++++++++---- 20 files changed, 450 insertions(+), 239 deletions(-) delete mode 100644 mysql-test/suite/innodb/r/alter_algorithm,COPY.rdiff create mode 100644 mysql-test/suite/innodb/r/alter_algorithm,NOCOPY.rdiff diff --git a/mysql-test/suite/innodb/r/alter_algorithm,COPY.rdiff b/mysql-test/suite/innodb/r/alter_algorithm,COPY.rdiff deleted file mode 100644 index be71e125e22..00000000000 --- a/mysql-test/suite/innodb/r/alter_algorithm,COPY.rdiff +++ /dev/null @@ -1,92 +0,0 @@ ---- alter_algorithm.result 2018-05-06 23:42:08.022302601 +0530 -+++ alter_algorithm.reject 2018-05-06 23:42:16.382634082 +0530 -@@ -7,35 +7,44 @@ - INSERT INTO t1(f1, f2, f3) VALUES(1, 1, 1); - SELECT @@alter_algorithm; - @@alter_algorithm --NOCOPY -+COPY - # All the following cases needs table rebuild - # Add and Drop primary key - ALTER TABLE t1 ADD COLUMN col1 INT NOT NULL,DROP PRIMARY KEY,ADD PRIMARY KEY(col1); --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE -+affected rows: 1 -+info: Records: 1 Duplicates: 0 Warnings: 0 - # Make existing column NULLABLE - ALTER TABLE t1 MODIFY f2 INT; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE -+affected rows: 1 -+info: Records: 1 Duplicates: 0 Warnings: 0 - # Make existing column NON-NULLABLE - ALTER TABLE t1 MODIFY f3 INT NOT NULL; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE -+affected rows: 1 -+info: Records: 1 Duplicates: 0 Warnings: 0 - # Drop Stored Column - ALTER TABLE t1 DROP COLUMN f5; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE -+affected rows: 1 -+info: Records: 1 Duplicates: 0 Warnings: 0 - # Add base non-generated column as a last column in the compressed table - ALTER TABLE t1 ADD COLUMN f6 INT NOT NULL; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE -+affected rows: 1 -+info: Records: 1 Duplicates: 0 Warnings: 0 - # Add base non-generated column but not in the last position - ALTER TABLE t1 ADD COLUMN f7 INT NOT NULL after f3; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE -+affected rows: 1 -+info: Records: 1 Duplicates: 0 Warnings: 0 - # Force the table to rebuild - ALTER TABLE t1 FORCE; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE -+affected rows: 1 -+info: Records: 1 Duplicates: 0 Warnings: 0 - # Row format changes - ALTER TABLE t1 ROW_FORMAT=COMPRESSED; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE -+affected rows: 1 -+info: Records: 1 Duplicates: 0 Warnings: 0 - # Engine table - ALTER TABLE t1 ENGINE=INNODB; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE -+affected rows: 1 -+info: Records: 1 Duplicates: 0 Warnings: 0 - DROP TABLE t1; - affected rows: 0 - CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT NOT NULL, -@@ -49,23 +58,23 @@ - INSERT INTO t1(f1, f2, f4, f5) VALUES(1, 2, 3, 4); - SELECT @@alter_algorithm; - @@alter_algorithm --NOCOPY -+COPY - ALTER TABLE t1 ADD INDEX idx1(f4); --affected rows: 0 --info: Records: 0 Duplicates: 0 Warnings: 0 -+affected rows: 1 -+info: Records: 1 Duplicates: 0 Warnings: 0 - ALTER TABLE t1 DROP INDEX idx; --affected rows: 0 --info: Records: 0 Duplicates: 0 Warnings: 0 -+affected rows: 1 -+info: Records: 1 Duplicates: 0 Warnings: 0 - ALTER TABLE t1 ADD UNIQUE INDEX u1(f2); --affected rows: 0 --info: Records: 0 Duplicates: 0 Warnings: 0 -+affected rows: 1 -+info: Records: 1 Duplicates: 0 Warnings: 0 - ALTER TABLE t1 DROP INDEX f4; --affected rows: 0 --info: Records: 0 Duplicates: 0 Warnings: 0 -+affected rows: 1 -+info: Records: 1 Duplicates: 0 Warnings: 0 - SET foreign_key_checks = 0; - affected rows: 0 - ALTER TABLE t1 ADD FOREIGN KEY(f5) REFERENCES t2(f1); --affected rows: 0 --info: Records: 0 Duplicates: 0 Warnings: 0 -+affected rows: 1 -+info: Records: 1 Duplicates: 0 Warnings: 0 - DROP TABLE t2, t1; - affected rows: 0 diff --git a/mysql-test/suite/innodb/r/alter_algorithm,INPLACE.rdiff b/mysql-test/suite/innodb/r/alter_algorithm,INPLACE.rdiff index 71891bbf473..e9a24820a50 100644 --- a/mysql-test/suite/innodb/r/alter_algorithm,INPLACE.rdiff +++ b/mysql-test/suite/innodb/r/alter_algorithm,INPLACE.rdiff @@ -1,66 +1,101 @@ ---- alter_algorithm.result 2018-05-06 23:42:08.022302601 +0530 -+++ alter_algorithm.reject 2018-05-06 23:45:23.813346814 +0530 -@@ -7,35 +7,44 @@ +--- alter_algorithm.result ++++ alter_algorithm.reject +@@ -7,44 +7,44 @@ INSERT INTO t1(f1, f2, f3) VALUES(1, 1, 1); SELECT @@alter_algorithm; @@alter_algorithm --NOCOPY +-COPY +INPLACE # All the following cases needs table rebuild # Add and Drop primary key ALTER TABLE t1 ADD COLUMN col1 INT NOT NULL,DROP PRIMARY KEY,ADD PRIMARY KEY(col1); --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 # Make existing column NULLABLE ALTER TABLE t1 MODIFY f2 INT; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 # Make existing column NON-NULLABLE ALTER TABLE t1 MODIFY f3 INT NOT NULL; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 # Drop Stored Column ALTER TABLE t1 DROP COLUMN f5; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 # Add base non-generated column as a last column in the compressed table ALTER TABLE t1 ADD COLUMN f6 INT NOT NULL; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 # Add base non-generated column but not in the last position ALTER TABLE t1 ADD COLUMN f7 INT NOT NULL after f3; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 # Force the table to rebuild ALTER TABLE t1 FORCE; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 # Row format changes ALTER TABLE t1 ROW_FORMAT=COMPRESSED; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 # Engine table ALTER TABLE t1 ENGINE=INNODB; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 DROP TABLE t1; affected rows: 0 CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT NOT NULL, -@@ -49,7 +58,7 @@ +@@ -58,23 +58,23 @@ INSERT INTO t1(f1, f2, f4, f5) VALUES(1, 2, 3, 4); SELECT @@alter_algorithm; @@alter_algorithm --NOCOPY +-COPY +INPLACE ALTER TABLE t1 ADD INDEX idx1(f4); +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++affected rows: 0 ++info: Records: 0 Duplicates: 0 Warnings: 0 + ALTER TABLE t1 DROP INDEX idx; +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++affected rows: 0 ++info: Records: 0 Duplicates: 0 Warnings: 0 + ALTER TABLE t1 ADD UNIQUE INDEX u1(f2); +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++affected rows: 0 ++info: Records: 0 Duplicates: 0 Warnings: 0 + ALTER TABLE t1 DROP INDEX f4; +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++affected rows: 0 ++info: Records: 0 Duplicates: 0 Warnings: 0 + SET foreign_key_checks = 0; + affected rows: 0 + ALTER TABLE t1 ADD FOREIGN KEY(f5) REFERENCES t2(f1); +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++affected rows: 0 ++info: Records: 0 Duplicates: 0 Warnings: 0 + DROP TABLE t2, t1; affected rows: 0 - info: Records: 0 Duplicates: 0 Warnings: 0 diff --git a/mysql-test/suite/innodb/r/alter_algorithm,INSTANT.rdiff b/mysql-test/suite/innodb/r/alter_algorithm,INSTANT.rdiff index 6e12b78fb9d..c432494dd53 100644 --- a/mysql-test/suite/innodb/r/alter_algorithm,INSTANT.rdiff +++ b/mysql-test/suite/innodb/r/alter_algorithm,INSTANT.rdiff @@ -1,78 +1,87 @@ ---- alter_algorithm.result 2018-05-06 23:42:08.022302601 +0530 -+++ alter_algorithm.reject 2018-05-06 23:46:08.482772800 +0530 -@@ -7,35 +7,35 @@ +--- alter_algorithm.result ++++ alter_algorithm.reject +@@ -7,44 +7,35 @@ INSERT INTO t1(f1, f2, f3) VALUES(1, 1, 1); SELECT @@alter_algorithm; @@alter_algorithm --NOCOPY +-COPY +INSTANT # All the following cases needs table rebuild # Add and Drop primary key ALTER TABLE t1 ADD COLUMN col1 INT NOT NULL,DROP PRIMARY KEY,ADD PRIMARY KEY(col1); --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +Got one of the listed errors # Make existing column NULLABLE ALTER TABLE t1 MODIFY f2 INT; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +Got one of the listed errors # Make existing column NON-NULLABLE ALTER TABLE t1 MODIFY f3 INT NOT NULL; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +Got one of the listed errors # Drop Stored Column ALTER TABLE t1 DROP COLUMN f5; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +Got one of the listed errors # Add base non-generated column as a last column in the compressed table ALTER TABLE t1 ADD COLUMN f6 INT NOT NULL; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +Got one of the listed errors # Add base non-generated column but not in the last position ALTER TABLE t1 ADD COLUMN f7 INT NOT NULL after f3; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +Got one of the listed errors # Force the table to rebuild ALTER TABLE t1 FORCE; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +Got one of the listed errors # Row format changes ALTER TABLE t1 ROW_FORMAT=COMPRESSED; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +Got one of the listed errors # Engine table ALTER TABLE t1 ENGINE=INNODB; --ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +Got one of the listed errors DROP TABLE t1; affected rows: 0 CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT NOT NULL, -@@ -49,23 +49,18 @@ +@@ -58,23 +49,18 @@ INSERT INTO t1(f1, f2, f4, f5) VALUES(1, 2, 3, 4); SELECT @@alter_algorithm; @@alter_algorithm --NOCOPY +-COPY +INSTANT ALTER TABLE t1 ADD INDEX idx1(f4); --affected rows: 0 --info: Records: 0 Duplicates: 0 Warnings: 0 +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY ALTER TABLE t1 DROP INDEX idx; --affected rows: 0 --info: Records: 0 Duplicates: 0 Warnings: 0 +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: DROP INDEX. Try ALGORITHM=NOCOPY ALTER TABLE t1 ADD UNIQUE INDEX u1(f2); --affected rows: 0 --info: Records: 0 Duplicates: 0 Warnings: 0 +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY ALTER TABLE t1 DROP INDEX f4; --affected rows: 0 --info: Records: 0 Duplicates: 0 Warnings: 0 +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: DROP INDEX. Try ALGORITHM=NOCOPY SET foreign_key_checks = 0; affected rows: 0 ALTER TABLE t1 ADD FOREIGN KEY(f5) REFERENCES t2(f1); --affected rows: 0 --info: Records: 0 Duplicates: 0 Warnings: 0 +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY DROP TABLE t2, t1; affected rows: 0 diff --git a/mysql-test/suite/innodb/r/alter_algorithm,NOCOPY.rdiff b/mysql-test/suite/innodb/r/alter_algorithm,NOCOPY.rdiff new file mode 100644 index 00000000000..3ec1eed2e3b --- /dev/null +++ b/mysql-test/suite/innodb/r/alter_algorithm,NOCOPY.rdiff @@ -0,0 +1,92 @@ +--- alter_algorithm.result ++++ alter_algorithm.reject +@@ -7,44 +7,35 @@ + INSERT INTO t1(f1, f2, f3) VALUES(1, 1, 1); + SELECT @@alter_algorithm; + @@alter_algorithm +-COPY ++NOCOPY + # All the following cases needs table rebuild + # Add and Drop primary key + ALTER TABLE t1 ADD COLUMN col1 INT NOT NULL,DROP PRIMARY KEY,ADD PRIMARY KEY(col1); +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++Got one of the listed errors + # Make existing column NULLABLE + ALTER TABLE t1 MODIFY f2 INT; +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++Got one of the listed errors + # Make existing column NON-NULLABLE + ALTER TABLE t1 MODIFY f3 INT NOT NULL; +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++Got one of the listed errors + # Drop Stored Column + ALTER TABLE t1 DROP COLUMN f5; +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++Got one of the listed errors + # Add base non-generated column as a last column in the compressed table + ALTER TABLE t1 ADD COLUMN f6 INT NOT NULL; +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++Got one of the listed errors + # Add base non-generated column but not in the last position + ALTER TABLE t1 ADD COLUMN f7 INT NOT NULL after f3; +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++Got one of the listed errors + # Force the table to rebuild + ALTER TABLE t1 FORCE; +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++Got one of the listed errors + # Row format changes + ALTER TABLE t1 ROW_FORMAT=COMPRESSED; +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++Got one of the listed errors + # Engine table + ALTER TABLE t1 ENGINE=INNODB; +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++Got one of the listed errors + DROP TABLE t1; + affected rows: 0 + CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT NOT NULL, +@@ -58,23 +49,23 @@ + INSERT INTO t1(f1, f2, f4, f5) VALUES(1, 2, 3, 4); + SELECT @@alter_algorithm; + @@alter_algorithm +-COPY ++NOCOPY + ALTER TABLE t1 ADD INDEX idx1(f4); +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++affected rows: 0 ++info: Records: 0 Duplicates: 0 Warnings: 0 + ALTER TABLE t1 DROP INDEX idx; +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++affected rows: 0 ++info: Records: 0 Duplicates: 0 Warnings: 0 + ALTER TABLE t1 ADD UNIQUE INDEX u1(f2); +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++affected rows: 0 ++info: Records: 0 Duplicates: 0 Warnings: 0 + ALTER TABLE t1 DROP INDEX f4; +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++affected rows: 0 ++info: Records: 0 Duplicates: 0 Warnings: 0 + SET foreign_key_checks = 0; + affected rows: 0 + ALTER TABLE t1 ADD FOREIGN KEY(f5) REFERENCES t2(f1); +-affected rows: 1 +-info: Records: 1 Duplicates: 0 Warnings: 0 ++affected rows: 0 ++info: Records: 0 Duplicates: 0 Warnings: 0 + DROP TABLE t2, t1; + affected rows: 0 diff --git a/mysql-test/suite/innodb/r/alter_algorithm.result b/mysql-test/suite/innodb/r/alter_algorithm.result index ee91159bf7a..9a031d9066a 100644 --- a/mysql-test/suite/innodb/r/alter_algorithm.result +++ b/mysql-test/suite/innodb/r/alter_algorithm.result @@ -7,35 +7,44 @@ PRIMARY KEY(f1))ROW_FORMAT=COMPRESSED, ENGINE=INNODB; INSERT INTO t1(f1, f2, f3) VALUES(1, 1, 1); SELECT @@alter_algorithm; @@alter_algorithm -NOCOPY +COPY # All the following cases needs table rebuild # Add and Drop primary key ALTER TABLE t1 ADD COLUMN col1 INT NOT NULL,DROP PRIMARY KEY,ADD PRIMARY KEY(col1); -ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +affected rows: 1 +info: Records: 1 Duplicates: 0 Warnings: 0 # Make existing column NULLABLE ALTER TABLE t1 MODIFY f2 INT; -ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +affected rows: 1 +info: Records: 1 Duplicates: 0 Warnings: 0 # Make existing column NON-NULLABLE ALTER TABLE t1 MODIFY f3 INT NOT NULL; -ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +affected rows: 1 +info: Records: 1 Duplicates: 0 Warnings: 0 # Drop Stored Column ALTER TABLE t1 DROP COLUMN f5; -ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +affected rows: 1 +info: Records: 1 Duplicates: 0 Warnings: 0 # Add base non-generated column as a last column in the compressed table ALTER TABLE t1 ADD COLUMN f6 INT NOT NULL; -ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +affected rows: 1 +info: Records: 1 Duplicates: 0 Warnings: 0 # Add base non-generated column but not in the last position ALTER TABLE t1 ADD COLUMN f7 INT NOT NULL after f3; -ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +affected rows: 1 +info: Records: 1 Duplicates: 0 Warnings: 0 # Force the table to rebuild ALTER TABLE t1 FORCE; -ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +affected rows: 1 +info: Records: 1 Duplicates: 0 Warnings: 0 # Row format changes ALTER TABLE t1 ROW_FORMAT=COMPRESSED; -ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +affected rows: 1 +info: Records: 1 Duplicates: 0 Warnings: 0 # Engine table ALTER TABLE t1 ENGINE=INNODB; -ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +affected rows: 1 +info: Records: 1 Duplicates: 0 Warnings: 0 DROP TABLE t1; affected rows: 0 CREATE TABLE t1(f1 INT PRIMARY KEY, f2 INT NOT NULL, @@ -49,23 +58,23 @@ FOREIGN KEY `fidx` (f1) REFERENCES t1(f1))ENGINE=INNODB; INSERT INTO t1(f1, f2, f4, f5) VALUES(1, 2, 3, 4); SELECT @@alter_algorithm; @@alter_algorithm -NOCOPY +COPY ALTER TABLE t1 ADD INDEX idx1(f4); -affected rows: 0 -info: Records: 0 Duplicates: 0 Warnings: 0 +affected rows: 1 +info: Records: 1 Duplicates: 0 Warnings: 0 ALTER TABLE t1 DROP INDEX idx; -affected rows: 0 -info: Records: 0 Duplicates: 0 Warnings: 0 +affected rows: 1 +info: Records: 1 Duplicates: 0 Warnings: 0 ALTER TABLE t1 ADD UNIQUE INDEX u1(f2); -affected rows: 0 -info: Records: 0 Duplicates: 0 Warnings: 0 +affected rows: 1 +info: Records: 1 Duplicates: 0 Warnings: 0 ALTER TABLE t1 DROP INDEX f4; -affected rows: 0 -info: Records: 0 Duplicates: 0 Warnings: 0 +affected rows: 1 +info: Records: 1 Duplicates: 0 Warnings: 0 SET foreign_key_checks = 0; affected rows: 0 ALTER TABLE t1 ADD FOREIGN KEY(f5) REFERENCES t2(f1); -affected rows: 0 -info: Records: 0 Duplicates: 0 Warnings: 0 +affected rows: 1 +info: Records: 1 Duplicates: 0 Warnings: 0 DROP TABLE t2, t1; affected rows: 0 diff --git a/mysql-test/suite/innodb/r/innodb-page_compression_bzip2.result b/mysql-test/suite/innodb/r/innodb-page_compression_bzip2.result index 61507ddbe5c..5411f5149d1 100644 --- a/mysql-test/suite/innodb/r/innodb-page_compression_bzip2.result +++ b/mysql-test/suite/innodb/r/innodb-page_compression_bzip2.result @@ -147,7 +147,8 @@ count(*) select count(*) from innodb_page_compressed9 where c1 < 500000; count(*) 5000 -alter table innodb_normal page_compressed=1 page_compression_level=8; +alter table innodb_normal page_compressed=1 page_compression_level=8, +algorithm=instant; show warnings; Level Code Message show create table innodb_normal; @@ -156,6 +157,10 @@ innodb_normal CREATE TABLE `innodb_normal` ( `c1` int(11) DEFAULT NULL, `b` char(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `page_compressed`=1 `page_compression_level`=8 +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Changing table options requires the table to be rebuilt. Try ALGORITHM=INPLACE +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=nocopy; +ERROR 0A000: ALGORITHM=NOCOPY is not supported. Reason: Changing table options requires the table to be rebuilt. Try ALGORITHM=INPLACE alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0; show warnings; Level Code Message @@ -174,6 +179,7 @@ update innodb_page_compressed6 set c1 = c1 + 1; update innodb_page_compressed7 set c1 = c1 + 1; update innodb_page_compressed8 set c1 = c1 + 1; update innodb_page_compressed9 set c1 = c1 + 1; +commit; select count(*) from innodb_compressed; count(*) 5000 diff --git a/mysql-test/suite/innodb/r/innodb-page_compression_lz4.result b/mysql-test/suite/innodb/r/innodb-page_compression_lz4.result index 6cef1978ca0..aefb5c8a0be 100644 --- a/mysql-test/suite/innodb/r/innodb-page_compression_lz4.result +++ b/mysql-test/suite/innodb/r/innodb-page_compression_lz4.result @@ -147,7 +147,8 @@ count(*) select count(*) from innodb_page_compressed9 where c1 < 500000; count(*) 5000 -alter table innodb_normal page_compressed=1 page_compression_level=8; +alter table innodb_normal page_compressed=1 page_compression_level=8, +algorithm=instant; show warnings; Level Code Message show create table innodb_normal; @@ -156,6 +157,10 @@ innodb_normal CREATE TABLE `innodb_normal` ( `c1` int(11) DEFAULT NULL, `b` char(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `page_compressed`=1 `page_compression_level`=8 +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Changing table options requires the table to be rebuilt. Try ALGORITHM=INPLACE +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=nocopy; +ERROR 0A000: ALGORITHM=NOCOPY is not supported. Reason: Changing table options requires the table to be rebuilt. Try ALGORITHM=INPLACE alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0; show warnings; Level Code Message diff --git a/mysql-test/suite/innodb/r/innodb-page_compression_lzma.result b/mysql-test/suite/innodb/r/innodb-page_compression_lzma.result index c7ab859e102..606de870d7c 100644 --- a/mysql-test/suite/innodb/r/innodb-page_compression_lzma.result +++ b/mysql-test/suite/innodb/r/innodb-page_compression_lzma.result @@ -147,7 +147,8 @@ count(*) select count(*) from innodb_page_compressed9 where c1 < 500000; count(*) 5000 -alter table innodb_normal page_compressed=1 page_compression_level=8; +alter table innodb_normal page_compressed=1 page_compression_level=8, +algorithm=instant; show warnings; Level Code Message show create table innodb_normal; @@ -156,6 +157,10 @@ innodb_normal CREATE TABLE `innodb_normal` ( `c1` int(11) DEFAULT NULL, `b` char(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `page_compressed`=1 `page_compression_level`=8 +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Changing table options requires the table to be rebuilt. Try ALGORITHM=INPLACE +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=nocopy; +ERROR 0A000: ALGORITHM=NOCOPY is not supported. Reason: Changing table options requires the table to be rebuilt. Try ALGORITHM=INPLACE alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0; show warnings; Level Code Message @@ -174,6 +179,7 @@ update innodb_page_compressed6 set c1 = c1 + 1; update innodb_page_compressed7 set c1 = c1 + 1; update innodb_page_compressed8 set c1 = c1 + 1; update innodb_page_compressed9 set c1 = c1 + 1; +commit; select count(*) from innodb_compressed; count(*) 5000 diff --git a/mysql-test/suite/innodb/r/innodb-page_compression_lzo.result b/mysql-test/suite/innodb/r/innodb-page_compression_lzo.result index 379abcc9968..66783c35d6c 100644 --- a/mysql-test/suite/innodb/r/innodb-page_compression_lzo.result +++ b/mysql-test/suite/innodb/r/innodb-page_compression_lzo.result @@ -147,7 +147,8 @@ count(*) select count(*) from innodb_page_compressed9 where c1 < 500000; count(*) 5000 -alter table innodb_normal page_compressed=1 page_compression_level=8; +alter table innodb_normal page_compressed=1 page_compression_level=8, +algorithm=instant; show warnings; Level Code Message show create table innodb_normal; @@ -156,6 +157,10 @@ innodb_normal CREATE TABLE `innodb_normal` ( `c1` int(11) DEFAULT NULL, `b` char(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `page_compressed`=1 `page_compression_level`=8 +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Changing table options requires the table to be rebuilt. Try ALGORITHM=INPLACE +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=nocopy; +ERROR 0A000: ALGORITHM=NOCOPY is not supported. Reason: Changing table options requires the table to be rebuilt. Try ALGORITHM=INPLACE alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0; show warnings; Level Code Message @@ -174,6 +179,7 @@ update innodb_page_compressed6 set c1 = c1 + 1; update innodb_page_compressed7 set c1 = c1 + 1; update innodb_page_compressed8 set c1 = c1 + 1; update innodb_page_compressed9 set c1 = c1 + 1; +commit; select count(*) from innodb_compressed; count(*) 5000 diff --git a/mysql-test/suite/innodb/r/innodb-page_compression_tables.result b/mysql-test/suite/innodb/r/innodb-page_compression_tables.result index 33b36428040..439f409ea59 100644 --- a/mysql-test/suite/innodb/r/innodb-page_compression_tables.result +++ b/mysql-test/suite/innodb/r/innodb-page_compression_tables.result @@ -88,8 +88,12 @@ select count(*) from innodb_dynamic where c1 < 1500000; count(*) 5000 set global innodb_compression_algorithm = 0; -alter table innodb_compact engine=innodb page_compressed=DEFAULT; -alter table innodb_dynamic engine=innodb page_compressed=DEFAULT; +alter table innodb_compact page_compressed=DEFAULT, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Changing table options requires the table to be rebuilt. Try ALGORITHM=INPLACE +alter table innodb_compact page_compressed=DEFAULT; +alter table innodb_dynamic page_compressed=DEFAULT, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Changing table options requires the table to be rebuilt. Try ALGORITHM=INPLACE +alter table innodb_dynamic page_compressed=DEFAULT; show create table innodb_compact; Table Create Table innodb_compact CREATE TABLE `innodb_compact` ( diff --git a/mysql-test/suite/innodb/r/innodb-page_compression_zip.result b/mysql-test/suite/innodb/r/innodb-page_compression_zip.result index bb9ceb29e17..9dcf676cb3d 100644 --- a/mysql-test/suite/innodb/r/innodb-page_compression_zip.result +++ b/mysql-test/suite/innodb/r/innodb-page_compression_zip.result @@ -147,7 +147,8 @@ count(*) select count(*) from innodb_page_compressed9 where c1 < 500000; count(*) 5000 -alter table innodb_normal page_compressed=1 page_compression_level=8; +alter table innodb_normal page_compressed=1 page_compression_level=8, +algorithm=instant; show warnings; Level Code Message show create table innodb_normal; @@ -156,6 +157,10 @@ innodb_normal CREATE TABLE `innodb_normal` ( `c1` int(11) DEFAULT NULL, `b` char(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `page_compressed`=1 `page_compression_level`=8 +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Changing table options requires the table to be rebuilt. Try ALGORITHM=INPLACE +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=nocopy; +ERROR 0A000: ALGORITHM=NOCOPY is not supported. Reason: Changing table options requires the table to be rebuilt. Try ALGORITHM=INPLACE alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0; show warnings; Level Code Message diff --git a/mysql-test/suite/innodb/t/alter_algorithm.test b/mysql-test/suite/innodb/t/alter_algorithm.test index 5a720489281..23cddd46225 100644 --- a/mysql-test/suite/innodb/t/alter_algorithm.test +++ b/mysql-test/suite/innodb/t/alter_algorithm.test @@ -3,7 +3,7 @@ let $algorithm = `SELECT @@ALTER_ALGORITHM`; let $error_code = 0; if ($algorithm == "NOCOPY") { - let $error_code = ER_ALTER_OPERATION_NOT_SUPPORTED; + let $error_code = ER_ALTER_OPERATION_NOT_SUPPORTED, ER_ALTER_OPERATION_NOT_SUPPORTED_REASON; } if ($algorithm == "INSTANT") { diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_bzip2.test b/mysql-test/suite/innodb/t/innodb-page_compression_bzip2.test index 69a632d6010..2b4a9ea22a9 100644 --- a/mysql-test/suite/innodb/t/innodb-page_compression_bzip2.test +++ b/mysql-test/suite/innodb/t/innodb-page_compression_bzip2.test @@ -2,8 +2,6 @@ -- source include/have_innodb_bzip2.inc -- source include/not_embedded.inc -let $innodb_compression_algorithm_orig=`select @@innodb_compression_algorithm`; - # bzip2 set global innodb_compression_algorithm = 5; @@ -79,9 +77,14 @@ select count(*) from innodb_page_compressed7 where c1 < 500000; select count(*) from innodb_page_compressed8 where c1 < 500000; select count(*) from innodb_page_compressed9 where c1 < 500000; -alter table innodb_normal page_compressed=1 page_compression_level=8; +alter table innodb_normal page_compressed=1 page_compression_level=8, +algorithm=instant; show warnings; show create table innodb_normal; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=nocopy; alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0; show warnings; show create table innodb_compressed; @@ -95,6 +98,7 @@ update innodb_page_compressed6 set c1 = c1 + 1; update innodb_page_compressed7 set c1 = c1 + 1; update innodb_page_compressed8 set c1 = c1 + 1; update innodb_page_compressed9 set c1 = c1 + 1; +commit; select count(*) from innodb_compressed; select count(*) from innodb_page_compressed1; select count(*) from innodb_page_compressed1 where c1 < 500000; @@ -236,8 +240,3 @@ drop table innodb_page_compressed6; drop table innodb_page_compressed7; drop table innodb_page_compressed8; drop table innodb_page_compressed9; - -# reset system ---disable_query_log -EVAL SET GLOBAL innodb_compression_algorithm = $innodb_compression_algorithm_orig; ---enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_lz4.test b/mysql-test/suite/innodb/t/innodb-page_compression_lz4.test index 1b1df674e3c..49255d3a1ac 100644 --- a/mysql-test/suite/innodb/t/innodb-page_compression_lz4.test +++ b/mysql-test/suite/innodb/t/innodb-page_compression_lz4.test @@ -2,8 +2,6 @@ -- source include/have_innodb_lz4.inc -- source include/not_embedded.inc -let $innodb_compression_algorithm_orig=`SELECT @@innodb_compression_algorithm`; - # lz4 set global innodb_compression_algorithm = 2; @@ -79,9 +77,14 @@ select count(*) from innodb_page_compressed7 where c1 < 500000; select count(*) from innodb_page_compressed8 where c1 < 500000; select count(*) from innodb_page_compressed9 where c1 < 500000; -alter table innodb_normal page_compressed=1 page_compression_level=8; +alter table innodb_normal page_compressed=1 page_compression_level=8, +algorithm=instant; show warnings; show create table innodb_normal; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=nocopy; alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0; show warnings; show create table innodb_compressed; @@ -237,8 +240,3 @@ drop table innodb_page_compressed6; drop table innodb_page_compressed7; drop table innodb_page_compressed8; drop table innodb_page_compressed9; - -# reset system ---disable_query_log -EVAL SET GLOBAL innodb_compression_algorithm = $innodb_compression_algorithm_orig; ---enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_lzma.test b/mysql-test/suite/innodb/t/innodb-page_compression_lzma.test index 9cec3e7a947..e05c08f7515 100644 --- a/mysql-test/suite/innodb/t/innodb-page_compression_lzma.test +++ b/mysql-test/suite/innodb/t/innodb-page_compression_lzma.test @@ -2,8 +2,6 @@ -- source include/have_innodb_lzma.inc -- source include/not_embedded.inc -let $innodb_compression_algorithm_orig=`SELECT @@innodb_compression_algorithm`; - # lzma set global innodb_compression_algorithm = 4; @@ -79,9 +77,14 @@ select count(*) from innodb_page_compressed7 where c1 < 500000; select count(*) from innodb_page_compressed8 where c1 < 500000; select count(*) from innodb_page_compressed9 where c1 < 500000; -alter table innodb_normal page_compressed=1 page_compression_level=8; +alter table innodb_normal page_compressed=1 page_compression_level=8, +algorithm=instant; show warnings; show create table innodb_normal; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=nocopy; alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0; show warnings; show create table innodb_compressed; @@ -95,6 +98,7 @@ update innodb_page_compressed6 set c1 = c1 + 1; update innodb_page_compressed7 set c1 = c1 + 1; update innodb_page_compressed8 set c1 = c1 + 1; update innodb_page_compressed9 set c1 = c1 + 1; +commit; select count(*) from innodb_compressed; select count(*) from innodb_page_compressed1; select count(*) from innodb_page_compressed1 where c1 < 500000; @@ -236,8 +240,3 @@ drop table innodb_page_compressed6; drop table innodb_page_compressed7; drop table innodb_page_compressed8; drop table innodb_page_compressed9; - -# reset system ---disable_query_log -EVAL SET GLOBAL innodb_compression_algorithm = $innodb_compression_algorithm_orig; ---enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_lzo.test b/mysql-test/suite/innodb/t/innodb-page_compression_lzo.test index 65c7e5dd3d9..af831bd2467 100644 --- a/mysql-test/suite/innodb/t/innodb-page_compression_lzo.test +++ b/mysql-test/suite/innodb/t/innodb-page_compression_lzo.test @@ -2,8 +2,6 @@ -- source include/have_innodb_lzo.inc -- source include/not_embedded.inc -let $innodb_compression_algorithm_orig=`select @@innodb_compression_algorithm`; - # lzo set global innodb_compression_algorithm = 3; @@ -79,9 +77,14 @@ select count(*) from innodb_page_compressed7 where c1 < 500000; select count(*) from innodb_page_compressed8 where c1 < 500000; select count(*) from innodb_page_compressed9 where c1 < 500000; -alter table innodb_normal page_compressed=1 page_compression_level=8; +alter table innodb_normal page_compressed=1 page_compression_level=8, +algorithm=instant; show warnings; show create table innodb_normal; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=nocopy; alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0; show warnings; show create table innodb_compressed; @@ -95,6 +98,7 @@ update innodb_page_compressed6 set c1 = c1 + 1; update innodb_page_compressed7 set c1 = c1 + 1; update innodb_page_compressed8 set c1 = c1 + 1; update innodb_page_compressed9 set c1 = c1 + 1; +commit; select count(*) from innodb_compressed; select count(*) from innodb_page_compressed1; select count(*) from innodb_page_compressed1 where c1 < 500000; @@ -189,8 +193,3 @@ drop table innodb_page_compressed6; drop table innodb_page_compressed7; drop table innodb_page_compressed8; drop table innodb_page_compressed9; - -# reset system ---disable_query_log -eval set global innodb_compression_algorithm = $innodb_compression_algorithm_orig; ---enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_tables.test b/mysql-test/suite/innodb/t/innodb-page_compression_tables.test index bf83ebf5e82..a51a697931a 100644 --- a/mysql-test/suite/innodb/t/innodb-page_compression_tables.test +++ b/mysql-test/suite/innodb/t/innodb-page_compression_tables.test @@ -70,8 +70,12 @@ select count(*) from innodb_dynamic where c1 < 1500000; # none set global innodb_compression_algorithm = 0; -alter table innodb_compact engine=innodb page_compressed=DEFAULT; -alter table innodb_dynamic engine=innodb page_compressed=DEFAULT; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table innodb_compact page_compressed=DEFAULT, algorithm=instant; +alter table innodb_compact page_compressed=DEFAULT; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table innodb_dynamic page_compressed=DEFAULT, algorithm=instant; +alter table innodb_dynamic page_compressed=DEFAULT; show create table innodb_compact; show create table innodb_dynamic; diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_zip.test b/mysql-test/suite/innodb/t/innodb-page_compression_zip.test index 0c843314eee..45e62722972 100644 --- a/mysql-test/suite/innodb/t/innodb-page_compression_zip.test +++ b/mysql-test/suite/innodb/t/innodb-page_compression_zip.test @@ -1,8 +1,6 @@ --source include/have_innodb.inc --source include/not_embedded.inc -let $innodb_compression_algorithm_orig=`SELECT @@innodb_compression_algorithm`; - # zlib set global innodb_compression_algorithm = 1; @@ -78,9 +76,14 @@ select count(*) from innodb_page_compressed7 where c1 < 500000; select count(*) from innodb_page_compressed8 where c1 < 500000; select count(*) from innodb_page_compressed9 where c1 < 500000; -alter table innodb_normal page_compressed=1 page_compression_level=8; +alter table innodb_normal page_compressed=1 page_compression_level=8, +algorithm=instant; show warnings; show create table innodb_normal; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0, algorithm=nocopy; alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0; show warnings; show create table innodb_compressed; @@ -187,8 +190,3 @@ drop table innodb_page_compressed6; drop table innodb_page_compressed7; drop table innodb_page_compressed8; drop table innodb_page_compressed9; - -# reset system ---disable_query_log -EVAL SET GLOBAL innodb_compression_algorithm = $innodb_compression_algorithm_orig; ---enable_query_log diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 77347472521..a60ddeb3017 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7919,3 +7919,5 @@ ER_VERS_QUERY_IN_PARTITION eng "SYSTEM_TIME partitions in table %`s does not support historical query" ER_KEY_DOESNT_SUPPORT eng "%s index %`s does not support this operation" +ER_ALTER_OPERATION_TABLE_OPTIONS_NEED_REBUILD + eng "Changing table options requires the table to be rebuilt" diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 6a3ad4bd2ab..1b1b8e4ffa8 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -78,7 +78,7 @@ static const alter_table_operations INNOBASE_ALTER_REBUILD = ALTER_ADD_PK_INDEX | ALTER_DROP_PK_INDEX | ALTER_OPTIONS - /* ALTER_OPTIONS needs to check create_option_need_rebuild() */ + /* ALTER_OPTIONS needs to check alter_options_need_rebuild() */ | ALTER_COLUMN_NULLABLE | INNOBASE_DEFAULTS | ALTER_STORED_COLUMN_ORDER @@ -210,6 +210,9 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx (3) Allow the conversion only in non-strict mode. */ const bool allow_not_null; + /** The page_compression_level attribute, or 0 */ + const uint page_compression_level; + ha_innobase_inplace_ctx(row_prebuilt_t*& prebuilt_arg, dict_index_t** drop_arg, ulint num_to_drop_arg, @@ -226,7 +229,9 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx ulint add_autoinc_arg, ulonglong autoinc_col_min_value_arg, ulonglong autoinc_col_max_value_arg, - bool allow_not_null_flag) : + bool allow_not_null_flag, + bool page_compressed, + uint page_compression_level_arg) : inplace_alter_handler_ctx(), prebuilt (prebuilt_arg), add_index (0), add_key_numbers (0), num_to_add_index (0), @@ -254,9 +259,15 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx old_n_cols(prebuilt_arg->table->n_cols), old_cols(prebuilt_arg->table->cols), old_col_names(prebuilt_arg->table->col_names), - allow_not_null(allow_not_null_flag) + allow_not_null(allow_not_null_flag), + page_compression_level(page_compressed + ? (page_compression_level_arg + ? page_compression_level_arg + : page_zip_level) + : 0) { ut_ad(old_n_cols >= DATA_N_SYS_COLS); + ut_ad(page_compression_level <= 9); #ifdef UNIV_DEBUG for (ulint i = 0; i < num_to_add_index; i++) { ut_ad(!add_index[i]->to_be_dropped); @@ -490,11 +501,11 @@ innobase_spatial_exist( return(false); } -/** Determine if CHANGE_CREATE_OPTION requires rebuilding the table. +/** Determine if ALTER_OPTIONS requires rebuilding the table. @param[in] ha_alter_info the ALTER TABLE operation @param[in] table metadata before ALTER TABLE @return whether it is mandatory to rebuild the table */ -static bool create_option_need_rebuild( +static bool alter_options_need_rebuild( const Alter_inplace_info* ha_alter_info, const TABLE* table) { @@ -513,12 +524,12 @@ static bool create_option_need_rebuild( } const ha_table_option_struct& alt_opt= - *ha_alter_info->create_info->option_struct; + *ha_alter_info->create_info->option_struct; const ha_table_option_struct& opt= *table->s->option_struct; - if (alt_opt.page_compressed != opt.page_compressed - || alt_opt.page_compression_level - != opt.page_compression_level + /* Allow an instant change to enable page_compressed, + and any change of page_compression_level. */ + if ((!alt_opt.page_compressed && opt.page_compressed) || alt_opt.encryption != opt.encryption || alt_opt.encryption_key_id != opt.encryption_key_id) { return(true); @@ -541,7 +552,7 @@ innobase_need_rebuild( if ((ha_alter_info->handler_flags & ~(INNOBASE_INPLACE_IGNORE | INNOBASE_ALTER_INSTANT)) == ALTER_OPTIONS) { - return create_option_need_rebuild(ha_alter_info, table); + return alter_options_need_rebuild(ha_alter_info, table); } return !!(ha_alter_info->handler_flags & INNOBASE_ALTER_REBUILD); @@ -689,7 +700,7 @@ instant_alter_column_possible( } return !(ha_alter_info->handler_flags & ALTER_OPTIONS) - || !create_option_need_rebuild(ha_alter_info, table); + || !alter_options_need_rebuild(ha_alter_info, table); } /** Check whether the non-const default value for the field @@ -849,9 +860,11 @@ ha_innobase::check_if_supported_inplace_alter( { DBUG_ENTER("check_if_supported_inplace_alter"); - if ((table->versioned(VERS_TIMESTAMP) - || altered_table->versioned(VERS_TIMESTAMP)) - && innobase_need_rebuild(ha_alter_info, table)) { + const bool need_rebuild = innobase_need_rebuild(ha_alter_info, table); + + if (need_rebuild + && (table->versioned(VERS_TIMESTAMP) + || altered_table->versioned(VERS_TIMESTAMP))) { ha_alter_info->unsupported_reason = "Not implemented for system-versioned tables"; DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); @@ -907,15 +920,15 @@ ha_innobase::check_if_supported_inplace_alter( DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); } -#if 0 - if (altered_table->file->ht != ht) { - /* Non-native partitioning table engine. No longer supported, - due to implementation of native InnoDB partitioning. */ - DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); - } -#endif - - if (!(ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE)) { + switch (ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE) { + case ALTER_OPTIONS: + if (alter_options_need_rebuild(ha_alter_info, table)) { + ha_alter_info->unsupported_reason = my_get_err_msg( + ER_ALTER_OPERATION_TABLE_OPTIONS_NEED_REBUILD); + break; + } + /* fall through */ + case 0: DBUG_RETURN(HA_ALTER_INPLACE_INSTANT); } @@ -1294,9 +1307,8 @@ next_column: if (!online) { /* We already determined that only a non-locking operation is possible. */ - } else if (((ha_alter_info->handler_flags - & ALTER_ADD_PK_INDEX) - || innobase_need_rebuild(ha_alter_info, table)) + } else if ((need_rebuild || (ha_alter_info->handler_flags + & ALTER_ADD_PK_INDEX)) && (innobase_fulltext_exist(altered_table) || innobase_spatial_exist(altered_table) || innobase_indexed_virtual_exist(altered_table))) { @@ -1394,10 +1406,9 @@ cannot_create_many_fulltext_index: } // FIXME: implement Online DDL for system-versioned tables - if ((table->versioned(VERS_TRX_ID) - || altered_table->versioned(VERS_TRX_ID)) - && innobase_need_rebuild(ha_alter_info, table)) { - + if (need_rebuild && + (table->versioned(VERS_TRX_ID) + || altered_table->versioned(VERS_TRX_ID))) { if (ha_alter_info->online) { ha_alter_info->unsupported_reason = "Not implemented for system-versioned tables"; @@ -1406,7 +1417,7 @@ cannot_create_many_fulltext_index: online = false; } - if (fts_need_rebuild || innobase_need_rebuild(ha_alter_info, table)) { + if (need_rebuild || fts_need_rebuild) { DBUG_RETURN(online ? HA_ALTER_INPLACE_COPY_NO_LOCK : HA_ALTER_INPLACE_COPY_LOCK); @@ -6827,11 +6838,14 @@ err_exit: } } + const ha_table_option_struct& alt_opt= + *ha_alter_info->create_info->option_struct; + if (!(ha_alter_info->handler_flags & INNOBASE_ALTER_DATA) || ((ha_alter_info->handler_flags & ~(INNOBASE_INPLACE_IGNORE | INNOBASE_ALTER_INSTANT)) == ALTER_OPTIONS - && !create_option_need_rebuild(ha_alter_info, table))) { + && !alter_options_need_rebuild(ha_alter_info, table))) { if (heap) { ha_alter_info->handler_ctx @@ -6845,7 +6859,9 @@ err_exit: heap, indexed_table, col_names, ULINT_UNDEFINED, 0, 0, (ha_alter_info->ignore - || !thd_is_strict_mode(m_user_thd))); + || !thd_is_strict_mode(m_user_thd)), + alt_opt.page_compressed, + alt_opt.page_compression_level); } DBUG_ASSERT(m_prebuilt->trx->dict_operation_lock_mode == 0); @@ -6974,7 +6990,8 @@ found_col: add_autoinc_col_no, ha_alter_info->create_info->auto_increment_value, autoinc_col_max_value, - ha_alter_info->ignore || !thd_is_strict_mode(m_user_thd)); + ha_alter_info->ignore || !thd_is_strict_mode(m_user_thd), + alt_opt.page_compressed, alt_opt.page_compression_level); DBUG_RETURN(prepare_inplace_alter_table_dict( ha_alter_info, altered_table, table, @@ -7113,7 +7130,7 @@ ok_exit: if ((ha_alter_info->handler_flags & ~(INNOBASE_INPLACE_IGNORE | INNOBASE_ALTER_INSTANT)) == ALTER_OPTIONS - && !create_option_need_rebuild(ha_alter_info, table)) { + && !alter_options_need_rebuild(ha_alter_info, table)) { goto ok_exit; } @@ -8824,6 +8841,58 @@ get_col_list_to_be_dropped( } } +/** Change PAGE_COMPRESSED to ON or change the PAGE_COMPRESSION_LEVEL. +@param[in] level PAGE_COMPRESSION_LEVEL +@param[in] table table before the change +@param[in,out] trx data dictionary transaction +@param[in] table_name table name in MariaDB +@return whether the operation succeeded */ +MY_ATTRIBUTE((nonnull, warn_unused_result)) +static +bool +innobase_page_compression_try( + uint level, + const dict_table_t* table, + trx_t* trx, + const char* table_name) +{ + DBUG_ENTER("innobase_page_compression_try"); + DBUG_ASSERT(level >= 1); + DBUG_ASSERT(level <= 9); + + unsigned flags = table->flags + & ~(0xFU << DICT_TF_POS_PAGE_COMPRESSION_LEVEL); + flags |= 1U << DICT_TF_POS_PAGE_COMPRESSION + | level << DICT_TF_POS_PAGE_COMPRESSION_LEVEL; + + if (table->flags == flags) { + DBUG_RETURN(false); + } + + pars_info_t* info = pars_info_create(); + + pars_info_add_ull_literal(info, "id", table->id); + pars_info_add_int4_literal(info, "type", + dict_tf_to_sys_tables_type(flags)); + + dberr_t error = que_eval_sql(info, + "PROCEDURE CHANGE_COMPRESSION () IS\n" + "BEGIN\n" + "UPDATE SYS_TABLES SET TYPE=:type\n" + "WHERE ID=:id;\n" + "END;\n", + false, trx); + + if (error != DB_SUCCESS) { + my_error_innodb(error, table_name, 0); + trx->error_state = DB_SUCCESS; + trx->op_info = ""; + DBUG_RETURN(true); + } + + DBUG_RETURN(false); +} + /** Commit the changes made during prepare_inplace_alter_table() and inplace_alter_table() inside the data dictionary tables, when not rebuilding the table. @@ -8857,6 +8926,13 @@ commit_try_norebuild( || ctx->num_to_drop_vcol == ha_alter_info->alter_info->drop_list.elements); + if (ctx->page_compression_level + && innobase_page_compression_try(ctx->page_compression_level, + ctx->new_table, trx, + table_name)) { + DBUG_RETURN(true); + } + for (ulint i = 0; i < ctx->num_to_add_index; i++) { dict_index_t* index = ctx->add_index[i]; DBUG_ASSERT(dict_index_get_online_status(index) @@ -9002,6 +9078,57 @@ commit_cache_norebuild( { DBUG_ENTER("commit_cache_norebuild"); DBUG_ASSERT(!ctx->need_rebuild()); + DBUG_ASSERT(ctx->new_table->space != fil_system.temp_space); + DBUG_ASSERT(!ctx->new_table->is_temporary()); + + if (ctx->page_compression_level) { + DBUG_ASSERT(ctx->new_table->space != fil_system.sys_space); + ctx->new_table->flags &= + ~(0xFU << DICT_TF_POS_PAGE_COMPRESSION_LEVEL); + ctx->new_table->flags |= 1 << DICT_TF_POS_PAGE_COMPRESSION + | (ctx->page_compression_level + << DICT_TF_POS_PAGE_COMPRESSION_LEVEL); + + if (fil_space_t* space = ctx->new_table->space) { + bool update = !(space->flags + & FSP_FLAGS_MASK_PAGE_COMPRESSION); + mutex_enter(&fil_system.mutex); + space->flags = (~FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL + & (space->flags + | FSP_FLAGS_MASK_PAGE_COMPRESSION)) + | ctx->page_compression_level + << FSP_FLAGS_MEM_COMPRESSION_LEVEL; + mutex_exit(&fil_system.mutex); + + if (update) { + /* Maybe we should introduce an undo + log record for updating tablespace + flags, and perform the update already + in innobase_page_compression_try(). + + If the server is killed before the + following mini-transaction commit + becomes durable, fsp_flags_try_adjust() + will perform the equivalent adjustment + and warn "adjusting FSP_SPACE_FLAGS". */ + mtr_t mtr; + mtr.start(); + if (buf_block_t* b = buf_page_get( + page_id_t(space->id, 0), + page_size_t(space->flags), + RW_X_LATCH, &mtr)) { + mtr.set_named_space(space); + mlog_write_ulint( + FSP_HEADER_OFFSET + + FSP_SPACE_FLAGS + b->frame, + space->flags + & ~FSP_FLAGS_MEM_MASK, + MLOG_4BYTES, &mtr); + } + mtr.commit(); + } + } + } col_set drop_list; col_set v_drop_list; From 774a4cb5474f932a04ced63bf5751201f2fe8d19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 17 Sep 2018 17:50:56 +0300 Subject: [PATCH 3/8] Mroonga follow-up fix for MDEV-16328 Now that ha_innobase::prepare_inplace_alter_table() is accessing ha_alter_info->create_info->option_struct, we must initialize it in the Mroonga wrapper for ALTER TABLE based on the parsed table options for the wrap_altered_table. --- storage/mroonga/mrn_table.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/storage/mroonga/mrn_table.hpp b/storage/mroonga/mrn_table.hpp index 422d48d234d..70af3ab512f 100644 --- a/storage/mroonga/mrn_table.hpp +++ b/storage/mroonga/mrn_table.hpp @@ -97,6 +97,7 @@ struct st_mrn_slot_data #define MRN_SET_WRAP_ALTER_KEY(file, ha_alter_info) \ alter_table_operations base_handler_flags = ha_alter_info->handler_flags; \ + ha_table_option_struct* base_option_struct = ha_alter_info->create_info->option_struct; \ KEY *base_key_info_buffer = ha_alter_info->key_info_buffer; \ uint base_key_count = ha_alter_info->key_count; \ uint base_index_drop_count = ha_alter_info->index_drop_count; \ @@ -104,6 +105,7 @@ struct st_mrn_slot_data uint base_index_add_count = ha_alter_info->index_add_count; \ uint *base_index_add_buffer = ha_alter_info->index_add_buffer; \ ha_alter_info->handler_flags = file->alter_handler_flags; \ + ha_alter_info->create_info->option_struct = wrap_altered_table->s->option_struct; \ ha_alter_info->key_info_buffer = file->alter_key_info_buffer; \ ha_alter_info->key_count = file->alter_key_count; \ ha_alter_info->index_drop_count = file->alter_index_drop_count; \ @@ -113,6 +115,7 @@ struct st_mrn_slot_data #define MRN_SET_BASE_ALTER_KEY(share, table_share) \ ha_alter_info->handler_flags = base_handler_flags; \ + ha_alter_info->create_info->option_struct = base_option_struct; \ ha_alter_info->key_info_buffer = base_key_info_buffer; \ ha_alter_info->key_count = base_key_count; \ ha_alter_info->index_drop_count = base_index_drop_count; \ From 21f310db30fbf11c1fe7ae3a558c7ec0f0fc2641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 17 Sep 2018 18:10:37 +0300 Subject: [PATCH 4/8] Fix the Windows build --- storage/innobase/handler/handler0alter.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 1b1b8e4ffa8..0c95f6c4a62 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -231,7 +231,7 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx ulonglong autoinc_col_max_value_arg, bool allow_not_null_flag, bool page_compressed, - uint page_compression_level_arg) : + ulonglong page_compression_level_arg) : inplace_alter_handler_ctx(), prebuilt (prebuilt_arg), add_index (0), add_key_numbers (0), num_to_add_index (0), @@ -262,7 +262,7 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx allow_not_null(allow_not_null_flag), page_compression_level(page_compressed ? (page_compression_level_arg - ? page_compression_level_arg + ? uint(page_compression_level_arg) : page_zip_level) : 0) { From e33961611a8423ddfc7fa17ceed3c7a6ab234a57 Mon Sep 17 00:00:00 2001 From: Jacob Mathew Date: Mon, 17 Sep 2018 18:39:16 -0700 Subject: [PATCH 5/8] MDEV-17144: Sample of spider_direct_sql cause crash The crash occurs when the Spider node server attempts to create an error message stating that the temporary table is not found. The function to create the error message is called with incorrect parameters. I fixed the crash by correcting the incorrect parameter values. Author: Jacob Mathew. Reviewer: Kentoku Shiba. --- storage/spider/spd_direct_sql.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/spider/spd_direct_sql.cc b/storage/spider/spd_direct_sql.cc index de355c1068d..d56848f5dbd 100644 --- a/storage/spider/spd_direct_sql.cc +++ b/storage/spider/spd_direct_sql.cc @@ -1706,7 +1706,7 @@ long long spider_direct_sql_body( error_num = ER_SPIDER_UDF_TMP_TABLE_NOT_FOUND_NUM; my_printf_error(ER_SPIDER_UDF_TMP_TABLE_NOT_FOUND_NUM, ER_SPIDER_UDF_TMP_TABLE_NOT_FOUND_STR, - MYF(0), table_list.db, table_list.table_name); + MYF(0), table_list.db.str, table_list.table_name.str); goto error; #if MYSQL_VERSION_ID < 50500 #else From 5ec144cfab58a77b67277d0687fdc09ed17f8029 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Mon, 17 Sep 2018 18:49:53 -0700 Subject: [PATCH 6/8] MDEV-17211 Server crash on query The function JOIN_TAB::choose_best_splitting() did not take into account that for some tables whose fields were used in the GROUP BY list of the specification of a splittable materialized derived there might exist no elements in the array ext_keyuses_for_splitting. --- mysql-test/main/derived_split_innodb.result | 34 +++++++++++++++++++++ mysql-test/main/derived_split_innodb.test | 29 ++++++++++++++++++ sql/opt_split.cc | 2 ++ 3 files changed, 65 insertions(+) diff --git a/mysql-test/main/derived_split_innodb.result b/mysql-test/main/derived_split_innodb.result index 6fa20b721e0..7e4ba8e67eb 100644 --- a/mysql-test/main/derived_split_innodb.result +++ b/mysql-test/main/derived_split_innodb.result @@ -24,3 +24,37 @@ n1 0 1 DROP TABLE t1; +# +# MDEV-17211: splittable materialized derived joining 3 tables with +# GROUP BY list containing fields from 2 of them +# +CREATE TABLE t1 ( +id1 int, i1 int, id2 int, +PRIMARY KEY (id1), KEY (i1), KEY (id2) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1,1); +CREATE TABLE t2 (id2 int, i2 int) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1, 1); +CREATE TABLE t3 (id3 int, i3 int, PRIMARY KEY (id3)) ENGINE=InnoDB; +INSERT INTO t3 VALUES (1,1); +EXPLAIN SELECT id3 +FROM (SELECT t3.id3, t2.i2, t1.id2 FROM t3,t1,t2 +WHERE t3.i3=t1.id1 AND t2.id2=t1.id2 +GROUP BY t3.id3, t1.id2) AS t, +t2 +WHERE t2.id2=t.id2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where +1 PRIMARY ref key0 key0 5 test.t2.id2 2 +2 DERIVED t3 ALL NULL NULL NULL NULL 1 Using where; Using temporary; Using filesort +2 DERIVED t1 eq_ref PRIMARY,id2 PRIMARY 4 test.t3.i3 1 +2 DERIVED t2 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (flat, BNL join) +SELECT id3 +FROM (SELECT t3.id3, t2.i2, t1.id2 FROM t3,t1,t2 +WHERE t3.i3=t1.id1 AND t2.id2=t1.id2 +GROUP BY t3.id3, t1.id2) AS t, +t2 +WHERE t2.id2=t.id2; +id3 +1 +DROP TABLE t1,t2,t3; diff --git a/mysql-test/main/derived_split_innodb.test b/mysql-test/main/derived_split_innodb.test index 2abd6fa9f97..5e5e3d5d723 100644 --- a/mysql-test/main/derived_split_innodb.test +++ b/mysql-test/main/derived_split_innodb.test @@ -24,3 +24,32 @@ eval $q; DROP TABLE t1; +--echo # +--echo # MDEV-17211: splittable materialized derived joining 3 tables with +--echo # GROUP BY list containing fields from 2 of them +--echo # + +CREATE TABLE t1 ( + id1 int, i1 int, id2 int, + PRIMARY KEY (id1), KEY (i1), KEY (id2) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1,1); + +CREATE TABLE t2 (id2 int, i2 int) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1, 1); + +CREATE TABLE t3 (id3 int, i3 int, PRIMARY KEY (id3)) ENGINE=InnoDB; +INSERT INTO t3 VALUES (1,1); + +let $q= +SELECT id3 + FROM (SELECT t3.id3, t2.i2, t1.id2 FROM t3,t1,t2 + WHERE t3.i3=t1.id1 AND t2.id2=t1.id2 + GROUP BY t3.id3, t1.id2) AS t, + t2 + WHERE t2.id2=t.id2; + +eval EXPLAIN $q; +eval $q; + +DROP TABLE t1,t2,t3; diff --git a/sql/opt_split.cc b/sql/opt_split.cc index c5e31ba5bcf..fc3f08464f4 100644 --- a/sql/opt_split.cc +++ b/sql/opt_split.cc @@ -895,6 +895,8 @@ SplM_plan_info * JOIN_TAB::choose_best_splitting(double record_count, continue; JOIN_TAB *tab= join->map2table[tablenr]; TABLE *table= tab->table; + if (keyuse_ext->table != table) + continue; do { uint key= keyuse_ext->key; From 043639f9b0fb23053334f661ac65765cbc8b7cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 18 Sep 2018 21:25:24 +0300 Subject: [PATCH 7/8] Simplify innobase_add_instant_try() Remove some code duplication and dead code. If no 'default row' record exists, the root page must be in the conventional format. Should the page type already be FIL_PAGE_TYPE_INSTANT, we would necessarily hit a debug assertion failure in page_set_instant(). --- storage/innobase/handler/handler0alter.cc | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 0c95f6c4a62..002f4bd8cc9 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -4441,8 +4441,8 @@ empty_table: ut_ad(page_is_root(block->frame)); btr_page_empty(block, NULL, index, 0, &mtr); index->remove_instant(); - mtr.commit(); - return false; + err = DB_SUCCESS; + goto func_exit; } /* Convert the table to the instant ADD COLUMN format. */ @@ -4451,20 +4451,12 @@ empty_table: mtr.start(); index->set_modified(mtr); if (page_t* root = btr_root_get(index, &mtr)) { - switch (fil_page_get_type(root)) { - case FIL_PAGE_TYPE_INSTANT: - DBUG_ASSERT(page_get_instant(root) - == index->n_core_fields); - break; - case FIL_PAGE_INDEX: - DBUG_ASSERT(!page_is_comp(root) - || !page_get_instant(root)); - break; - default: + if (fil_page_get_type(root) != FIL_PAGE_INDEX) { DBUG_ASSERT(!"wrong page type"); - goto func_exit; + goto err_exit; } + DBUG_ASSERT(!page_is_comp(root) || !page_get_instant(root)); mlog_write_ulint(root + FIL_PAGE_TYPE, FIL_PAGE_TYPE_INSTANT, MLOG_2BYTES, &mtr); @@ -4476,6 +4468,7 @@ empty_table: BTR_NO_LOCKING_FLAG, BTR_MODIFY_TREE, index, index->n_uniq, entry, 0, thr, false); } else { +err_exit: err = DB_CORRUPTION; } From 755187c8531ddcf3639b130bc1cd0dc36c7938f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 19 Sep 2018 07:21:24 +0300 Subject: [PATCH 8/8] Terminology: 'metadata record' instead of 'default row' For instant ALTER TABLE, we store a hidden metadata record at the start of the clustered index, to indicate how the format of the records differs from the latest table definition. The term 'default row' is too specific, because it applies to instant ADD COLUMN only, and we will be supporting more classes of instant ALTER TABLE later on. For instant ADD COLUMN, we store the initial default values in the metadata record. --- storage/innobase/btr/btr0cur.cc | 77 +++++++++++------------ storage/innobase/btr/btr0pcur.cc | 4 +- storage/innobase/btr/btr0sea.cc | 8 +-- storage/innobase/data/data0data.cc | 3 +- storage/innobase/dict/dict0stats.cc | 2 +- storage/innobase/fts/fts0fts.cc | 2 +- storage/innobase/handler/handler0alter.cc | 10 +-- storage/innobase/include/data0data.h | 3 +- storage/innobase/include/page0page.h | 14 ++--- storage/innobase/include/rem0rec.h | 14 ++--- storage/innobase/include/row0mysql.h | 2 +- storage/innobase/lock/lock0lock.cc | 64 +++++++++---------- storage/innobase/page/page0cur.cc | 2 +- storage/innobase/page/page0page.cc | 2 +- storage/innobase/rem/rem0rec.cc | 2 +- storage/innobase/row/row0import.cc | 8 +-- storage/innobase/row/row0ins.cc | 7 ++- storage/innobase/row/row0log.cc | 2 +- storage/innobase/row/row0merge.cc | 4 +- storage/innobase/row/row0row.cc | 4 +- storage/innobase/row/row0sel.cc | 22 +++---- storage/innobase/row/row0uins.cc | 2 +- storage/innobase/row/row0umod.cc | 9 ++- storage/innobase/trx/trx0rec.cc | 4 +- 24 files changed, 134 insertions(+), 137 deletions(-) diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 90d795f2596..0f2d3b9289f 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -431,7 +431,7 @@ btr_cur_instant_init_low(dict_index_t* index, mtr_t* mtr) const rec_t* rec = cur.page_cur.rec; - if (page_rec_is_supremum(rec) || !rec_is_default_row(rec, index)) { + if (page_rec_is_supremum(rec) || !rec_is_metadata(rec, index)) { ib::error() << "Table " << index->table->name << " is missing instant ALTER metadata"; index->table->corrupted = true; @@ -452,7 +452,7 @@ incompatible: goto incompatible; } - /* Read the 'default row'. We can get here on server restart + /* Read the metadata. We can get here on server restart or when the table was evicted from the data dictionary cache and is now being accessed again. @@ -471,8 +471,8 @@ inconsistent: goto incompatible; } - /* In fact, because we only ever append fields to the 'default - value' record, it is also OK to perform READ UNCOMMITTED and + /* In fact, because we only ever append fields to the metadata + record, it is also OK to perform READ UNCOMMITTED and then ignore any extra fields, provided that trx_sys.is_registered(DB_TRX_ID). */ if (rec_offs_n_fields(offsets) > index->n_fields @@ -2270,10 +2270,9 @@ need_opposite_intention: ut_ad(index->is_instant()); /* This may be a search tuple for btr_pcur_restore_position(). */ - ut_ad(tuple->info_bits == REC_INFO_DEFAULT_ROW + ut_ad(tuple->info_bits == REC_INFO_METADATA || tuple->info_bits == REC_INFO_MIN_REC_FLAG); - } else if (rec_is_default_row(btr_cur_get_rec(cursor), - index)) { + } else if (rec_is_metadata(btr_cur_get_rec(cursor), index)) { /* Only user records belong in the adaptive hash index. */ } else { @@ -3412,7 +3411,7 @@ fail_err: } else if (index->disable_ahi) { # endif } else if (entry->info_bits & REC_INFO_MIN_REC_FLAG) { - ut_ad(entry->info_bits == REC_INFO_DEFAULT_ROW); + ut_ad(entry->info_bits == REC_INFO_METADATA); ut_ad(index->is_instant()); ut_ad(flags == BTR_NO_LOCKING_FLAG); } else { @@ -3620,7 +3619,7 @@ btr_cur_pessimistic_insert( if (index->disable_ahi); else # endif if (entry->info_bits & REC_INFO_MIN_REC_FLAG) { - ut_ad(entry->info_bits == REC_INFO_DEFAULT_ROW); + ut_ad(entry->info_bits == REC_INFO_METADATA); ut_ad(index->is_instant()); ut_ad((flags & ulint(~BTR_KEEP_IBUF_BITMAP)) == BTR_NO_LOCKING_FLAG); @@ -4100,9 +4099,9 @@ func_exit: /** Trim an update tuple due to instant ADD COLUMN, if needed. For normal records, the trailing instantly added fields that match -the 'default row' are omitted. +the initial default values are omitted. -For the special 'default row' record on a table on which instant +For the special metadata record on a table on which instant ADD COLUMN has already been executed, both ADD COLUMN and the rollback of ADD COLUMN need to be handled specially. @@ -4119,8 +4118,8 @@ btr_cur_trim( const que_thr_t* thr) { if (!index->is_instant()) { - } else if (UNIV_UNLIKELY(update->info_bits == REC_INFO_DEFAULT_ROW)) { - /* We are either updating a 'default row' + } else if (UNIV_UNLIKELY(update->info_bits == REC_INFO_METADATA)) { + /* We are either updating a metadata record (instantly adding columns to a table where instant ADD was already executed) or rolling back such an operation. */ ut_ad(!upd_get_nth_field(update, 0)->orig_len); @@ -4227,9 +4226,9 @@ btr_cur_optimistic_update( || trx_is_recv(thr_get_trx(thr))); #endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ - const bool is_default_row = update->info_bits == REC_INFO_DEFAULT_ROW; + const bool is_metadata = update->info_bits == REC_INFO_METADATA; - if (UNIV_LIKELY(!is_default_row) + if (UNIV_LIKELY(!is_metadata) && !row_upd_changes_field_size_or_external(index, *offsets, update)) { @@ -4389,8 +4388,8 @@ any_extern: lock_rec_store_on_page_infimum(block, rec); } - if (UNIV_UNLIKELY(is_default_row)) { - ut_ad(new_entry->info_bits == REC_INFO_DEFAULT_ROW); + if (UNIV_UNLIKELY(is_metadata)) { + ut_ad(new_entry->info_bits == REC_INFO_METADATA); ut_ad(index->is_instant()); /* This can be innobase_add_instant_try() performing a subsequent instant ADD COLUMN, or its rollback by @@ -4416,9 +4415,9 @@ any_extern: cursor, new_entry, offsets, heap, 0/*n_ext*/, mtr); ut_a(rec); /* <- We calculated above the insert would fit */ - if (UNIV_UNLIKELY(is_default_row)) { + if (UNIV_UNLIKELY(is_metadata)) { /* We must empty the PAGE_FREE list, because if this - was a rollback, the shortened 'default row' record + was a rollback, the shortened metadata record would have too many fields, and we would be unable to know the size of the freed record. */ btr_page_reorganize(page_cursor, index, mtr); @@ -4623,7 +4622,7 @@ btr_cur_pessimistic_update( entry_heap); btr_cur_trim(new_entry, index, update, thr); - const bool is_default_row = new_entry->info_bits + const bool is_metadata = new_entry->info_bits & REC_INFO_MIN_REC_FLAG; /* We have to set appropriate extern storage bits in the new @@ -4717,8 +4716,8 @@ btr_cur_pessimistic_update( page, 1); } - if (UNIV_UNLIKELY(is_default_row)) { - ut_ad(new_entry->info_bits == REC_INFO_DEFAULT_ROW); + if (UNIV_UNLIKELY(is_metadata)) { + ut_ad(new_entry->info_bits == REC_INFO_METADATA); ut_ad(index->is_instant()); /* This can be innobase_add_instant_try() performing a subsequent instant ADD COLUMN, or its rollback by @@ -4757,9 +4756,9 @@ btr_cur_pessimistic_update( if (rec) { page_cursor->rec = rec; - if (UNIV_UNLIKELY(is_default_row)) { + if (UNIV_UNLIKELY(is_metadata)) { /* We must empty the PAGE_FREE list, because if this - was a rollback, the shortened 'default row' record + was a rollback, the shortened metadata record would have too many fields, and we would be unable to know the size of the freed record. */ btr_page_reorganize(page_cursor, index, mtr); @@ -4913,9 +4912,9 @@ btr_cur_pessimistic_update( ut_ad(row_get_rec_trx_id(rec, index, *offsets)); } - if (UNIV_UNLIKELY(is_default_row)) { + if (UNIV_UNLIKELY(is_metadata)) { /* We must empty the PAGE_FREE list, because if this - was a rollback, the shortened 'default row' record + was a rollback, the shortened metadata record would have too many fields, and we would be unable to know the size of the freed record. */ btr_page_reorganize(page_cursor, index, mtr); @@ -5413,16 +5412,16 @@ btr_cur_optimistic_delete_func( if (UNIV_UNLIKELY(page_is_root(block->frame) && page_get_n_recs(block->frame) == 1 + (cursor->index->is_instant() - && !rec_is_default_row(rec, cursor->index)))) { + && !rec_is_metadata(rec, cursor->index)))) { /* The whole index (and table) becomes logically empty. Empty the whole page. That is, if we are deleting the - only user record, also delete the 'default row' record + only user record, also delete the metadata record if one exists (it exists if and only if is_instant()). - If we are deleting the 'default row' record and the + If we are deleting the metadata record and the table becomes empty, clean up the whole page. */ dict_index_t* index = cursor->index; ut_ad(!index->is_instant() - || rec_is_default_row( + || rec_is_metadata( page_rec_get_next_const( page_get_infimum_rec(block->frame)), index)); @@ -5475,7 +5474,7 @@ btr_cur_optimistic_delete_func( page_cur_delete_rec(btr_cur_get_page_cur(cursor), cursor->index, offsets, mtr); /* We must empty the PAGE_FREE list, because - after rollback, this deleted 'default row' record + after rollback, this deleted metadata record would have too many fields, and we would be unable to know the size of the freed record. */ btr_page_reorganize(btr_cur_get_page_cur(cursor), @@ -5628,9 +5627,9 @@ btr_cur_pessimistic_delete( } if (page_is_leaf(page)) { - const bool is_default_row = rec_get_info_bits( + const bool is_metadata = rec_get_info_bits( rec, page_rec_is_comp(rec)) & REC_INFO_MIN_REC_FLAG; - if (UNIV_UNLIKELY(is_default_row)) { + if (UNIV_UNLIKELY(is_metadata)) { /* This should be rolling back instant ADD COLUMN. If this is a recovered transaction, then index->is_instant() will hold until the @@ -5648,15 +5647,15 @@ btr_cur_pessimistic_delete( } } else if (page_get_n_recs(page) == 1 + (index->is_instant() - && !rec_is_default_row(rec, index))) { + && !rec_is_metadata(rec, index))) { /* The whole index (and table) becomes logically empty. Empty the whole page. That is, if we are deleting the - only user record, also delete the 'default row' record + only user record, also delete the metadata record if one exists (it exists if and only if is_instant()). - If we are deleting the 'default row' record and the + If we are deleting the metadata record and the table becomes empty, clean up the whole page. */ ut_ad(!index->is_instant() - || rec_is_default_row( + || rec_is_metadata( page_rec_get_next_const( page_get_infimum_rec(page)), index)); @@ -5673,13 +5672,13 @@ btr_cur_pessimistic_delete( goto return_after_reservations; } - if (UNIV_LIKELY(!is_default_row)) { + if (UNIV_LIKELY(!is_metadata)) { btr_search_update_hash_on_delete(cursor); } else { page_cur_delete_rec(btr_cur_get_page_cur(cursor), index, offsets, mtr); /* We must empty the PAGE_FREE list, because - after rollback, this deleted 'default row' record + after rollback, this deleted metadata record would carry too many fields, and we would be unable to know the size of the freed record. */ btr_page_reorganize(btr_cur_get_page_cur(cursor), diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index 46f563a7379..41661d226e1 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -151,13 +151,13 @@ btr_pcur_store_position( rec = page_rec_get_prev(rec); ut_ad(!page_rec_is_infimum(rec)); - ut_ad(!rec_is_default_row(rec, index)); + ut_ad(!rec_is_metadata(rec, index)); cursor->rel_pos = BTR_PCUR_AFTER; } else if (page_rec_is_infimum_low(offs)) { rec = page_rec_get_next(rec); - if (rec_is_default_row(rec, index)) { + if (rec_is_metadata(rec, index)) { rec = page_rec_get_next(rec); ut_ad(!page_rec_is_supremum(rec)); } diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index 1041ad8614a..0cb7611b433 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -111,7 +111,7 @@ rec_fold( ut_ad(rec_offs_validate(rec, NULL, offsets)); ut_ad(rec_validate(rec, offsets)); ut_ad(page_rec_is_leaf(rec)); - ut_ad(!page_rec_is_default_row(rec)); + ut_ad(!page_rec_is_metadata(rec)); ut_ad(n_fields > 0 || n_bytes > 0); n_fields_rec = rec_offs_n_fields(offsets); @@ -1190,7 +1190,7 @@ retry: rec = page_get_infimum_rec(page); rec = page_rec_get_next_low(rec, page_is_comp(page)); - if (rec_is_default_row(rec, index)) { + if (rec_is_metadata(rec, index)) { rec = page_rec_get_next_low(rec, page_is_comp(page)); } @@ -1398,7 +1398,7 @@ btr_search_build_page_hash_index( rec = page_rec_get_next_const(page_get_infimum_rec(page)); - if (rec_is_default_row(rec, index)) { + if (rec_is_metadata(rec, index)) { rec = page_rec_get_next_const(rec); if (!--n_recs) return; } @@ -1862,7 +1862,7 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) n_bytes, index->id); } - if (!page_rec_is_infimum(rec) && !rec_is_default_row(rec, index)) { + if (!page_rec_is_infimum(rec) && !rec_is_metadata(rec, index)) { offsets = rec_get_offsets( rec, index, offsets, true, btr_search_get_n_fields(n_fields, n_bytes), &heap); diff --git a/storage/innobase/data/data0data.cc b/storage/innobase/data/data0data.cc index 809a60d6431..5c9af8a7da6 100644 --- a/storage/innobase/data/data0data.cc +++ b/storage/innobase/data/data0data.cc @@ -44,7 +44,8 @@ byte data_error; /** Trim the tail of an index tuple before insert or update. After instant ADD COLUMN, if the last fields of a clustered index tuple -match the 'default row', there will be no need to store them. +match the default values that were explicitly specified or implied during +ADD COLUMN, there will be no need to store them. NOTE: A page latch in the index must be held, so that the index may not lose 'instantness' before the trimmed tuple has been inserted or updated. diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 69eebab8e17..ed333caffe5 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -1084,7 +1084,7 @@ dict_stats_analyze_index_level( btr_pcur_get_rec(&pcur), page_is_comp(page))) { ut_ad(btr_pcur_is_on_user_rec(&pcur)); if (level == 0) { - /* Skip the 'default row' pseudo-record */ + /* Skip the metadata pseudo-record */ ut_ad(index->is_instant()); btr_pcur_move_to_next_user_rec(&pcur, mtr); } diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 104700bc913..a558775a97a 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -3733,7 +3733,7 @@ fts_get_max_doc_id( goto func_exit; } - ut_ad(!rec_is_default_row(rec, index)); + ut_ad(!rec_is_metadata(rec, index)); offsets = rec_get_offsets( rec, index, offsets, true, ULINT_UNDEFINED, &heap); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 002f4bd8cc9..86f8ce50a72 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -4236,7 +4236,7 @@ innobase_add_virtual_try( return innodb_update_n_cols(user_table, new_n, trx); } -/** Insert into SYS_COLUMNS and insert/update the 'default row' +/** Insert into SYS_COLUMNS and insert/update the hidden metadata record for instant ADD COLUMN. @param[in,out] ctx ALTER TABLE context for the current partition @param[in] altered_table MySQL table that is being altered @@ -4304,7 +4304,7 @@ innobase_add_instant_try( /* For fixed-length NOT NULL 'core' columns, get a dummy default value from SQL. Note that we will preserve the old values of these - columns when updating the 'default row' + columns when updating the metadata record, to avoid unnecessary updates. */ ulint len = (*af)->pack_length(); DBUG_ASSERT(d->type.mtype != DATA_INT @@ -4371,7 +4371,7 @@ innobase_add_instant_try( memset(roll_ptr, 0, sizeof roll_ptr); dtuple_t* entry = row_build_index_entry(row, NULL, index, ctx->heap); - entry->info_bits = REC_INFO_DEFAULT_ROW; + entry->info_bits = REC_INFO_METADATA; mtr_t mtr; mtr.start(); @@ -4391,7 +4391,7 @@ innobase_add_instant_try( NULL, trx, ctx->heap, NULL); dberr_t err; - if (rec_is_default_row(rec, index)) { + if (rec_is_metadata(rec, index)) { ut_ad(page_rec_is_user_rec(rec)); if (!page_has_next(block->frame) && page_rec_is_last(rec, block->frame)) { @@ -4404,7 +4404,7 @@ innobase_add_instant_try( page as a result of the update. */ upd_t* update = upd_create(index->n_fields, ctx->heap); update->n_fields = n; - update->info_bits = REC_INFO_DEFAULT_ROW; + update->info_bits = REC_INFO_METADATA; /* Add the default values for instantly added columns */ for (unsigned i = 0; i < n; i++) { upd_field_t* uf = upd_get_nth_field(update, i); diff --git a/storage/innobase/include/data0data.h b/storage/innobase/include/data0data.h index d3361ad8b3b..0fa4cbe8777 100644 --- a/storage/innobase/include/data0data.h +++ b/storage/innobase/include/data0data.h @@ -638,7 +638,8 @@ struct dtuple_t { /** Trim the tail of an index tuple before insert or update. After instant ADD COLUMN, if the last fields of a clustered index tuple - match the 'default row', there will be no need to store them. + match the default values that were explicitly specified or implied + during ADD COLUMN, there will be no need to store them. NOTE: A page latch in the index must be held, so that the index may not lose 'instantness' before the trimmed tuple has been inserted or updated. diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h index d3f6bd304a6..db48fef9e69 100644 --- a/storage/innobase/include/page0page.h +++ b/storage/innobase/include/page0page.h @@ -87,12 +87,12 @@ bits are stored in the most significant 5 bits of PAGE_DIRECTION_B. These FIL_PAGE_TYPE_INSTANT and PAGE_INSTANT may be assigned even if instant ADD COLUMN was not committed. Changes to these page header fields -are not undo-logged, but changes to the 'default value record' are. +are not undo-logged, but changes to the hidden metadata record are. If the server is killed and restarted, the page header fields could -remain set even though no 'default value record' is present. +remain set even though no metadata record is present. When the table becomes empty, the PAGE_INSTANT field and the -FIL_PAGE_TYPE can be reset and any 'default value record' be removed. */ +FIL_PAGE_TYPE can be reset and any metadata record be removed. */ #define PAGE_INSTANT 12 /** last insert direction: PAGE_LEFT, .... @@ -285,13 +285,11 @@ page_rec_is_comp(const byte* rec) } # ifdef UNIV_DEBUG -/** Determine if the record is the 'default row' pseudo-record +/** Determine if the record is the metadata pseudo-record in the clustered index. @param[in] rec leaf page record on an index page -@return whether the record is the 'default row' pseudo-record */ -inline -bool -page_rec_is_default_row(const rec_t* rec) +@return whether the record is the metadata pseudo-record */ +inline bool page_rec_is_metadata(const rec_t* rec) { return rec_get_info_bits(rec, page_rec_is_comp(rec)) & REC_INFO_MIN_REC_FLAG; diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 3ee993944e9..c1eae387377 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -70,9 +70,9 @@ enum rec_comp_status_t { REC_STATUS_COLUMNS_ADDED = 4 }; -/** The dtuple_t::info_bits of the 'default row' record. -@see rec_is_default_row() */ -static const byte REC_INFO_DEFAULT_ROW +/** The dtuple_t::info_bits of the metadata pseudo-record. +@see rec_is_metadata() */ +static const byte REC_INFO_METADATA = REC_INFO_MIN_REC_FLAG | REC_STATUS_COLUMNS_ADDED; #define REC_NEW_STATUS 3 /* This is single byte bit-field */ @@ -791,14 +791,12 @@ rec_offs_comp(const ulint* offsets) return(*rec_offs_base(offsets) & REC_OFFS_COMPACT); } -/** Determine if the record is the 'default row' pseudo-record +/** Determine if the record is the metadata pseudo-record in the clustered index. @param[in] rec leaf page record @param[in] index index of the record -@return whether the record is the 'default row' pseudo-record */ -inline -bool -rec_is_default_row(const rec_t* rec, const dict_index_t* index) +@return whether the record is the metadata pseudo-record */ +inline bool rec_is_metadata(const rec_t* rec, const dict_index_t* index) { bool is = rec_get_info_bits(rec, dict_table_is_comp(index->table)) & REC_INFO_MIN_REC_FLAG; diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index 96454995e74..c38f94f5e73 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -688,7 +688,7 @@ struct row_prebuilt_t { to the Innobase format from the MySQL format */ const byte* default_rec; /*!< the default values of all columns - (a "default row") in MySQL format */ + (a "metadata") in MySQL format */ ulint hint_need_to_fetch_extra_cols; /*!< normally this is set to 0; if this is set to ROW_RETRIEVE_PRIMARY_KEY, diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index b7c4f8d37cd..c19797ab9da 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -337,7 +337,7 @@ lock_report_trx_id_insanity( trx_id_t max_trx_id) /*!< in: trx_sys.get_max_trx_id() */ { ut_ad(rec_offs_validate(rec, index, offsets)); - ut_ad(!rec_is_default_row(rec, index)); + ut_ad(!rec_is_metadata(rec, index)); ib::error() << "Transaction id " << trx_id @@ -360,7 +360,7 @@ lock_check_trx_id_sanity( const ulint* offsets) /*!< in: rec_get_offsets(rec, index) */ { ut_ad(rec_offs_validate(rec, index, offsets)); - ut_ad(!rec_is_default_row(rec, index)); + ut_ad(!rec_is_metadata(rec, index)); trx_id_t max_trx_id = trx_sys.get_max_trx_id(); ut_ad(max_trx_id || srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN); @@ -389,7 +389,7 @@ lock_clust_rec_cons_read_sees( ut_ad(dict_index_is_clust(index)); ut_ad(page_rec_is_user_rec(rec)); ut_ad(rec_offs_validate(rec, index, offsets)); - ut_ad(!rec_is_default_row(rec, index)); + ut_ad(!rec_is_metadata(rec, index)); /* Temp-tables are not shared across connections and multiple transactions from different connections cannot simultaneously @@ -428,7 +428,7 @@ lock_sec_rec_cons_read_sees( { ut_ad(page_rec_is_user_rec(rec)); ut_ad(!index->is_primary()); - ut_ad(!rec_is_default_row(rec, index)); + ut_ad(!rec_is_metadata(rec, index)); /* NOTE that we might call this function while holding the search system latch. */ @@ -1222,7 +1222,7 @@ lock_sec_rec_some_has_impl( ut_ad(!dict_index_is_clust(index)); ut_ad(page_rec_is_user_rec(rec)); ut_ad(rec_offs_validate(rec, index, offsets)); - ut_ad(!rec_is_default_row(rec, index)); + ut_ad(!rec_is_metadata(rec, index)); max_trx_id = page_get_max_trx_id(page); @@ -2696,8 +2696,8 @@ lock_move_reorganize_page( ulint old_heap_no; ulint new_heap_no; ut_d(const rec_t* const orec = rec1); - ut_ad(page_rec_is_default_row(rec1) - == page_rec_is_default_row(rec2)); + ut_ad(page_rec_is_metadata(rec1) + == page_rec_is_metadata(rec2)); if (comp) { old_heap_no = rec_get_heap_no_new(rec2); @@ -2718,7 +2718,7 @@ lock_move_reorganize_page( /* Clear the bit in old_lock. */ if (old_heap_no < lock->un_member.rec_lock.n_bits && lock_rec_reset_nth_bit(lock, old_heap_no)) { - ut_ad(!page_rec_is_default_row(orec)); + ut_ad(!page_rec_is_metadata(orec)); /* NOTE that the old lock bitmap could be too small for the new heap number! */ @@ -2799,8 +2799,8 @@ lock_move_rec_list_end( reset the lock bits on the old */ for (;;) { - ut_ad(page_rec_is_default_row(rec1) - == page_rec_is_default_row(rec2)); + ut_ad(page_rec_is_metadata(rec1) + == page_rec_is_metadata(rec2)); ut_d(const rec_t* const orec = rec1); ulint rec1_heap_no; @@ -2837,7 +2837,7 @@ lock_move_rec_list_end( if (rec1_heap_no < lock->un_member.rec_lock.n_bits && lock_rec_reset_nth_bit(lock, rec1_heap_no)) { - ut_ad(!page_rec_is_default_row(orec)); + ut_ad(!page_rec_is_metadata(orec)); if (type_mode & LOCK_WAIT) { lock_reset_lock_and_trx_wait(lock); @@ -2882,7 +2882,7 @@ lock_move_rec_list_start( ut_ad(block->frame == page_align(rec)); ut_ad(new_block->frame == page_align(old_end)); ut_ad(comp == page_rec_is_comp(old_end)); - ut_ad(!page_rec_is_default_row(rec)); + ut_ad(!page_rec_is_metadata(rec)); lock_mutex_enter(); @@ -2908,8 +2908,8 @@ lock_move_rec_list_start( reset the lock bits on the old */ while (rec1 != rec) { - ut_ad(page_rec_is_default_row(rec1) - == page_rec_is_default_row(rec2)); + ut_ad(page_rec_is_metadata(rec1) + == page_rec_is_metadata(rec2)); ut_d(const rec_t* const prev = rec1); ulint rec1_heap_no; @@ -2934,7 +2934,7 @@ lock_move_rec_list_start( if (rec1_heap_no < lock->un_member.rec_lock.n_bits && lock_rec_reset_nth_bit(lock, rec1_heap_no)) { - ut_ad(!page_rec_is_default_row(prev)); + ut_ad(!page_rec_is_metadata(prev)); if (type_mode & LOCK_WAIT) { lock_reset_lock_and_trx_wait(lock); @@ -3014,8 +3014,8 @@ lock_rtr_move_rec_list( rec1 = rec_move[moved].old_rec; rec2 = rec_move[moved].new_rec; - ut_ad(!page_rec_is_default_row(rec1)); - ut_ad(!page_rec_is_default_row(rec2)); + ut_ad(!page_rec_is_metadata(rec1)); + ut_ad(!page_rec_is_metadata(rec2)); if (comp) { rec1_heap_no = rec_get_heap_no_new(rec1); @@ -3094,7 +3094,7 @@ lock_update_merge_right( page which will be discarded */ { - ut_ad(!page_rec_is_default_row(orig_succ)); + ut_ad(!page_rec_is_metadata(orig_succ)); lock_mutex_enter(); @@ -3346,7 +3346,7 @@ lock_update_insert( ulint donator_heap_no; ut_ad(block->frame == page_align(rec)); - ut_ad(!page_rec_is_default_row(rec)); + ut_ad(!page_rec_is_metadata(rec)); /* Inherit the gap-locking locks for rec, in gap mode, from the next record */ @@ -3378,7 +3378,7 @@ lock_update_delete( ulint next_heap_no; ut_ad(page == page_align(rec)); - ut_ad(!page_rec_is_default_row(rec)); + ut_ad(!page_rec_is_metadata(rec)); if (page_is_comp(page)) { heap_no = rec_get_heap_no_new(rec); @@ -4176,7 +4176,7 @@ lock_rec_unlock( ut_ad(block->frame == page_align(rec)); ut_ad(!trx->lock.wait_lock); ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)); - ut_ad(!page_rec_is_default_row(rec)); + ut_ad(!page_rec_is_metadata(rec)); heap_no = page_rec_get_heap_no(rec); @@ -4505,7 +4505,7 @@ lock_rec_print(FILE* file, const lock_t* lock) rec = page_find_rec_with_heap_no( buf_block_get_frame(block), i); - ut_ad(!page_rec_is_default_row(rec)); + ut_ad(!page_rec_is_metadata(rec)); offsets = rec_get_offsets( rec, lock->index, offsets, true, @@ -4977,7 +4977,7 @@ lock_rec_queue_validate( lock = lock_rec_get_next_const(heap_no, lock)) { ut_ad(!trx_is_ac_nl_ro(lock->trx)); - ut_ad(!page_rec_is_default_row(rec)); + ut_ad(!page_rec_is_metadata(rec)); if (index) { ut_a(lock->index == index); @@ -5312,7 +5312,7 @@ lock_rec_insert_check_and_lock( trx_t* trx = thr_get_trx(thr); const rec_t* next_rec = page_rec_get_next_const(rec); ulint heap_no = page_rec_get_heap_no(next_rec); - ut_ad(!rec_is_default_row(next_rec, index)); + ut_ad(!rec_is_metadata(next_rec, index)); lock_mutex_enter(); /* Because this code is invoked for a running transaction by @@ -5440,7 +5440,7 @@ lock_rec_convert_impl_to_expl_for_trx( { ut_ad(trx->is_referenced()); ut_ad(page_rec_is_leaf(rec)); - ut_ad(!rec_is_default_row(rec, index)); + ut_ad(!rec_is_metadata(rec, index)); DEBUG_SYNC_C("before_lock_rec_convert_impl_to_expl_for_trx"); @@ -5517,7 +5517,7 @@ static void lock_rec_other_trx_holds_expl(trx_t *caller_trx, trx_t *trx, { if (trx) { - ut_ad(!page_rec_is_default_row(rec)); + ut_ad(!page_rec_is_metadata(rec)); lock_mutex_enter(); lock_rec_other_trx_holds_expl_arg arg= { page_rec_get_heap_no(rec), block, trx }; @@ -5564,7 +5564,7 @@ lock_rec_convert_impl_to_expl( ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets)); ut_ad(page_rec_is_leaf(rec)); - ut_ad(!rec_is_default_row(rec, index)); + ut_ad(!rec_is_metadata(rec, index)); if (dict_index_is_clust(index)) { trx_id_t trx_id; @@ -5641,7 +5641,7 @@ lock_clust_rec_modify_check_and_lock( return(DB_SUCCESS); } - ut_ad(!rec_is_default_row(rec, index)); + ut_ad(!rec_is_metadata(rec, index)); ut_ad(!index->table->is_temporary()); heap_no = rec_offs_comp(offsets) @@ -5697,7 +5697,7 @@ lock_sec_rec_modify_check_and_lock( ut_ad(block->frame == page_align(rec)); ut_ad(mtr->is_named_space(index->table->space)); ut_ad(page_rec_is_leaf(rec)); - ut_ad(!rec_is_default_row(rec, index)); + ut_ad(!rec_is_metadata(rec, index)); if (flags & BTR_NO_LOCKING_FLAG) { @@ -5791,7 +5791,7 @@ lock_sec_rec_read_check_and_lock( return(DB_SUCCESS); } - ut_ad(!rec_is_default_row(rec, index)); + ut_ad(!rec_is_metadata(rec, index)); heap_no = page_rec_get_heap_no(rec); /* Some transaction may have an implicit x-lock on the record only @@ -5853,7 +5853,7 @@ lock_clust_rec_read_check_and_lock( || gap_mode == LOCK_REC_NOT_GAP); ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(page_rec_is_leaf(rec)); - ut_ad(!rec_is_default_row(rec, index)); + ut_ad(!rec_is_metadata(rec, index)); if ((flags & BTR_NO_LOCKING_FLAG) || srv_read_only_mode @@ -7100,7 +7100,7 @@ lock_update_split_and_merge( lock_mutex_enter(); left_next_rec = page_rec_get_next_const(orig_pred); - ut_ad(!page_rec_is_default_row(left_next_rec)); + ut_ad(!page_rec_is_metadata(left_next_rec)); /* Inherit the locks on the supremum of the left page to the first record which was moved from the right page */ diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc index fb8f62f5fe3..26a8a5574ec 100644 --- a/storage/innobase/page/page0cur.cc +++ b/storage/innobase/page/page0cur.cc @@ -737,7 +737,7 @@ up_slot_match: & REC_INFO_MIN_REC_FLAG)) { ut_ad(!page_has_prev(page_align(mid_rec))); ut_ad(!page_rec_is_leaf(mid_rec) - || rec_is_default_row(mid_rec, index)); + || rec_is_metadata(mid_rec, index)); cmp = 1; goto low_rec_match; } diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index d438e4b64e0..fdab4bfcedd 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -2810,7 +2810,7 @@ page_find_rec_max_not_deleted( const rec_t* prev_rec = NULL; // remove warning /* Because the page infimum is never delete-marked - and never the 'default row' pseudo-record (MIN_REC_FLAG)), + and never the metadata pseudo-record (MIN_REC_FLAG)), prev_rec will always be assigned to it first. */ ut_ad(!rec_get_info_bits(rec, page_rec_is_comp(rec))); ut_ad(page_is_leaf(page)); diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index 7a3aa44bc3f..6b391c2fe76 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -1905,7 +1905,7 @@ rec_copy_prefix_to_buf( case REC_STATUS_COLUMNS_ADDED: /* We would have !index->is_instant() when rolling back an instant ADD COLUMN operation. */ - ut_ad(index->is_instant() || page_rec_is_default_row(rec)); + ut_ad(index->is_instant() || page_rec_is_metadata(rec)); nulls++; const ulint n_rec = ulint(index->n_core_fields) + 1 + rec_get_n_add_field(nulls); diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 8758db3c346..d402f6ee67e 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1462,9 +1462,9 @@ IndexPurge::open() UNIV_NOTHROW btr_pcur_open_at_index_side( true, m_index, BTR_MODIFY_LEAF, &m_pcur, true, 0, &m_mtr); btr_pcur_move_to_next_user_rec(&m_pcur, &m_mtr); - if (rec_is_default_row(btr_pcur_get_rec(&m_pcur), m_index)) { + if (rec_is_metadata(btr_pcur_get_rec(&m_pcur), m_index)) { ut_ad(btr_pcur_is_on_user_rec(&m_pcur)); - /* Skip the 'default row' pseudo-record. */ + /* Skip the metadata pseudo-record. */ } else { btr_pcur_move_to_prev_on_page(&m_pcur); } @@ -2267,8 +2267,8 @@ row_import_set_sys_max_row_id( if (page_rec_is_infimum(rec)) { /* The table is empty. */ err = DB_SUCCESS; - } else if (rec_is_default_row(rec, index)) { - /* The clustered index contains the 'default row', + } else if (rec_is_metadata(rec, index)) { + /* The clustered index contains the metadata record only, that is, the table is empty. */ err = DB_SUCCESS; } else { diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 37ae828d09d..7ab0f8eca37 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -2652,7 +2652,7 @@ row_ins_clust_index_entry_low( #endif /* UNIV_DEBUG */ if (UNIV_UNLIKELY(entry->info_bits != 0)) { - ut_ad(entry->info_bits == REC_INFO_DEFAULT_ROW); + ut_ad(entry->info_bits == REC_INFO_METADATA); ut_ad(flags == BTR_NO_LOCKING_FLAG); ut_ad(index->is_instant()); ut_ad(!dict_index_is_online_ddl(index)); @@ -2667,7 +2667,8 @@ row_ins_clust_index_entry_low( err = DB_DUPLICATE_KEY; goto err_exit; case REC_INFO_MIN_REC_FLAG | REC_INFO_DELETED_FLAG: - /* The 'default row' is never delete-marked. + /* The metadata record never carries the delete-mark + in MariaDB Server 10.3. If a table loses its 'instantness', it happens by the rollback of this first-time insert, or by a call to btr_page_empty() on the root page @@ -2682,7 +2683,7 @@ row_ins_clust_index_entry_low( if (index->is_instant()) entry->trim(*index); - if (rec_is_default_row(btr_cur_get_rec(cursor), index)) { + if (rec_is_metadata(btr_cur_get_rec(cursor), index)) { goto do_insert; } diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index a6e35744446..e94a1cbfc6b 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -970,7 +970,7 @@ row_log_table_low( ut_ad(!"wrong page type"); } #endif /* UNIV_DEBUG */ - ut_ad(!rec_is_default_row(rec, index)); + ut_ad(!rec_is_metadata(rec, index)); ut_ad(page_rec_is_leaf(rec)); ut_ad(!page_is_comp(page_align(rec)) == !rec_offs_comp(offsets)); /* old_pk=row_log_table_get_pk() [not needed in INSERT] is a prefix diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index eaddb8b0432..ad44742e57b 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -1873,9 +1873,9 @@ row_merge_read_clustered_index( btr_pcur_open_at_index_side( true, clust_index, BTR_SEARCH_LEAF, &pcur, true, 0, &mtr); btr_pcur_move_to_next_user_rec(&pcur, &mtr); - if (rec_is_default_row(btr_pcur_get_rec(&pcur), clust_index)) { + if (rec_is_metadata(btr_pcur_get_rec(&pcur), clust_index)) { ut_ad(btr_pcur_is_on_user_rec(&pcur)); - /* Skip the 'default row' pseudo-record. */ + /* Skip the metadata pseudo-record. */ } else { ut_ad(!clust_index->is_instant()); btr_pcur_move_to_prev_on_page(&pcur); diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc index 21a44fc1825..04af5646e6b 100644 --- a/storage/innobase/row/row0row.cc +++ b/storage/innobase/row/row0row.cc @@ -1013,7 +1013,7 @@ row_search_on_row_ref( index = dict_table_get_first_index(table); if (UNIV_UNLIKELY(ref->info_bits != 0)) { - ut_ad(ref->info_bits == REC_INFO_DEFAULT_ROW); + ut_ad(ref->info_bits == REC_INFO_METADATA); ut_ad(ref->n_fields <= index->n_uniq); btr_pcur_open_at_index_side(true, index, mode, pcur, true, 0, mtr); @@ -1021,7 +1021,7 @@ row_search_on_row_ref( /* We do not necessarily have index->is_instant() here, because we could be executing a rollback of an instant ADD COLUMN operation. The function - rec_is_default_row() asserts index->is_instant(); + rec_is_metadata() asserts index->is_instant(); we do not want to call it here. */ return rec_get_info_bits(btr_pcur_get_rec(pcur), dict_table_is_comp(index->table)) diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index c6a463c584b..1531fb38b7f 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -1489,7 +1489,7 @@ row_sel_try_search_shortcut( const rec_t* rec = btr_pcur_get_rec(&(plan->pcur)); - if (!page_rec_is_user_rec(rec) || rec_is_default_row(rec, index)) { + if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, index)) { retry: rw_lock_s_unlock(ahi_latch); return(SEL_RETRY); @@ -1789,8 +1789,8 @@ skip_lock: goto next_rec; } - if (rec_is_default_row(rec, index)) { - /* Skip the 'default row' pseudo-record. */ + if (rec_is_metadata(rec, index)) { + /* Skip the metadata pseudo-record. */ cost_counter++; goto next_rec; } @@ -3011,7 +3011,7 @@ row_sel_store_mysql_field_func( } } else { /* The field is stored in the index record, or - in the 'default row' for instant ADD COLUMN. */ + in the metadata for instant ADD COLUMN. */ if (rec_offs_nth_default(offsets, field_no)) { ut_ad(dict_index_is_clust(index)); @@ -3563,8 +3563,8 @@ sel_restore_position_for_mysql( if (!success && moves_up) { next: if (btr_pcur_move_to_next(pcur, mtr) - && rec_is_default_row(btr_pcur_get_rec(pcur), - pcur->btr_cur.index)) { + && rec_is_metadata(btr_pcur_get_rec(pcur), + pcur->btr_cur.index)) { btr_pcur_move_to_next(pcur, mtr); } @@ -3579,8 +3579,8 @@ next: pcur->pos_state = BTR_PCUR_IS_POSITIONED; prev: if (btr_pcur_is_on_user_rec(pcur) && !moves_up - && !rec_is_default_row(btr_pcur_get_rec(pcur), - pcur->btr_cur.index)) { + && !rec_is_metadata(btr_pcur_get_rec(pcur), + pcur->btr_cur.index)) { btr_pcur_move_to_prev(pcur, mtr); } return true; @@ -3857,7 +3857,7 @@ row_sel_try_search_shortcut_for_mysql( BTR_SEARCH_LEAF, pcur, ahi_latch, mtr); rec = btr_pcur_get_rec(pcur); - if (!page_rec_is_user_rec(rec) || rec_is_default_row(rec, index)) { + if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, index)) { retry: rw_lock_s_unlock(ahi_latch); return(SEL_RETRY); @@ -4758,7 +4758,7 @@ rec_loop: if (comp) { if (rec_get_info_bits(rec, true) & REC_INFO_MIN_REC_FLAG) { - /* Skip the 'default row' pseudo-record. */ + /* Skip the metadata pseudo-record. */ ut_ad(index->is_instant()); goto next_rec; } @@ -4770,7 +4770,7 @@ rec_loop: } } else { if (rec_get_info_bits(rec, false) & REC_INFO_MIN_REC_FLAG) { - /* Skip the 'default row' pseudo-record. */ + /* Skip the metadata pseudo-record. */ ut_ad(index->is_instant()); goto next_rec; } diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index 67a11711fe2..a5d7294c9ed 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -142,7 +142,7 @@ row_undo_ins_remove_clust_rec( /* This is rolling back an INSERT into SYS_COLUMNS. If it was part of an instant ADD COLUMN operation, we must modify the table definition. At this point, any - corresponding operation to the 'default row' will have + corresponding operation to the metadata record will have been rolled back. */ ut_ad(!online); ut_ad(node->trx->dict_operation_lock_mode == RW_X_LATCH); diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index b46d3d83bb0..0ab186aac5e 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -1211,16 +1211,15 @@ close_table: if (node->update->info_bits & REC_INFO_MIN_REC_FLAG) { /* This must be an undo log record for a subsequent - instant ADD COLUMN on a table, extending the - 'default value' record. */ + instant ALTER TABLE, extending the metadata record. */ ut_ad(clust_index->is_instant()); if (node->update->info_bits != REC_INFO_MIN_REC_FLAG) { ut_ad(!"wrong info_bits in undo log record"); goto close_table; } - node->update->info_bits = REC_INFO_DEFAULT_ROW; + node->update->info_bits = REC_INFO_METADATA; const_cast(node->ref)->info_bits - = REC_INFO_DEFAULT_ROW; + = REC_INFO_METADATA; } if (!row_undo_search_clust_to_pcur(node)) { @@ -1297,7 +1296,7 @@ row_undo_mod( ut_ad(dict_index_is_clust(node->index)); if (node->ref->info_bits) { - ut_ad(node->ref->info_bits == REC_INFO_DEFAULT_ROW); + ut_ad(node->ref->info_bits == REC_INFO_METADATA); goto rollback_clust; } diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 90681f20cab..652154ae4c2 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -42,7 +42,7 @@ Created 3/26/1996 Heikki Tuuri /** The search tuple corresponding to TRX_UNDO_INSERT_DEFAULT */ const dtuple_t trx_undo_default_rec = { - REC_INFO_DEFAULT_ROW, 0, 0, + REC_INFO_METADATA, 0, 0, NULL, 0, NULL, UT_LIST_NODE_T(dtuple_t)() #ifdef UNIV_DEBUG @@ -506,7 +506,7 @@ trx_undo_page_report_insert( /* Store then the fields required to uniquely determine the record to be inserted in the clustered index */ if (UNIV_UNLIKELY(clust_entry->info_bits != 0)) { - ut_ad(clust_entry->info_bits == REC_INFO_DEFAULT_ROW); + ut_ad(clust_entry->info_bits == REC_INFO_METADATA); ut_ad(index->is_instant()); ut_ad(undo_block->frame[first_free + 2] == TRX_UNDO_INSERT_REC);