| From: | "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com> |
|---|---|
| To: | Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Matthias van de Meent <boekewurm+postgres(at)gmail(dot)com> |
| Cc: | Shinya Kato <shinya11(dot)kato(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
| Subject: | RE: Logical replication row filter loses unchanged toasted columns |
| Date: | 2026-08-14 16:39:46 |
| Message-ID: | TY4PR01MB177182B9392843AF53BAA53DF94DA2@TY4PR01MB17718.jpnprd01.prod.outlook.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
On Friday, August 14, 2026 8:50 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Thu, Aug 13, 2026 at 7:20 PM Matthias van de Meent
> <boekewurm+postgres(at)gmail(dot)com> wrote:
> >
> > On Wed, 12 Aug 2026 at 05:23, Shinya Kato <shinya11(dot)kato(at)gmail(dot)com>
> wrote:
> > >
> > > I see three ways to deal with this.
> > >
> > > Option A: detect the missing value in pgoutput_row_filter() and
> > > raise an error naming the table and the column, trading silent data
> > > loss for a loud failure. [...]
> > >
> > > Option B: when a table belongs to a publication with a row filter,
> > > make heap_update() log the whole old tuple, as it already does for
> > > REPLICA IDENTITY FULL. [...]
> > >
> > > Option C: document the restriction and leave the behavior alone.
> > > [...]
> >
> > Or, an option D: Forbid the creation (and use) of filtered publication
> > table definitions for tables which contain a non-identity
> > varlena-typed column (i.e. the type's typlen is -1).
> >
>
> I think even if we want to block operations that can create such a situation, we
> should reject only the specific updates that lead to the problem, not every
> update on a table that merely has the potential for it. We already do
> something similar: UPDATE/DELETE is rejected when there's no replica identity
> and the table's publications publish those operations. I'd like to apply the same
> principle here.
Yes, I was also concerned that disallowing all toastable columns would affect
too broad a range of cases. However, I agree that catching the issue earlier -
before replication happens, is better. So I also think we could try once to
catch this during DML, where we can narrow down the scope.
>
> With that in mind, I could think of following two options:
>
> Option 1
> Check at DML time, inside heap_update(): Detect the problem per-row, at the
> point where old/new tuple data is actually available when following conditions
> are met: the relation is published and has UPDATEs enabled, (b) some
> publication defines a row filter on it, (c) the replica identity key changed value
> in this UPDATE, (d) the old tuple has some externally-stored (TOASTed)
> attribute (HeapTupleHasExternal()), and (e) some specific non-replica-identity
> column's value is unchanged and still stored out-of-line.
> ...
>
> Option 2:
> Check at statement time, inside CheckCmdReplicaIdentity(): Reject upfront,
> before any row is touched, whenever: (a) the relation is published and has
> UPDATEs enabled, (b) some publication defines a row filter on it, (c) the
> relation has some toastable column outside the replica identity, and (d) the
> relation has a TOAST table (reltoastrelid is valid).
> ...
>
> I lean towards Option 1 (at least for master branch) for the reason above.
> Thoughts?
For Option 1, the advantage is that it lays the groundwork for a future
improvement: automatically logging the unchanged toast values when it's possible
to convert an UPDATE to an INSERT with a publication row filter. (That could be
an optional feature, I think.). The underlying logic, finding unchanged toast
columns and detecting row filters, would be needed anyway.
For reference, I've generated both patches for comparison and evaluation:
0001: heap_update check
0002: CheckCmdReplicaIdentity check
I haven't added doc yet, but I can add it once we reach consensus.
Best Regards,
Zhijie Hou
| Attachment | Content-Type | Size |
|---|---|---|
| v1-0001-Reject-UPDATEs-that-would-silently-lose-a-row-fil.patch | application/octet-stream | 15.6 KB |
| v1-0002-Reject-UPDATEs-that-would-silently-lose-a-row-fil.patch | application/octet-stream | 17.9 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Tristan Partin | 2026-08-14 17:11:03 | Re: Fix a host of strto*() bugs |
| Previous Message | Matheus Alcantara | 2026-08-14 16:39:05 | Re: Redundant qualifier elimination |