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
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;

View file

@ -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;

View file

@ -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++)

View file

@ -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 */

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 */
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));

View file

@ -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