From 5070a26fb54b956557f4ba3a44b796ab4c232c93 Mon Sep 17 00:00:00 2001 From: Tomas Vondra Date: Wed, 9 Mar 2022 18:10:56 +0100 Subject: [PATCH 1/2] fixup: publish_as_relid --- src/backend/replication/pgoutput/pgoutput.c | 32 +++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c index ea57a0477f0..dbac2690b7f 100644 --- a/src/backend/replication/pgoutput/pgoutput.c +++ b/src/backend/replication/pgoutput/pgoutput.c @@ -1815,11 +1815,17 @@ get_rel_sync_entry(PGOutputData *data, Relation relation) Publication *pub = lfirst(lc); bool publish = false; + /* + * Under what relid should we publish changes in this publication? + * We'll use the top-most relid across all publications. + */ + Oid pub_relid = relid; + if (pub->alltables) { publish = true; if (pub->pubviaroot && am_partition) - publish_as_relid = llast_oid(get_partition_ancestors(relid)); + pub_relid = llast_oid(get_partition_ancestors(relid)); } if (!publish) @@ -1844,7 +1850,7 @@ get_rel_sync_entry(PGOutputData *data, Relation relation) { ancestor_published = true; if (pub->pubviaroot) - publish_as_relid = ancestor; + pub_relid = ancestor; } } @@ -1862,12 +1868,34 @@ get_rel_sync_entry(PGOutputData *data, Relation relation) if (publish && (relkind != RELKIND_PARTITIONED_TABLE || pub->pubviaroot)) { + List *ancestors; + entry->pubactions.pubinsert |= pub->pubactions.pubinsert; entry->pubactions.pubupdate |= pub->pubactions.pubupdate; entry->pubactions.pubdelete |= pub->pubactions.pubdelete; entry->pubactions.pubtruncate |= pub->pubactions.pubtruncate; rel_publications = lappend(rel_publications, pub); + + /* + * We want to publish the changes as the top-most ancestor + * across all publications. So we fetch all ancestors of the + * relid calculated for this publication, and check if the + * already calculated value is in the list. If yes, we can + * ignore the new value (as it's a child). Otherwise the new + * value is an ancestor, so we keep it. + */ + ancestors = get_partition_ancestors(pub_relid); + + /* + * The new pub_relid is a child of the current publish_as_relid + * value, so we can ignore it. + */ + if (list_member_oid(ancestors, publish_as_relid)) + continue; + + /* The new value is an ancestor, so let's keep it. */ + publish_as_relid = pub_relid; } } -- 2.34.1