Skip to content

Commit 0d9f516

Browse files
author
Commitfest Bot
committed
[CF 5774] v5 - Extend skipping FK checks on replicas to include ADD FK and TRUNCATE
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org/patch/5774 The branch will be overwritten each time a new patch version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. Patch(es): https://www.postgresql.org/message-id/CAMT0RQS8ifBjeUyA9=an+=NahwtjUiH=HLq4fHc28-3kBZpHoQ@mail.gmail.com Author(s): Hannu Krosing
2 parents 8982935 + 49e673d commit 0d9f516

3 files changed

Lines changed: 96 additions & 3 deletions

File tree

‎src/backend/commands/tablecmds.c‎

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,13 +2076,19 @@ ExecuteTruncateGuts(List *explicit_rels,
20762076
* Check foreign key references. In CASCADE mode, this should be
20772077
* unnecessary since we just pulled in all the references; but as a
20782078
* cross-check, do it anyway if in an Assert-enabled build.
2079+
*
2080+
* Skip foreign key checks when `session_replication_role = replica` to
2081+
* match the behaviour of disabling FK triggers in the same situation
20792082
*/
2083+
if (SessionReplicationRole != SESSION_REPLICATION_ROLE_REPLICA)
2084+
{
20802085
#ifdef USE_ASSERT_CHECKING
2081-
heap_truncate_check_FKs(rels, false);
2082-
#else
2083-
if (behavior == DROP_RESTRICT)
20842086
heap_truncate_check_FKs(rels, false);
2087+
#else
2088+
if (behavior == DROP_RESTRICT)
2089+
heap_truncate_check_FKs(rels, false);
20852090
#endif
2091+
}
20862092

20872093
/*
20882094
* If we are asked to restart sequences, find all the sequences, lock them
@@ -6114,7 +6120,12 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode,
61146120
* theoretically possible that we have changed both relations of the
61156121
* foreign key, and we'd better have finished both rewrites before we try
61166122
* to read the tables.
6123+
*
6124+
* Skip the check when `session_replication_mode = replica` to save time
6125+
* and to match the FK trigger behaviour in the same situation
61176126
*/
6127+
if (SessionReplicationRole != SESSION_REPLICATION_ROLE_REPLICA)
6128+
{
61186129
foreach(ltab, *wqueue)
61196130
{
61206131
AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab);
@@ -6159,6 +6170,7 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode,
61596170
if (rel)
61606171
table_close(rel, NoLock);
61616172
}
6173+
}
61626174

61636175
/* Finally, run any afterStmts that were queued up */
61646176
foreach(ltab, *wqueue)

‎src/test/regress/expected/foreign_key.out‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3623,6 +3623,41 @@ ALTER TABLE fk_r DROP CONSTRAINT fk_r_p_id_p_jd_fkey_1;
36233623
ERROR: cannot drop inherited constraint "fk_r_p_id_p_jd_fkey_1" of relation "fk_r"
36243624
ALTER TABLE fk_r_2 DROP CONSTRAINT fk_r_p_id_p_jd_fkey;
36253625
ERROR: cannot drop inherited constraint "fk_r_p_id_p_jd_fkey" of relation "fk_r_2"
3626+
-- tests for SET session_replication_role = replica;
3627+
RESET session_replication_role;
3628+
-- disabling FK checks
3629+
CREATE TABLE pkt(id int PRIMARY KEY);
3630+
CREATE TABLE fkt(fk int REFERENCES pkt(id));
3631+
INSERT INTO fkt VALUES(1); -- should fail
3632+
ERROR: insert or update on table "fkt" violates foreign key constraint "fkt_fk_fkey"
3633+
DETAIL: Key (fk)=(1) is not present in table "pkt".
3634+
SET session_replication_role=replica;
3635+
INSERT INTO fkt VALUES(1); -- should succeed now
3636+
DROP TABLE fkt, pkt;
3637+
RESET session_replication_role;
3638+
-- skipping FK validation during ALTER TABLE ... ADD FOREIGN KEY
3639+
CREATE TABLE pkt(id int PRIMARY KEY);
3640+
CREATE TABLE fkt(fk int);
3641+
INSERT INTO fkt VALUES(1);
3642+
ALTER TABLE fkt ADD FOREIGN KEY (fk) REFERENCES pkt(id); -- should fail
3643+
ERROR: insert or update on table "fkt" violates foreign key constraint "fkt_fk_fkey"
3644+
DETAIL: Key (fk)=(1) is not present in table "pkt".
3645+
SET session_replication_role=replica;
3646+
ALTER TABLE fkt ADD FOREIGN KEY (fk) REFERENCES pkt(id); -- should succeed now
3647+
DROP TABLE fkt, pkt;
3648+
RESET session_replication_role;
3649+
-- skipping FK existence checks during TRUNCATE
3650+
CREATE TABLE pkt(id int PRIMARY KEY);
3651+
CREATE TABLE fkt(fk int REFERENCES pkt(id));
3652+
TRUNCATE pkt; -- should fail
3653+
ERROR: cannot truncate a table referenced in a foreign key constraint
3654+
DETAIL: Table "fkt" references "pkt".
3655+
HINT: Truncate table "fkt" at the same time, or use TRUNCATE ... CASCADE.
3656+
SET session_replication_role=replica;
3657+
TRUNCATE pkt; -- should succeed now
3658+
DROP TABLE fkt, pkt;
3659+
RESET session_replication_role;
3660+
-- end of tests for SET session_replication_role = replica;
36263661
SET client_min_messages TO warning;
36273662
DROP SCHEMA fkpart12 CASCADE;
36283663
RESET client_min_messages;

‎src/test/regress/sql/foreign_key.sql‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2597,6 +2597,52 @@ ALTER TABLE fk_r_1 DROP CONSTRAINT fk_r_p_id_p_jd_fkey;
25972597
ALTER TABLE fk_r DROP CONSTRAINT fk_r_p_id_p_jd_fkey_1;
25982598
ALTER TABLE fk_r_2 DROP CONSTRAINT fk_r_p_id_p_jd_fkey;
25992599

2600+
-- tests for SET session_replication_role = replica;
2601+
2602+
RESET session_replication_role;
2603+
2604+
-- disabling FK checks
2605+
2606+
CREATE TABLE pkt(id int PRIMARY KEY);
2607+
CREATE TABLE fkt(fk int REFERENCES pkt(id));
2608+
2609+
INSERT INTO fkt VALUES(1); -- should fail
2610+
2611+
SET session_replication_role=replica;
2612+
INSERT INTO fkt VALUES(1); -- should succeed now
2613+
2614+
DROP TABLE fkt, pkt;
2615+
RESET session_replication_role;
2616+
2617+
-- skipping FK validation during ALTER TABLE ... ADD FOREIGN KEY
2618+
2619+
CREATE TABLE pkt(id int PRIMARY KEY);
2620+
CREATE TABLE fkt(fk int);
2621+
INSERT INTO fkt VALUES(1);
2622+
2623+
ALTER TABLE fkt ADD FOREIGN KEY (fk) REFERENCES pkt(id); -- should fail
2624+
2625+
SET session_replication_role=replica;
2626+
ALTER TABLE fkt ADD FOREIGN KEY (fk) REFERENCES pkt(id); -- should succeed now
2627+
2628+
DROP TABLE fkt, pkt;
2629+
RESET session_replication_role;
2630+
2631+
-- skipping FK existence checks during TRUNCATE
2632+
2633+
CREATE TABLE pkt(id int PRIMARY KEY);
2634+
CREATE TABLE fkt(fk int REFERENCES pkt(id));
2635+
2636+
TRUNCATE pkt; -- should fail
2637+
2638+
SET session_replication_role=replica;
2639+
TRUNCATE pkt; -- should succeed now
2640+
2641+
DROP TABLE fkt, pkt;
2642+
RESET session_replication_role;
2643+
2644+
-- end of tests for SET session_replication_role = replica;
2645+
26002646
SET client_min_messages TO warning;
26012647
DROP SCHEMA fkpart12 CASCADE;
26022648
RESET client_min_messages;

0 commit comments

Comments
 (0)