mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
MDEV-35731 Assertion `(mem_root->flags & 4) == 0' failed upon 2nd exec of CHECK
... TABLE with FK The normal order of things in prepared statement is: 1. open tables during prepare 2. use them during all the executions Currently, tables are opened in the body of CHECK TABLE's execution part. This is motivated by the nature of this statement: we have to run the checks for all the tables specified in the list, event if some of them fail to open. Rewriting it as in normal order is possible, but is out of scope of this task. That is, we shouldn't activate stmt_arena when constructing the referential tables list. It's not enough, since the next statement execution will try to reuse all the TABLE_LIST's in lex->query_list, but the referential tables are allocated on the normal query arena, so they should be cleaned up from that list. Given how specific the open_only_one_table work is, we only have to re-link table lists as they were before the tables are opened. It's enough to just assign next_local to next_global for each table specified by user, i.e. in lex->first_select_lex(). lex->query_tables_last and other lex fields are already maintained by that function. Base task: MDEV-34309
This commit is contained in:
parent
2af2808f57
commit
e6862c0620
4 changed files with 68 additions and 1 deletions
|
@ -186,3 +186,41 @@ Table Op Msg_type Msg_text
|
|||
test.t check Warning Cannot add or update a child row: a foreign key constraint fails (Key: t_ibfk_1, record: '\x00')
|
||||
test.t check error Corrupt
|
||||
DROP TABLE t;
|
||||
# MDEV-35731 Assertion `(mem_root->flags & 4) == 0' failed upon 2nd
|
||||
# execution of CHECK TABLE with FK
|
||||
create table t1 (a int) engine=innodb;
|
||||
set foreign_key_checks = off;
|
||||
alter table t1 add foreign key (a) references x(x);
|
||||
set foreign_key_checks = on;
|
||||
prepare stmt from 'check table t1 extended';
|
||||
execute stmt;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check Warning Table test.x is not found. Needed for a foreign key t1_ibfk_1
|
||||
test.t1 check error Corrupt
|
||||
execute stmt;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check Warning Table test.x is not found. Needed for a foreign key t1_ibfk_1
|
||||
test.t1 check error Corrupt
|
||||
create table t2 (a int) engine=innodb;
|
||||
set foreign_key_checks = off;
|
||||
alter table t2 add foreign key (a) references x(x);
|
||||
set foreign_key_checks = on;
|
||||
prepare stmt from 'check table t1, t2, nosuchtable extended';
|
||||
execute stmt;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check Warning Table test.x is not found. Needed for a foreign key t1_ibfk_1
|
||||
test.t1 check error Corrupt
|
||||
test.t2 check Warning Table test.x is not found. Needed for a foreign key t2_ibfk_1
|
||||
test.t2 check error Corrupt
|
||||
test.nosuchtable check Error Table 'test.nosuchtable' doesn't exist
|
||||
test.nosuchtable check status Operation failed
|
||||
execute stmt;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check Warning Table test.x is not found. Needed for a foreign key t1_ibfk_1
|
||||
test.t1 check error Corrupt
|
||||
test.t2 check Warning Table test.x is not found. Needed for a foreign key t2_ibfk_1
|
||||
test.t2 check error Corrupt
|
||||
test.nosuchtable check Error Table 'test.nosuchtable' doesn't exist
|
||||
test.nosuchtable check status Operation failed
|
||||
drop table t2;
|
||||
drop table t1;
|
||||
|
|
|
@ -126,3 +126,26 @@ ALTER TABLE t ADD FOREIGN KEY (b) REFERENCES t (a);
|
|||
SET FOREIGN_KEY_CHECKS = ON;
|
||||
CHECK TABLE t EXTENDED;
|
||||
DROP TABLE t;
|
||||
|
||||
|
||||
--echo # MDEV-35731 Assertion `(mem_root->flags & 4) == 0' failed upon 2nd
|
||||
--echo # execution of CHECK TABLE with FK
|
||||
|
||||
create table t1 (a int) engine=innodb;
|
||||
set foreign_key_checks = off;
|
||||
alter table t1 add foreign key (a) references x(x);
|
||||
set foreign_key_checks = on;
|
||||
prepare stmt from 'check table t1 extended';
|
||||
execute stmt;
|
||||
execute stmt;
|
||||
|
||||
create table t2 (a int) engine=innodb;
|
||||
set foreign_key_checks = off;
|
||||
alter table t2 add foreign key (a) references x(x);
|
||||
set foreign_key_checks = on;
|
||||
prepare stmt from 'check table t1, t2, nosuchtable extended';
|
||||
execute stmt;
|
||||
execute stmt;
|
||||
|
||||
drop table t2;
|
||||
drop table t1;
|
||||
|
|
|
@ -1468,6 +1468,13 @@ send_result_message:
|
|||
}
|
||||
close_thread_tables(thd);
|
||||
|
||||
/*
|
||||
Opening tables and extending table list doesn't happen on the prepare
|
||||
stage here, so we have to make sure that Prepared_statement won't try to
|
||||
reuse table lists, that have a statement execution lifetime.
|
||||
*/
|
||||
table->next_global= table->next_local;
|
||||
|
||||
if (storage_engine_name[0])
|
||||
{
|
||||
/* Table was changed (repair, optimize or something similar) */
|
||||
|
|
|
@ -5200,7 +5200,6 @@ Check_table_prelocking_strategy::handle_table(THD *thd,
|
|||
TABLE_LIST *tables,
|
||||
bool *need_prelocking)
|
||||
{
|
||||
Query_arena_stmt stmt_ctx(thd);
|
||||
List <FOREIGN_KEY_INFO> fk_child_list, fk_parent_list;
|
||||
tables->table->file->get_foreign_key_list(thd, &fk_child_list);
|
||||
tables->table->file->get_parent_foreign_key_list(thd, &fk_parent_list);
|
||||
|
|
Loading…
Reference in a new issue