v42-topup-Create-conflict-log-table-after-inserting-subscr.patch.txt
text/plain
Filename: v42-topup-Create-conflict-log-table-after-inserting-subscr.patch.txt
Type: text/plain
Part: 0
From a8e1329bb58436b44d4f0daadc5240daebd39bae Mon Sep 17 00:00:00 2001
From: Dilip Kumar <dilipkumarb@google.com>
Date: Sat, 30 May 2026 05:33:21 +0530
Subject: [PATCH v42] Create conflict log table after inserting subscription
row
---
src/backend/commands/subscriptioncmds.c | 73 ++++++++++------------
src/backend/replication/logical/conflict.c | 17 +++++
2 files changed, 49 insertions(+), 41 deletions(-)
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 88f22bbb286..67311a65e29 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -651,7 +651,6 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
uint32 supported_opts;
SubOpts opts = {0};
AclResult aclresult;
- Oid logrelid = InvalidOid;
/*
* Parse and check options.
@@ -844,22 +843,45 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
values[Anum_pg_subscription_subconflictlogdest - 1] =
CStringGetTextDatum(ConflictLogDestNames[opts.conflictlogdest]);
+ values[Anum_pg_subscription_subconflictlogrelid - 1] =
+ ObjectIdGetDatum(InvalidOid);
+
+ tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
+
+ /* Insert tuple into catalog. */
+ CatalogTupleInsert(rel, tup);
+ //heap_freetuple(tup);
+
/*
* If logging to a table is required, physically create it now. We create
- * the conflict log table here so its relation OID can be stored when
- * inserting the pg_subscription tuple below.
+ * the conflict log table here. Also update the pg_subscription row
+ * after creating the conflict log table with its reloid.
*/
if (CONFLICTS_LOGGED_TO_TABLE(opts.conflictlogdest))
- logrelid = create_conflict_log_table(subid, stmt->subname, owner);
+ {
+ bool replaces[Natts_pg_subscription];
+ Oid logrelid =
+ create_conflict_log_table(subid, stmt->subname, owner);
- /* Store table OID in the catalog. */
- values[Anum_pg_subscription_subconflictlogrelid - 1] =
- ObjectIdGetDatum(logrelid);
+ /* Form a new tuple. */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));
- tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
+ values[Anum_pg_subscription_subconflictlogrelid - 1] =
+ ObjectIdGetDatum(logrelid);
+ replaces[Anum_pg_subscription_subconflictlogrelid - 1] =
+ true;
+
+ /* Make subscription tuple visible before updating it. */
+ CommandCounterIncrement();
+
+ tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
+ replaces);
+
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+ }
- /* Insert tuple into catalog. */
- CatalogTupleInsert(rel, tup);
heap_freetuple(tup);
recordDependencyOnOwner(SubscriptionRelationId, subid, owner);
@@ -876,25 +898,6 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
- /*
- * If conflicts are logs to table establish an internal dependency
- * between the conflict log table and the subscription.
- *
- * We use DEPENDENCY_INTERNAL to signify that the table's lifecycle is
- * strictly tied to the subscription, similar to how a TOAST table relates
- * to its main table or a sequence relates to an identity column.
- *
- * This ensures the conflict log table is automatically reaped during a
- * DROP SUBSCRIPTION via performDeletion().
- */
- if (CONFLICTS_LOGGED_TO_TABLE(opts.conflictlogdest))
- {
- ObjectAddress clt;
-
- ObjectAddressSet(clt, RelationRelationId, logrelid);
- recordDependencyOn(&clt, &myself, DEPENDENCY_INTERNAL);
- }
-
/*
* A replication origin is currently created for all subscriptions,
* including those that only contain sequences or are otherwise empty.
@@ -1507,20 +1510,8 @@ alter_sub_conflictlogdestination(Subscription *sub, ConflictLogDest logdest,
/* There was no previous conflict log table. */
if (want_table)
{
- ObjectAddress clt;
- ObjectAddress subobj;
-
relid = create_conflict_log_table(sub->oid, sub->name, sub->owner);
update_relid = true;
-
- /*
- * Establish an internal dependency between the conflict log table
- * and the subscription. For details refer comments in
- * CreateSubscription function.
- */
- ObjectAddressSet(clt, RelationRelationId, relid);
- ObjectAddressSet(subobj, SubscriptionRelationId, sub->oid);
- recordDependencyOn(&clt, &subobj, DEPENDENCY_INTERNAL);
}
}
diff --git a/src/backend/replication/logical/conflict.c b/src/backend/replication/logical/conflict.c
index 15b0ef7f3ca..0f077b28678 100644
--- a/src/backend/replication/logical/conflict.c
+++ b/src/backend/replication/logical/conflict.c
@@ -175,6 +175,8 @@ create_conflict_log_table(Oid subid, char *subname, Oid subowner)
{
TupleDesc tupdesc;
Oid relid;
+ ObjectAddress myself;
+ ObjectAddress subaddr;
char relname[NAMEDATALEN];
snprintf(relname, NAMEDATALEN, "pg_conflict_log_for_subid_%u", subid);
@@ -218,6 +220,21 @@ create_conflict_log_table(Oid subid, char *subname, Oid subowner)
NULL); /* typaddress */
Assert(OidIsValid(relid));
+ /*
+ * Establish an internal dependency between the conflict log table and
+ * the subscription.
+ *
+ * We use DEPENDENCY_INTERNAL to signify that the table's lifecycle is
+ * strictly tied to the subscription, similar to how a TOAST table relates
+ * to its main table or a sequence relates to an identity column.
+ *
+ * This ensures the conflict log table is automatically reaped during a
+ * DROP SUBSCRIPTION via performDeletion().
+ */
+ ObjectAddressSet(myself, RelationRelationId, relid);
+ ObjectAddressSet(subaddr, SubscriptionRelationId, subid);
+ recordDependencyOn(&myself, &subaddr, DEPENDENCY_INTERNAL);
+
/* Release tuple descriptor memory. */
FreeTupleDesc(tupdesc);
--
2.49.0