Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w7iQw-005ckx-02 for pgsql-hackers@arkaria.postgresql.org; Tue, 31 Mar 2026 23:23:42 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w7iQu-00Dj4S-1y for pgsql-hackers@arkaria.postgresql.org; Tue, 31 Mar 2026 23:23:41 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w7iQu-00Dj4J-0S for pgsql-hackers@lists.postgresql.org; Tue, 31 Mar 2026 23:23:40 +0000 Received: from mail-pl1-x634.google.com ([2607:f8b0:4864:20::634]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1w7iQs-000000022uA-2Iqn for pgsql-hackers@lists.postgresql.org; Tue, 31 Mar 2026 23:23:39 +0000 Received: by mail-pl1-x634.google.com with SMTP id d9443c01a7336-2adbfab4501so31194195ad.2 for ; Tue, 31 Mar 2026 16:23:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1774999417; cv=none; d=google.com; s=arc-20240605; b=PlcH8ZzhkuZrmdjhUad/2TUll2eP7a3wD6pdALzcorjXEUTEQVOwZ62S4e4iR8S6VW 53ybnWUC6WGOzNW+qCW2FpSPgU+HckWGcN7zHfThDYtIcCJ5WJ5MVzrOQLVPdlNhCGQT vc37nm+Lf0w/k5MqBggpbSfq8Vpi33yiCjIhVaSJykVPEAZDQeIOmua8tT8mF4yKZa3y /JzJ97KZBV7MOXiiIJQ2VpNyjSiLVgoTiNYwKNvxIcPxRGKnfFWEZ7pNBRQsZZEWbsIX 8DsEuS2YO+yQd2xM5U71/d5cWNWsYQ5rbq5qTQyHZYNuVEDrpTEiquRvUKctF5/4jIXg Angg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=Ek0CIbUd5ZW+qvgibBW2nbLZE98RGo0ZMM1GB8Qc12o=; fh=nIikgmEcMXW0ZqTbXQ7QSzJ5UYR4mP0xgbl1gZ83bbQ=; b=bcHjfcoZAEs43LW3iSZfKOURCjMA7maR9LH+p/IYNvJ+dUl5FdXL8D3FML99+iyjA7 EyPzS2veTq4UhOJhRzl/oPmKSw5CWuelEMOJDKN92SaEM3i4lTFyltzUqwWbFlRn9eLa 85ZaslrY+1WExeAcJsT/wDlUgPi+HLB3XH5ft9yMqbHsMkCc63cvfGuVAqOxSSbsuG62 BmKKT8phnwToaiW9AxRzQ+Pk/E4Mud6rnFzr1GlLvTJBSeLDfpHVvaMksVZe0RT8tIMw IjiwB0PS4GgmzZNJnhvPFIC3mlAWgMtLnrA8lK/Qfp6LgRTOsHhdGqJOZHQ2qAV4Bh+N tKUw==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774999417; x=1775604217; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=Ek0CIbUd5ZW+qvgibBW2nbLZE98RGo0ZMM1GB8Qc12o=; b=imCfcN68tWe4wNj7cVSgXmIfv6QknaYl88nnNr4Vu2YQCyvM30h/pcCQbeIr9FZVsj 60cvO/vzmsRzoqbptRceF9sfoecSi8vDlQhb6gdq29/WLwM/i7CiIrLhLnKatTiXhlbB VXnGBoNQdXkD7ZtinqjeqFhIvco/bn62GYR0Mh6G/SVQ2p18ccqNu/SwYDFuQ7Ao1Upl rIdq4GPS1DEus08pualmcajcwb3ejQD3srRSWuYSbCmhEC7413fb8qDfNwMxklYLmZW0 bYsU2hUB4Jyh7iJk+3uldkwog5wZ6cEAutiN0CLisj2MH5TeWFTJxF71iKekJ5CYxhOM /4mw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774999417; x=1775604217; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=Ek0CIbUd5ZW+qvgibBW2nbLZE98RGo0ZMM1GB8Qc12o=; b=TLKci4a3vKb6yv3SQLzlvVbXgcCBVeLmdemu2aIeMF2he/TEMTqoxhI0RWxtLro5qq J/Dqqz7xz6GjzvwswFDD7sFh8mqn5SMnUg/Q6HLB7ciHmm3QiEjs4GyJPb/I2vlrcVli mhBXD3Mf5EGnRe8pptxArS/QTwDZQpGo6MMCCbEUYeBF3wSnyGb2PHF0g+Hl4Z80xZwT WBYJzvHtAt1bRVfydfZC1z4aDzjCq8YZ/6ofq7h8WGmcxBn3t1qHnFLAOKhtCE59Cbyn 5pJgTnxBwiaFQTVtueMCXZxs4V9+9ukKGc120KKfYOEy6S9dWmL6IfXRg0XdCAxG9UCi Bw/g== X-Forwarded-Encrypted: i=1; AJvYcCWsp3EXeoU3S1WQIuc1EUVziMdoYdvY7SY744aPTm4zllW7uMB/hLXKDzQzU2CpZ+QAR7Qg3C1S5VdGbMIc@lists.postgresql.org X-Gm-Message-State: AOJu0YzLTZOK4Dd4pM8S8SBJyMxhvcioL2G3uNwBXIO+P6JNByTZGQw1 BJYAksmAHh5USh/ZGSiLTtCztmPdFpvQ4qmB7i7AIlZG/OkHNGc932TRHxwlkC3UaWoq7uUgozt J7H26CrTL1b8yRIkxVWB/jtyyh6jyfMBDlBiqmCk= X-Gm-Gg: ATEYQzyxGmrKeGL16WmpH+A2qSREvOBdsyKs55H+zmnZFErdDw+1dPKPmey6C+pAQod fU7wkGnWY6Kz+rBILkWkn4OTd4y9ScvWYuIV6fboPxBak61eN7Y8g9ZwIhFudSa+HZrKm93c3kR MK98ChpTVs4N3SQ7sh6gXY5nkDowaefkZhAYgIL/BdpqdBYxR9Zn0wFmP3Y6IvXIJwqt8ZJoeXl 7svEqq2kRvX0F3ycl+9Fw11P6DyoRV648ukgjp0sVvcgLbwgQXEa6f8sg/K52Vc68GoyG9U73zX G4ZJKBt7H/mj8r7mKIAT8yrMRdK7vLUPjst9ivjGUM33P99Z7AMARNefrE+4l8oU9Iayq7Q8jp3 c5ta8ug== X-Received: by 2002:a17:902:da8f:b0:2b2:67ca:5ff1 with SMTP id d9443c01a7336-2b269c9f871mr10367595ad.31.1774999417515; Tue, 31 Mar 2026 16:23:37 -0700 (PDT) MIME-Version: 1.0 References: <202603261226.uo54xj4rpex2@alvherre.pgsql> In-Reply-To: From: Roberto Mello Date: Tue, 31 Mar 2026 17:23:11 -0600 X-Gm-Features: AQROBzB6d8EpkroWq7I0uvlTfGir_CYwdAHHD9dgyKhhKKGDj3k2JxW3Y9Vkowc Message-ID: Subject: Re: pg_publication_tables: return NULL attnames when no column list is specified To: "David G. Johnston" Cc: =?UTF-8?Q?=C3=81lvaro_Herrera?= , PostgreSQL Developers Content-Type: multipart/alternative; boundary="000000000000c1fbfb064e5a416c" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000c1fbfb064e5a416c Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Tue, Mar 31, 2026 at 4:55=E2=80=AFPM David G. Johnston < david.g.johnston@gmail.com> wrote: > > IIUC the wording for v18 and earlier should read more like: > > =E2=80=9CSubscriptions having several publications in which the same tabl= e has > different sets of columns published are not supported.=E2=80=9D > > The claim that this defacto behavior is a bug needing to be fixed is now > before us (there is no disagreement that the physical column lists are > different - null vs non-null). My cursory take at this leads me to belie= ve > we should accept what actually got implemented and not call this a bug to > be fixed (aside from the docs). > > That the catalog is the only official source of truth regarding the > physical column list distinction, and the function represents the logical > =E2=80=9Cset of columns actually seen=E2=80=9D, makes sense seen in that = light. > The internal code was designed around the NULL/non-NULL distinction. The SRF pg_get_publication_tables() is the one place that erased it, and the CASE WHEN relnatts heuristic in tablesync was an attempt to reverse that erasure, but it's demonstrably broken for tables with dropped columns. That seems like a bug to me regardless of how we feel about the behavioral question, but I have no objections to not calling it a bug. I'm confident the best thing was intended when the code was committed and hindsight is always 20/20. I haven=E2=80=99t dived deep enough to understand whether there is C code i= ssue > that needs to be resolved. Or whether we can make dealing with this more > user-friendly given this constraint. > > Removing the limitation would seem more appealing if we are going to make > a change. The obvious answer of =E2=80=9Cunion all sets of columns publi= shed for a > table and replicate those=E2=80=9D would be the simplest to document thou= gh I > suspect the current implementation basically chooses one of the > publications to pull from which makes that difficult in the general case. > I do kinda wonder why we need to enforce any kind of error so long as one > of the publications for a given table includes all columns though. Or ev= en > is a proper superset to be a tiny bit more flexible. A technically > uninformed wondering but still. > The superset idea would be a significant change to how the WAL output plugin works. pgoutput.c doesn't have a concept of "this publication contributes columns X and that publication contributes columns Y, send the union." This would be an interesting improvement but it's a larger project... it would touch pgoutput, tablesync, and the subscriber's relation mapping. My patch is trying to fix the immediate inconsistency (the view lying about the catalog state, and the broken relnatts heuristic) without changing the replication protocol or column merging behavior. If the view shows {id, name} for both publications, a DBA planning a schema migration has no way to know that ALTER TABLE ADD COLUMN email will be replicated for one publication but not the other. The catalog stores the information needed to make this determination, the view actively hides it. NULL in the view would tell the DBA "this publication replicates everything, including future columns" which is actionable information. Roberto Mello Snowflake --000000000000c1fbfb064e5a416c Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
On Tue, Mar 31, 2026 at 4:55=E2=80=AFPM D= avid G. Johnston <david.g.= johnston@gmail.com> wrote:

IIUC the wording for v18 and earlier should read more like:

=E2=80=9CSubscriptions having several publications in = which the same table has different sets of columns published are not suppor= ted.=E2=80=9D

The claim that this = defacto behavior is a bug needing to be fixed is now before us (there is no= disagreement that the physical column lists are different - null vs non-nu= ll).=C2=A0 My cursory take at this leads me to believe we should accept wha= t actually got implemented and not call this a bug to be fixed (aside from = the docs).

That the catalog is t= he only official source of truth regarding the physical column list distinc= tion, and the function represents the logical =E2=80=9Cset of columns actua= lly seen=E2=80=9D, makes sense seen in that light.

The internal code was designed around the NULL/non-N= ULL distinction. The SRF=C2=A0
pg_get_publication_tables() is the one place that=C2=A0erased it,= and the CASE WHEN relnatts heuristic=C2=A0
in tablesync was an attempt to reverse that erasure,= but it's demonstrably broken for
tables with dropped columns. = That seems like a bug to me regardless of how we feel about the
b= ehavioral question, but I have no objections to not calling it a bug. I'= ;m confident the
best thing was intended when the code was commit= ted and hindsight is always 20/20.

I haven=E2=80=99t dived deep enough to unders= tand whether there is C code issue that needs to be resolved.=C2=A0 Or whet= her we can make dealing with this more user-friendly given this constraint.=

Removing the limitation would= seem more appealing if we are going to make a change.=C2=A0 The obvious an= swer of =E2=80=9Cunion all sets of columns published for a table and replic= ate those=E2=80=9D would be the simplest to document though I suspect the c= urrent implementation basically chooses one of the publications to pull fro= m which makes that difficult in the general case.=C2=A0 I do kinda wonder w= hy we need to enforce any kind of error so long as one of the publications = for a given table includes all columns though.=C2=A0 Or even is a proper su= perset to be a tiny bit more flexible.=C2=A0 A technically uninformed wonde= ring but still.

The sup= erset idea would be a significant change to how the WAL output plugin works= . pgoutput.c
doesn't have a concept of=C2=A0"this public= ation contributes columns X and that publication contributes
colu= mns Y, send the union."

This would be an inte= resting improvement but it's a larger project... it would touch pgoutpu= t, tablesync,
and the subscriber's relation mapping. My patch= is trying to fix the immediate inconsistency (the view
lying abo= ut the catalog state, and the broken relnatts heuristic) without changing t= he replication protocol
or column merging behavior.
If the view shows {id, name} for both publications, a DBA=C2=A0= planning a schema migration has no way to
know that ALTER TABLE A= DD COLUMN email will be replicated for one publication but not the
other. The catalog stores the information needed to make this determinati= on, the view actively hides it.
NULL in the view would tell the D= BA "this publication replicates everything, including future columns&q= uot;
which is actionable information.

Roberto Mello
Snowflake
--000000000000c1fbfb064e5a416c--