mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-30378 Versioned REPLACE succeeds with ON DELETE RESTRICT constraint
node->is_delete was incorrectly set to NO_DELETE for a set of operations. In general we shouldn't rely on sql_command and look for more abstract ways to control the behavior. trg_event_map seems to be a suitable way. To mind replica nodes, it is ORed with slave_fk_event_map, which stores trg_event_map when replica has triggers disabled.
This commit is contained in:
@ -493,3 +493,42 @@ set foreign_key_checks= on;
|
||||
delete history from t1;
|
||||
delete from t1;
|
||||
drop table t1;
|
||||
#
|
||||
# MDEV-30378 Versioned REPLACE succeeds with ON DELETE RESTRICT
|
||||
# constraint
|
||||
#
|
||||
create table t0 (pk integer primary key) with system versioning engine=innodb;
|
||||
create table t1 (pk integer primary key,
|
||||
foreign key(pk) references t0(pk)
|
||||
on delete restrict on update cascade) engine=innodb;
|
||||
create table t2 (pk integer);
|
||||
insert into t0 (pk) values (1);
|
||||
insert into t1 (pk) values (1);
|
||||
insert into t2 (pk) values (1);
|
||||
delete from t0;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`pk`) REFERENCES `t0` (`pk`) ON UPDATE CASCADE)
|
||||
replace t0 values (1);
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`pk`) REFERENCES `t0` (`pk`) ON UPDATE CASCADE)
|
||||
select * into outfile 'load_t0' from t0 ;
|
||||
load data infile 'load_t0' replace into table t0;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`pk`) REFERENCES `t0` (`pk`) ON UPDATE CASCADE)
|
||||
delete t0, t2 from t0 join t2;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`pk`) REFERENCES `t0` (`pk`) ON UPDATE CASCADE)
|
||||
select pk from t0;
|
||||
pk
|
||||
1
|
||||
# Cleanup
|
||||
drop table t1, t0, t2;
|
||||
# create_select for a temporary table didn't set up pos_in_locked_tables.
|
||||
create table t (a int unique) engine=innodb
|
||||
replace select 1 as a, 2 as b union select 1 as a, 3 as c;
|
||||
select * from t;
|
||||
a b
|
||||
1 3
|
||||
drop table t;
|
||||
create temporary table t (a int unique) engine=innodb
|
||||
replace select 1 as a, 2 as b union select 1 as a, 3 as c;
|
||||
select * from t;
|
||||
a b
|
||||
1 3
|
||||
drop table t;
|
||||
|
@ -527,4 +527,50 @@ delete from t1;
|
||||
# cleanup
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-30378 Versioned REPLACE succeeds with ON DELETE RESTRICT
|
||||
--echo # constraint
|
||||
--echo #
|
||||
create table t0 (pk integer primary key) with system versioning engine=innodb;
|
||||
create table t1 (pk integer primary key,
|
||||
foreign key(pk) references t0(pk)
|
||||
on delete restrict on update cascade) engine=innodb;
|
||||
create table t2 (pk integer);
|
||||
|
||||
insert into t0 (pk) values (1);
|
||||
insert into t1 (pk) values (1);
|
||||
insert into t2 (pk) values (1);
|
||||
|
||||
--error ER_ROW_IS_REFERENCED_2
|
||||
delete from t0;
|
||||
|
||||
--error ER_ROW_IS_REFERENCED_2
|
||||
replace t0 values (1);
|
||||
|
||||
select * into outfile 'load_t0' from t0 ;
|
||||
--error ER_ROW_IS_REFERENCED_2
|
||||
load data infile 'load_t0' replace into table t0;
|
||||
|
||||
--error ER_ROW_IS_REFERENCED_2
|
||||
delete t0, t2 from t0 join t2;
|
||||
|
||||
select pk from t0;
|
||||
|
||||
--echo # Cleanup
|
||||
drop table t1, t0, t2;
|
||||
--let $datadir= `select @@datadir`
|
||||
--remove_file $datadir/test/load_t0
|
||||
|
||||
|
||||
--echo # create_select for a temporary table didn't set up pos_in_locked_tables.
|
||||
create table t (a int unique) engine=innodb
|
||||
replace select 1 as a, 2 as b union select 1 as a, 3 as c;
|
||||
select * from t;
|
||||
drop table t;
|
||||
|
||||
create temporary table t (a int unique) engine=innodb
|
||||
replace select 1 as a, 2 as b union select 1 as a, 3 as c;
|
||||
select * from t;
|
||||
drop table t;
|
||||
|
||||
--source suite/versioning/common_finish.inc
|
||||
|
@ -4396,6 +4396,7 @@ TABLE *select_create::create_table_from_items(THD *thd,
|
||||
*/
|
||||
DBUG_ASSERT(0);
|
||||
}
|
||||
create_table->table->pos_in_table_list= create_table;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -8957,10 +8957,12 @@ ha_innobase::update_row(
|
||||
const bool vers_ins_row = vers_set_fields
|
||||
&& thd_sql_command(m_user_thd) != SQLCOM_ALTER_TABLE;
|
||||
|
||||
TABLE_LIST *tl= table->pos_in_table_list;
|
||||
uint8 op_map= tl->trg_event_map | tl->slave_fk_event_map;
|
||||
/* This is not a delete */
|
||||
m_prebuilt->upd_node->is_delete =
|
||||
(vers_set_fields && !vers_ins_row) ||
|
||||
(thd_sql_command(m_user_thd) == SQLCOM_DELETE &&
|
||||
(op_map & trg2bit(TRG_EVENT_DELETE) &&
|
||||
table->versioned(VERS_TIMESTAMP))
|
||||
? VERSIONED_DELETE
|
||||
: NO_DELETE;
|
||||
|
Reference in New Issue
Block a user