Re: Proposal: Conflict log history table for Logical Replication

From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, shveta malik <shvetamalik(at)gmail(dot)com>
Subject: Re: Proposal: Conflict log history table for Logical Replication
Date: 2026-06-08 11:35:33
Message-ID: CALDaNm2V3EuSKMaTqDvaiLQW3jwBX90aXTkMST1ft=uJ8J+R5A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Thu, 4 Jun 2026 at 11:59, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Some review comments for patch v45-0003.
>
> 3.
> + relid = get_relname_relid(relname, PG_CONFLICT_NAMESPACE);
> + if (OidIsValid(relid))
> + {
> + /* Existing table from upgrade */
> + Assert(IsBinaryUpgrade);
> + }
> + else
>
> Should this be the other way around?
>
> if (IsBinaryUpgrade)
> {
> relid = get_relname_relid(relname, PG_CONFLICT_NAMESPACE);
> Assert(OidIsValid(relid));
> }

This is done intentionally so that the Assert fails if the table
exists in case of non binary upgrade mode.

> 6.
> + if (fout->remoteVersion >= 190000)
> + appendPQExpBufferStr(query,
> + " s.subconflictlogrelid, s.subconflictlogdest\n");
> else
> - appendPQExpBufferStr(query, " NULL AS subservername\n");
> + appendPQExpBufferStr(query,
> + " NULL AS subconflictlogrelid, NULL AS subconflictlogdest\n");
>
> It seems more natural to think of the 'subconflictlogdest' before the
> subconflictlogrelid. Perhaps the SQL should swap those around.

I think the existing is better as it does select in the same order as
it is maintained in the table.

> ~~~
>
> 7.
> + if (PQgetisnull(res, i, i_subconflictlogrelid))
> + subinfo[i].subconflictlogrelid = InvalidOid;
> + else
> + {
> + TableInfo *tableInfo;
> +
> + subinfo[i].subconflictlogrelid =
> + atooid(PQgetvalue(res, i, i_subconflictlogrelid));
> +
> + if (subinfo[i].subconflictlogrelid)
> + {
> + tableInfo = findTableByOid(subinfo[i].subconflictlogrelid);
> + if (!tableInfo)
> + pg_fatal("could not find conflict log table with OID %u",
> + subinfo[i].subconflictlogrelid);
> +
> + addObjectDependency(&subinfo[i].dobj, tableInfo->dobj.dumpId);
> + }
> + }
> +
> + if (PQgetisnull(res, i, i_sublogdestination))
> + subinfo[i].subconflictlogdest = NULL;
> + else
> + subinfo[i].subconflictlogdest =
> + pg_strdup(PQgetvalue(res, i, i_sublogdestination));
> +
>
> 7a.
> Those new attributes come as a pair -- e.g. the relid only makes sense
> depending on the destination value; maybe only look for the CLT relid
> is the destination is not LOG/NULL

I think the existing is better as it does select in the same order as
it is maintained in the table.

> Knowing the destination also means you can also do integrity checks
> for PQgetisnull(res, i, i_subconflictlogrelid) -- e.g. must be valid
> Oid, or must be invalid Oid.

I'm not sure if it is pg_dump's responsibility to do these integrity
checks in this case.

> ~~~
>
> dumpSubscription:
>
> 8.
> + if (subinfo->subconflictlogdest &&
> + (pg_strcasecmp(subinfo->subconflictlogdest, "log") != 0))
> + appendPQExpBuffer(query,
> + "\n\nALTER SUBSCRIPTION %s SET (conflict_log_destination = %s);\n",
> + qsubname,
> + subinfo->subconflictlogdest);
> +

> 8b.
> Not sure why this has a double \n\n prefix instead of just \n. I
> didn't see that pattern elsewhere in this file.

Generally there is 2 line gaps between the create and alter
subscription, it was done to maintain the same line gaps like below:
CREATE SUBSCRIPTION sub3 CONNECTION 'dbname=doesnotexist' PUBLICATION
pub1 WITH (connect = false, slot_name = 'sub3', streaming = on);

ALTER SUBSCRIPTION sub3 SET (conflict_log_destination = table);

ALTER SUBSCRIPTION sub3 OWNER TO vignesh;

The rest of the comments were fixed. The attached v47 version patch
has the changes for the same.

Regards,
Vignesh

Attachment Content-Type Size
v47-0001-Add-configurable-conflict-log-table-for-Logical.patch application/octet-stream 69.1 KB
v47-0002-Implement-the-conflict-insertion-infrastructure-.patch application/octet-stream 34.8 KB
v47-0003-Preserve-conflict-log-destination-and-subscripti.patch application/octet-stream 23.6 KB
v47-0005-Documentation-patch.patch application/octet-stream 42.3 KB
v47-0004-Add-conflict-log-table-information-to-describe-s.patch application/octet-stream 78.2 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message vignesh C 2026-06-08 11:39:15 Re: Proposal: Conflict log history table for Logical Replication
Previous Message solai v 2026-06-08 11:34:56 Re: Logging parallel worker draught