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
This commit is contained in:
Nikita Malyavin 2025-01-14 22:41:15 +01:00
parent d4707d3206
commit b29b30e75e
6 changed files with 27 additions and 8 deletions

View file

@ -224,3 +224,10 @@ test.nosuchtable check Error Table 'test.nosuchtable' doesn't exist
test.nosuchtable check status Operation failed test.nosuchtable check status Operation failed
drop table t2; drop table t2;
drop table t1; 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;

View file

@ -148,3 +148,10 @@ execute stmt;
drop table t2; drop table t2;
drop table t1; 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;

View file

@ -5394,7 +5394,7 @@ int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
} }
if (unlikely((error= check(thd, check_opt)))) if (unlikely((error= check(thd, check_opt))))
return error; 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))) unlikely(error = check_foreign_key_relations(thd, table)))
return error; return error;
for (uint i= table->s->keys; i < table->s->total_keys; i++) for (uint i= table->s->keys; i < table->s->total_keys; i++)

View file

@ -2752,7 +2752,7 @@ typedef class Item COND;
typedef struct st_ha_check_opt 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 flags; /* isam layer flags (e.g. for myisamchk) */
uint sql_flags; /* sql layer flags - for something myisamchk cannot do */ uint sql_flags; /* sql layer flags - for something myisamchk cannot do */
uint handler_flags; /* Reserved for handler usage */ uint handler_flags; /* Reserved for handler usage */

View file

@ -650,7 +650,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
/* open only one table from local list of command */ /* open only one table from local list of command */
while (1) while (1)
{ {
Check_table_prelocking_strategy prelocking_strategy; Check_table_prelocking_strategy prelocking_strategy(*check_opt);
open_error= open_only_one_table(thd, table, open_error= open_only_one_table(thd, table,
no_errors_from_open, no_errors_from_open,
(view_operator_func != NULL), (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) bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
{ {
DBUG_ENTER("mysql_preload_keys"); DBUG_ENTER("mysql_preload_keys");
HA_CHECK_OPT check_opt {};
/* /*
We cannot allow concurrent inserts. The storage engine reads We cannot allow concurrent inserts. The storage engine reads
directly from the index file, bypassing the cache. It could read directly from the index file, bypassing the cache. It could read
outdated information if parallel inserts into cache blocks happen. 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, &msg_preload_keys, TL_READ_NO_INSERT,
0, 0, 0, 0, 0, 0, 0, 0,
&handler::preload_keys, 0, false)); &handler::preload_keys, 0, false));

View file

@ -398,10 +398,11 @@ inline bool setup_fields_with_no_wrap(THD *thd, Ref_ptr_array ref_pointer_array,
} }
inline static 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 bool check_fk= !(variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS);
&& !(thd->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 class Check_table_prelocking_strategy : public DML_prelocking_strategy
{ {
const HA_CHECK_OPT &check_opt;
public: 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, bool handle_table(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking) override; TABLE_LIST *table_list, bool *need_prelocking) override;
bool may_need_prelocking(THD *thd, TABLE_LIST *table) const 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 TABLE_LIST::enum_open_strategy