0001-fixup-publish_as_relid-20220311.patch
text/x-patch
Filename: 0001-fixup-publish_as_relid-20220311.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch 0001
Subject: fixup: publish_as_relid
| File | + | − |
|---|---|---|
| src/backend/replication/pgoutput/pgoutput.c | 30 | 2 |
From 0726a46f050980df2ebbca48078b4fd3b0d374f8 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Wed, 9 Mar 2022 18:10:56 +0100
Subject: [PATCH 1/3] fixup: publish_as_relid
Make sure to determine the top-most ancestor listed in any publication.
Otherwise we might end up with different values depending on the order
of publications (as listed in subscription).
---
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