From b29b30e75ec5ff60970a7d80c96adbc830318a5a Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Tue, 14 Jan 2025 22:41:15 +0100 Subject: [PATCH] MDEV-35737 MSAN errors in check_table_referential_checks_needed upon LOAD INDEX LOAD INDEX doesn't initialize Lex->check_opt and mysql_preload_keys doesn't use it. However, Check_table_prelocking_strategy did, and it's always used in opening table. One solution could be using a different prelocking strategy for mysql_preload_keys. Let's instead just pass a correct check_opt to Check_table_prelocking_strategy. Base task: MDEV-34309 --- mysql-test/main/check_table_references.result | 7 +++++++ mysql-test/main/check_table_references.test | 7 +++++++ sql/handler.cc | 2 +- sql/handler.h | 2 +- sql/sql_admin.cc | 5 +++-- sql/sql_base.h | 12 ++++++++---- 6 files changed, 27 insertions(+), 8 deletions(-) diff --git a/mysql-test/main/check_table_references.result b/mysql-test/main/check_table_references.result index 2ee26881cd9..8c703c30382 100644 --- a/mysql-test/main/check_table_references.result +++ b/mysql-test/main/check_table_references.result @@ -224,3 +224,10 @@ test.nosuchtable check Error Table 'test.nosuchtable' doesn't exist test.nosuchtable check status Operation failed drop table t2; drop table t1; +# MDEV-35737 MSAN errors in check_table_referential_checks_needed upon +# LOAD INDEX +create table t (pk int primary key) engine=innodb; +load index into cache t; +Table Op Msg_type Msg_text +test.t preload_keys note The storage engine for the table doesn't support preload_keys +drop table t; diff --git a/mysql-test/main/check_table_references.test b/mysql-test/main/check_table_references.test index 0c85143812b..588526b3497 100644 --- a/mysql-test/main/check_table_references.test +++ b/mysql-test/main/check_table_references.test @@ -148,3 +148,10 @@ execute stmt; drop table t2; drop table t1; + +--echo # MDEV-35737 MSAN errors in check_table_referential_checks_needed upon +--echo # LOAD INDEX + +create table t (pk int primary key) engine=innodb; +load index into cache t; +drop table t; diff --git a/sql/handler.cc b/sql/handler.cc index 09de322d9a4..32c24dc335a 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -5394,7 +5394,7 @@ int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt) } if (unlikely((error= check(thd, check_opt)))) return error; - if (check_table_referential_checks_needed(thd) && + if (check_table_referential_checks_needed(thd->variables, *check_opt) && unlikely(error = check_foreign_key_relations(thd, table))) return error; for (uint i= table->s->keys; i < table->s->total_keys; i++) diff --git a/sql/handler.h b/sql/handler.h index 7e818b6d92a..f8c79f82186 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2752,7 +2752,7 @@ typedef class Item COND; typedef struct st_ha_check_opt { - st_ha_check_opt() = default; /* Remove gcc warning */ + st_ha_check_opt() = default; uint flags; /* isam layer flags (e.g. for myisamchk) */ uint sql_flags; /* sql layer flags - for something myisamchk cannot do */ uint handler_flags; /* Reserved for handler usage */ diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index d4c046b6be6..f0740a62370 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -650,7 +650,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, /* open only one table from local list of command */ while (1) { - Check_table_prelocking_strategy prelocking_strategy; + Check_table_prelocking_strategy prelocking_strategy(*check_opt); open_error= open_only_one_table(thd, table, no_errors_from_open, (view_operator_func != NULL), @@ -1603,12 +1603,13 @@ bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, bool mysql_preload_keys(THD* thd, TABLE_LIST* tables) { DBUG_ENTER("mysql_preload_keys"); + HA_CHECK_OPT check_opt {}; /* We cannot allow concurrent inserts. The storage engine reads directly from the index file, bypassing the cache. It could read outdated information if parallel inserts into cache blocks happen. */ - DBUG_RETURN(mysql_admin_table(thd, tables, 0, + DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt, &msg_preload_keys, TL_READ_NO_INSERT, 0, 0, 0, 0, &handler::preload_keys, 0, false)); diff --git a/sql/sql_base.h b/sql/sql_base.h index 538b3d69ddf..20075f699f7 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -398,10 +398,11 @@ inline bool setup_fields_with_no_wrap(THD *thd, Ref_ptr_array ref_pointer_array, } inline static -bool check_table_referential_checks_needed(THD *thd) +bool check_table_referential_checks_needed(const system_variables &variables, + const HA_CHECK_OPT &check_opt) { - return thd->lex->check_opt.flags & T_EXTEND - && !(thd->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS); + bool check_fk= !(variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS); + return check_opt.flags & T_EXTEND && check_fk; } /** @@ -514,12 +515,15 @@ public: class Check_table_prelocking_strategy : public DML_prelocking_strategy { + const HA_CHECK_OPT &check_opt; public: + explicit Check_table_prelocking_strategy(const HA_CHECK_OPT &check_opt) + : check_opt(check_opt) {} bool handle_table(THD *thd, Query_tables_list *prelocking_ctx, TABLE_LIST *table_list, bool *need_prelocking) override; bool may_need_prelocking(THD *thd, TABLE_LIST *table) const override { - return check_table_referential_checks_needed(thd); + return check_table_referential_checks_needed(thd->variables, check_opt); } TABLE_LIST::enum_open_strategy