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 1w7HPu-0058t1-1f for pgsql-hackers@arkaria.postgresql.org; Mon, 30 Mar 2026 18:32:50 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w7HPr-005Wp7-2D for pgsql-hackers@arkaria.postgresql.org; Mon, 30 Mar 2026 18:32:48 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w7HPr-005Woz-19 for pgsql-hackers@lists.postgresql.org; Mon, 30 Mar 2026 18:32:47 +0000 Received: from mail-pl1-x62c.google.com ([2607:f8b0:4864:20::62c]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1w7HPp-000000022bt-0JZz for pgsql-hackers@lists.postgresql.org; Mon, 30 Mar 2026 18:32:47 +0000 Received: by mail-pl1-x62c.google.com with SMTP id d9443c01a7336-2b258576d8cso6809875ad.0 for ; Mon, 30 Mar 2026 11:32:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1774895564; cv=none; d=google.com; s=arc-20240605; b=RRoaslXHiqbK2q4ik4QW8NUEFNpgUw6A183RHLp1bx6l3H7BK6mdyxLkW2kVlEGGRV sIpw2DA4uzNNodsDKR02KmJZLKyaEt9cG/+8Xw9HqJwLIkM81cCnxht3/piM6cpiNYLM 6z0+tdQKdRtf51uaJK+TeKzOjECSGI98Fra4YI5v+kWWzaahoVd6XkfKq3XDErp82bIM bhiVCak8q7aclwk0eHrw6cIfy5fyEx6hAOirXIAnCvbWnpABGJxvirdyqn1TB9eC0G79 +IlaxEyiKpgTqWq2hPkXXkj4mU8H+vYHEVHsKa7Ya+xHVeu7NNApDWr5+Fv5YhzNNlk5 kPzg== 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=soamp7fxjTHuGkPc2GrGaL0pRcdpE223Yhs3O3LJ8WU=; fh=/k/uS/3EGigow8/nOxOmNqgJix1B5pRaNgIVDPRBhM4=; b=Syv3LKAibNSW58p3pyUVmh5v85wJmfBiIhLlLi+5/HjtSpLgu0lskBC3/gkq8qiLIR W/sx1RS52fd4LGbZLtQ0SzpY1VhKf0Y6Ho07hIjgCX67tRcYBhh68Hdza2deLNOPKBIz kGYKjvCE1FH3sOmpUJE02T1qecS9+Xqa01B95FG8Fv6xN8EVp1dQzgoGtcn3GqGaxK7w Ff99ia/vHqLqOlBpFcBHnG7MaKyiFqMEJSemqluIYge4S2CHk8dApjUSb35ndAk7+Fz3 c4IUiUjEcuyXVA0fuK2x3tXu5U7K31ecwJ8bjWjORkdTs2wGOzgsYXV5Sttet1wUY5WD perw==; 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=1774895564; x=1775500364; 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=soamp7fxjTHuGkPc2GrGaL0pRcdpE223Yhs3O3LJ8WU=; b=JQnOI/bB6cidMpxFDSLnSarsPmIh7GRU9UmETWUuh17lwwwX2QfSWjOS+td7Am4eCZ IZU4Kc578wlLendnoMxuD0pMoE6EtfEE/w6XZhg6Qcj/FHpE/k6/f4x8HhNKvQgNQnje yg30SkKz3Kmoo7DnGfh3GNRDSp6kL3JP2fFRFC28dpIW+3ZIwNQgCwbXipkZXA7nwuIp /u/8qM/YgzvvmdMGxNutD/oY5fZl3vzus5d1pWg74Bzhn3F6P4Symf7H70X5BzjHMlBb H7nNSlNYbXfl9R3DLjqcdHy6oEmHREW73ueKUC/2o0SwNM60LMaaRZ99LeKC1D4pGsDU iYyg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774895564; x=1775500364; 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=soamp7fxjTHuGkPc2GrGaL0pRcdpE223Yhs3O3LJ8WU=; b=gZXv3knLOgemh2fJ202yQsMgDBU2R0RQaxJLc84MSADbjjDNuudEP4hAYmk2GsURJW 56ZwCe0qW7c2qw7qhATeeANE1CzhITs7WW8NnKoHTm8vu3fftiPkByqkdmw89AAWAoTs VNl7v79VtE5NVPigqzn721pYosKF0GapUTD3sX8zYKXMiDjsuwa8apprQdTF6/A4DExl a9qeiFGPb52uLWhxbJVyaRWiUcwFeJ2xUYTY52oPx2NWqBtiIi4QcQv6OafV5svfawJx DUl83uJg6QdIjqU4Ys5UujiV55MdEh6Ek8NvEYgfXjrrubh6xEFr+UakqwEZ5zQZ0J/K 1hBQ== X-Gm-Message-State: AOJu0Yx/6erLCIStzPhlqaJOjlEjxI7vXJYcvPUEq8fRNYAUXtOKC6g4 0slPeyjMvXi7v3MXxOPcdDAs9RqSLOy6YS6CZ90bFvNfDewCEF9WhEsoTRdxjqSVI8Jh5tZwseJ D5NY9z6NqcGlt5vDOko057ZtXFMBSrQo= X-Gm-Gg: ATEYQzzwMhtsGCehfG8VZnWgJLpVtbZGt7RJYGlRJCn63oJE+JH6z+hlnxlW8q3ekpo 5uhfiWnV0899cGpfhJ1RiPuYnWalkDLxKQfspuU2zNYg3deHyadP5JnaUHhLt46CVCBxBHJ8T/S l0zPzmSM4XhstFqthsH+UF1kYIEd3yQpRzlxgjfhjy2P8FnC+IzmkDTpKFdwMwxYIN0TM+DOFjP cprZIlb9/wMfxelKcxkHQgk+Iftss/v4RGAwuIOCcn6M9uYcApV087roXYfK/WsglOhIfTfmCv7 4titxhtdyUTBGzBPzcAJ3EQ/rfeHwTRuorV8uLZ2rtatQlz4oPJdQ/ekLT2F+m9sXxK9xn8= X-Received: by 2002:a17:902:e5cc:b0:2b0:b290:f2f4 with SMTP id d9443c01a7336-2b0cdd40053mr144776185ad.32.1774895563563; Mon, 30 Mar 2026 11:32:43 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Roberto Mello Date: Mon, 30 Mar 2026 12:32:17 -0600 X-Gm-Features: AQROBzAHT8AVB6ycuIKNGMtg4X7ochm5PvnZR4XyRbDtVpT9MKGoVS5cYRZByKQ Message-ID: Subject: Re: pg_publication_tables: return NULL attnames when no column list is specified To: Amit Kapila Cc: PostgreSQL Developers Content-Type: multipart/alternative; boundary="000000000000946d0b064e4213e9" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000946d0b064e4213e9 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Mon, Mar 30, 2026 at 1:21=E2=80=AFAM Amit Kapila wrote: > On Thu, Mar 26, 2026 at 1:21=E2=80=AFAM Roberto Mello > wrote: > > > By making them indistinguishable, the synthesis hid a real conflict fro= m > users > > who had a table in two publications with different column semantics on > the > > same subscription. I am proposing a fix that restores the distinction > and correctly > > (IMO) surfaces this conflict. > > > > I would like to understand why shall we consider this as a conflict? > IIRC, we tried to ensure that if in future new columns get added to > the relation and the same is not updated in the explicit column list > then it will result in error. > Hi Amit, The conflict exists because the two publications have different contracts about future schema changes, and the subscriber has no way to honor both simultaneously. For example: CREATE TABLE t (id int, name text); CREATE PUBLICATION pub_a FOR TABLE t; -- no column list CREATE PUBLICATION pub_b FOR TABLE t (id, name); -- explicit list CREATE SUBSCRIPTION sub CONNECTION '...' PUBLICATION pub_a, pub_b; At this point both publications replicate the same columns. But after: ALTER TABLE t ADD COLUMN email text; pub_a now replicates {id, name, email} (automatically, because no column list means all current and future columns), while pub_b still replicates {id, name} (the explicit list hasn't been altered). The subscriber receives WAL from both publications for the same table. Which column set should it apply? It cannot apply both as they disagree on whether email is included. This is exactly the situation the "cannot use different column lists" check was designed to prevent. The current code suppresses this error by making the two cases look identical at query time. But the underlying catalog still stored NULL for pub_a and {1,2} for pub_b, and the actual replication behavior at WAL decode time (in pgoutput.c) still treated them differently. So the conflict was real but hidden from the check that was supposed to detect it. To put it another way: the check's purpose is to ensure a single consistent column set for each table across all publications on a subscription. Two publications that will diverge on the next ALTER TABLE ADD COLUMN do not provide that guarantee. Surfacing the conflict at subscription creation / refresh time - before the schema change happens - is better than discovering it after, when the subscriber receives incompatible column sets and replication breaks. For users who currently have this configuration, the fix is straightforward= : either drop the explicit column list from pub_b (so both mean "all columns"), or keep the explicit list and use a separate subscription. Roberto Mello Snowflake --000000000000946d0b064e4213e9 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
On Mon, Mar 30, 2026 at 1:21=E2=80=AFAM A= mit Kapila <amit.kapila16@gma= il.com> wrote:
On Thu, Mar 26, 2026 at = 1:21=E2=80=AFAM Roberto Mello <roberto.mello@gmail.com> wrote:

> By making them indistinguishable, the synthesis hid a real conflict fr= om users
> who had a table in two publications with different column semantics on= the
> same subscription. I am proposing a fix that restores the distinction = and correctly
> (IMO) surfaces this conflict.
>

I would like to understand why shall we consider this as a conflict?
IIRC, we tried to ensure that if in future new columns get added to
the relation and the same is not updated in the explicit column list
then it will result in error.

Hi Amit,<= /div>

The conflict exists because the two publications have d= ifferent contracts about future
schema changes, and the subscriber has no way to honor both simu= ltaneously.

For example:

=C2=A0 =C2=A0 CREATE TABLE t (id int= , name text);
=C2=A0 =C2=A0 CREATE PUBLICATION pub_a FOR TABLE t;=C2=A0 = =C2=A0-- no column list
=C2=A0 =C2=A0 CREATE PUBLICATION pub_b FOR TABLE= t (id, name); -- explicit list
=C2=A0 =C2=A0 CREATE SUBSCRIPTION sub CO= NNECTION '...' PUBLICATION pub_a, pub_b;

At this point both = publications replicate the same columns. But after:

=C2=A0 =C2=A0 AL= TER TABLE t ADD COLUMN email text;

pub_a now replicates {id, name, e= mail} (automatically, because no column list
means all current and future columns), while pub_b = still replicates {id, name}
(the explicit list hasn't been altered).

The subscriber r= eceives WAL from both publications for the same table.
Which column set should it apply? It cann= ot apply both as they disagree on
whether email is included. This is exactly the situation the &= quot;cannot use
diffe= rent column lists" check was designed to prevent.

The current code suppresses this = error by making the two cases look
identical at query time. But the underlying catalog still sto= red NULL
for pub_a and {1,2} for pub_b, and the actual replication behav= ior at WAL
decode tim= e (in pgoutput.c) still treated them differently. So the conflict was real<= /div>
but hidden from the c= heck that was supposed to detect it.

To put it another way: the chec= k's purpose is to ensure a single consistent
column set for each table across all publicatio= ns on a subscription. Two
publications that will diverge on the next ALTER TABLE ADD COLUMN
do not provide that guara= ntee. Surfacing the conflict at subscription
creation / refresh time - before the schema change = happens - is better than
discovering it after, when the subscriber receives incompatible column = sets
and replication = breaks.

For users who currently have this configuration, the fix is = straightforward:
eith= er drop the explicit column list from pub_b (so both mean "all columns= "),
or keep the = explicit list and use a separate subscription.

Roberto Mello
Snowflake
--000000000000946d0b064e4213e9--