On Fri, 24 Jul 2020 at 05:16, Ajin Cherian <itsa...@gmail.com> wrote:
> The patch no longer applies, because of additions in the test source. > Otherwise, I have tested the patch and confirmed that updates and deletes > on tables with deferred primary keys work with logical replication. > > The new status of this patch is: Waiting on Author > Thanks for testing. I attached a rebased patch. -- Euler Taveira http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From c1ad1581962a56c83183bec1501df6f54406db89 Mon Sep 17 00:00:00 2001 From: Euler Taveira <euler.tave...@2ndquadrant.com> Date: Sun, 19 Apr 2020 20:04:39 -0300 Subject: [PATCH] Table with deferred PK is not updatable in logical replication In logical replication, an UPDATE or DELETE cannot be executed if a table has a primary key that is marked as deferred. RelationGetIndexList does not fill rd_replidindex accordingly. The consequence is that UPDATE or DELETE cannot be executed in a deferred PK table. Deferrable primary key cannot prevent a primary key to be used as replica identity. --- src/backend/utils/cache/relcache.c | 7 +++---- src/test/subscription/t/001_rep_changes.pl | 21 +++++++++++++++++++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index a2453cf1f4..8996279f3b 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4556,12 +4556,11 @@ RelationGetIndexList(Relation relation) result = lappend_oid(result, index->indexrelid); /* - * Invalid, non-unique, non-immediate or predicate indexes aren't - * interesting for either oid indexes or replication identity indexes, - * so don't check them. + * Invalid, non-unique or predicate indexes aren't interesting for + * either oid indexes or replication identity indexes, so don't check + * them. */ if (!index->indisvalid || !index->indisunique || - !index->indimmediate || !heap_attisnull(htup, Anum_pg_index_indpred, NULL)) continue; diff --git a/src/test/subscription/t/001_rep_changes.pl b/src/test/subscription/t/001_rep_changes.pl index 3f8318fc7c..f164d23a94 100644 --- a/src/test/subscription/t/001_rep_changes.pl +++ b/src/test/subscription/t/001_rep_changes.pl @@ -3,7 +3,7 @@ use strict; use warnings; use PostgresNode; use TestLib; -use Test::More tests => 23; +use Test::More tests => 24; # Initialize publisher node my $node_publisher = get_new_node('publisher'); @@ -38,6 +38,8 @@ $node_publisher->safe_psql('postgres', "CREATE TABLE tab_full_pk (a int primary key, b text)"); $node_publisher->safe_psql('postgres', "ALTER TABLE tab_full_pk REPLICA IDENTITY FULL"); +$node_publisher->safe_psql('postgres', + "CREATE TABLE tab_deferred_pk (a int PRIMARY KEY DEFERRABLE)"); # Let this table with REPLICA IDENTITY NOTHING, allowing only INSERT changes. $node_publisher->safe_psql('postgres', "CREATE TABLE tab_nothing (a int)"); $node_publisher->safe_psql('postgres', @@ -66,13 +68,17 @@ $node_subscriber->safe_psql('postgres', "CREATE TABLE tab_include (a int, b text, CONSTRAINT covering PRIMARY KEY(a) INCLUDE(b))" ); +# replication of the table with deferrable primary key +$node_subscriber->safe_psql('postgres', + "CREATE TABLE tab_deferred_pk (a int PRIMARY KEY DEFERRABLE)"); + # Setup logical replication my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres'; $node_publisher->safe_psql('postgres', "CREATE PUBLICATION tap_pub"); $node_publisher->safe_psql('postgres', "CREATE PUBLICATION tap_pub_ins_only WITH (publish = insert)"); $node_publisher->safe_psql('postgres', - "ALTER PUBLICATION tap_pub ADD TABLE tab_rep, tab_full, tab_full2, tab_mixed, tab_include, tab_nothing, tab_full_pk" + "ALTER PUBLICATION tap_pub ADD TABLE tab_rep, tab_full, tab_full2, tab_mixed, tab_include, tab_nothing, tab_full_pk, tab_deferred_pk" ); $node_publisher->safe_psql('postgres', "ALTER PUBLICATION tap_pub_ins_only ADD TABLE tab_ins"); @@ -122,6 +128,13 @@ $node_publisher->safe_psql('postgres', "DELETE FROM tab_include WHERE a > 20"); $node_publisher->safe_psql('postgres', "UPDATE tab_include SET a = -a"); +$node_publisher->safe_psql('postgres', + "INSERT INTO tab_deferred_pk VALUES (1),(2),(3)"); +$node_publisher->safe_psql('postgres', + "UPDATE tab_deferred_pk SET a = 11 WHERE a = 1"); +$node_publisher->safe_psql('postgres', + "DELETE FROM tab_deferred_pk WHERE a = 2"); + $node_publisher->wait_for_catchup('tap_sub'); $result = $node_subscriber->safe_psql('postgres', @@ -145,6 +158,10 @@ $result = $node_subscriber->safe_psql('postgres', is($result, qq(20|-20|-1), 'check replicated changes with primary key index with included columns'); +$result = $node_subscriber->safe_psql('postgres', + "SELECT count(*), min(a), max(a) FROM tab_deferred_pk"); +is($result, qq(2|3|11), 'check replicated changes with deferred primary key'); + # insert some duplicate rows $node_publisher->safe_psql('postgres', "INSERT INTO tab_full SELECT generate_series(1,10)"); -- 2.20.1