From c65fdcf7c81c47791966ec693a2dbcf6253e77bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 13 Oct 2017 21:59:15 +0300 Subject: MDEV-14062 Upgrade from 10.0 fails on assertion during ALTER TABLE The fix in MDEV-14022 was incomplete. We must adjust some more code for the fact that SYS_INDEXES records may lack the column MERGE_THRESHOLD that was "instantly" added in MySQL 5.7 and MariaDB 10.2.2. dict_boot(): Hard-core SYS_INDEXES.MERGE_THRESHOLD as DEFAULT NULL. dict_index_t::instant_field_value(), rec_offs_make_valid(): Tolerate the missing SYS_INDEXES.MERGE_THRESHOLD column. --- storage/innobase/dict/dict0boot.cc | 7 +++++++ storage/innobase/include/dict0boot.h | 2 +- storage/innobase/include/dict0mem.h | 6 ++++-- storage/innobase/rem/rem0rec.cc | 3 ++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc index 29707e5bdc2..1d79a2b4bcf 100644 --- a/storage/innobase/dict/dict0boot.cc +++ b/storage/innobase/dict/dict0boot.cc @@ -440,6 +440,13 @@ dict_boot(void) table->id = DICT_INDEXES_ID; dict_table_add_system_columns(table, heap); + /* The column SYS_INDEXES.MERGE_THRESHOLD was "instantly" + added in MySQL 5.7 and MariaDB 10.2.2. Assign it DEFAULT NULL. + Because of file format compatibility, we must treat SYS_INDEXES + as a special case, relaxing some debug assertions + for DICT_INDEXES_ID. */ + dict_table_get_nth_col(table, DICT_COL__SYS_INDEXES__MERGE_THRESHOLD) + ->def_val.len = UNIV_SQL_NULL; table->add_to_cache(); dict_sys->sys_indexes = table; mem_heap_empty(heap); diff --git a/storage/innobase/include/dict0boot.h b/storage/innobase/include/dict0boot.h index d6de7dcf71b..25aced44b2e 100644 --- a/storage/innobase/include/dict0boot.h +++ b/storage/innobase/include/dict0boot.h @@ -122,7 +122,7 @@ dict_is_sys_table( /* The ids for the basic system tables and their indexes */ #define DICT_TABLES_ID 1 #define DICT_COLUMNS_ID 2 -#define DICT_INDEXES_ID 3 +#define DICT_INDEXES_ID dict_index_t::DICT_INDEXES_ID /* 3 */ #define DICT_FIELDS_ID 4 /* The following is a secondary index on SYS_TABLES */ #define DICT_TABLE_IDS_ID 5 diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 152ff3f2fd6..ecfe37f9cc7 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -906,6 +906,8 @@ struct dict_index_t{ /** magic value signalling that n_core_null_bytes was not initialized yet */ static const unsigned NO_CORE_NULL_BYTES = 0xff; + /** The clustered index ID of the hard-coded SYS_INDEXES table. */ + static const unsigned DICT_INDEXES_ID = 3; unsigned cached:1;/*!< TRUE if the index object is in the dictionary cache */ unsigned to_be_dropped:1; @@ -1065,8 +1067,8 @@ struct dict_index_t{ @retval NULL if the default value is SQL NULL (len=UNIV_SQL_NULL) */ const byte* instant_field_value(uint n, ulint* len) const { - DBUG_ASSERT(is_instant()); - DBUG_ASSERT(n >= n_core_fields); + DBUG_ASSERT(is_instant() || id == DICT_INDEXES_ID); + DBUG_ASSERT(n + (id == DICT_INDEXES_ID) >= n_core_fields); DBUG_ASSERT(n < n_fields); return fields[n].col->instant_value(len); } diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index 3fed98f0f3d..c9d35521708 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -480,7 +480,8 @@ rec_offs_make_valid( /* The infimum and supremum records carry 1 field. */ ut_ad(is_user_rec || n == 1); ut_ad(is_user_rec || rec_offs_n_fields(offsets) == 1); - ut_ad(!is_user_rec || n >= index->n_core_fields + ut_ad(!is_user_rec + || (n + (index->id == DICT_INDEXES_ID)) >= index->n_core_fields || n >= rec_offs_n_fields(offsets)); for (; n < rec_offs_n_fields(offsets); n++) { ut_ad(leaf); -- cgit v1.2.1