Re: Skipping schema changes in publication

Lists: pgsql-hackers
From: vignesh C <vignesh21(at)gmail(dot)com>
To: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Skipping schema changes in publication
Date: 2022-03-22 07:08:43
Message-ID: CALDaNm3=JrucjhiiwsYQw5-PGtBHFONa6F7hhWCXMsGvh=tamA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi,

This feature adds an option to skip changes of all tables in specified
schema while creating publication.
This feature is helpful for use cases where the user wants to
subscribe to all the changes except for the changes present in a few
schemas.
Ex:
CREATE PUBLICATION pub1 FOR ALL TABLES SKIP ALL TABLES IN SCHEMA s1,s2;
OR
ALTER PUBLICATION pub1 ADD SKIP ALL TABLES IN SCHEMA s1,s2;

A new column pnskip is added to table "pg_publication_namespace", to
maintain the schemas that the user wants to skip publishing through
the publication. Modified the output plugin (pgoutput) to skip
publishing the changes if the relation is part of skip schema
publication.
As a continuation to this, I will work on implementing skipping tables
from all tables in schema and skipping tables from all tables
publication.

Attached patch has the implementation for this.
This feature is for the pg16 version.
Thoughts?

Regards,
Vignesh

Attachment Content-Type Size
v1-0001-Skip-publishing-the-tables-of-schema.patch text/x-patch 71.3 KB

From: vignesh C <vignesh21(at)gmail(dot)com>
To: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-03-26 14:07:26
Message-ID: CALDaNm1G0=0J2O+6pMStKuWUjxJJT5vbO-5jiUqzYVZM_sJ2+w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 22, 2022 at 12:38 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> Hi,
>
> This feature adds an option to skip changes of all tables in specified
> schema while creating publication.
> This feature is helpful for use cases where the user wants to
> subscribe to all the changes except for the changes present in a few
> schemas.
> Ex:
> CREATE PUBLICATION pub1 FOR ALL TABLES SKIP ALL TABLES IN SCHEMA s1,s2;
> OR
> ALTER PUBLICATION pub1 ADD SKIP ALL TABLES IN SCHEMA s1,s2;
>
> A new column pnskip is added to table "pg_publication_namespace", to
> maintain the schemas that the user wants to skip publishing through
> the publication. Modified the output plugin (pgoutput) to skip
> publishing the changes if the relation is part of skip schema
> publication.
> As a continuation to this, I will work on implementing skipping tables
> from all tables in schema and skipping tables from all tables
> publication.
>
> Attached patch has the implementation for this.

The patch was not applying on top of HEAD because of the recent
commits, attached patch is rebased on top of HEAD.

Regards,
Vignesh

Attachment Content-Type Size
v1-0001-Skip-publishing-the-tables-of-schema.patch text/x-patch 80.7 KB

From: vignesh C <vignesh21(at)gmail(dot)com>
To: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-12 06:23:29
Message-ID: CALDaNm3Rc2KxGzLy-4qxFS+MWS6GN-ROVoPEb1MFA53W3iAqog@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, Mar 26, 2022 at 7:37 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Tue, Mar 22, 2022 at 12:38 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > Hi,
> >
> > This feature adds an option to skip changes of all tables in specified
> > schema while creating publication.
> > This feature is helpful for use cases where the user wants to
> > subscribe to all the changes except for the changes present in a few
> > schemas.
> > Ex:
> > CREATE PUBLICATION pub1 FOR ALL TABLES SKIP ALL TABLES IN SCHEMA s1,s2;
> > OR
> > ALTER PUBLICATION pub1 ADD SKIP ALL TABLES IN SCHEMA s1,s2;
> >
> > A new column pnskip is added to table "pg_publication_namespace", to
> > maintain the schemas that the user wants to skip publishing through
> > the publication. Modified the output plugin (pgoutput) to skip
> > publishing the changes if the relation is part of skip schema
> > publication.
> > As a continuation to this, I will work on implementing skipping tables
> > from all tables in schema and skipping tables from all tables
> > publication.
> >
> > Attached patch has the implementation for this.
>
> The patch was not applying on top of HEAD because of the recent
> commits, attached patch is rebased on top of HEAD.

The patch does not apply on top of HEAD because of the recent commit,
attached patch is rebased on top of HEAD.

I have also included the implementation for skipping a few tables from
all tables publication, the 0002 patch has the implementation for the
same.
This feature is helpful for use cases where the user wants to
subscribe to all the changes except for the changes present in a few
tables.
Ex:
CREATE PUBLICATION pub1 FOR ALL TABLES SKIP TABLE t1,t2;
OR
ALTER PUBLICATION pub1 ADD SKIP TABLE t1,t2;

Regards,
Vignesh

Attachment Content-Type Size
v1-0001-Skip-publishing-the-tables-of-schema.patch text/x-patch 73.2 KB
v1-0002-Skip-publishing-the-tables.patch text/x-patch 58.0 KB

From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-12 06:49:22
Message-ID: CAA4eK1+rVhdxkwk76Rwyhxo_CHbR99GBvn8M9yhX2_xXgY8zWg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Apr 12, 2022 at 11:53 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Sat, Mar 26, 2022 at 7:37 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > On Tue, Mar 22, 2022 at 12:38 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > >
> > > Hi,
> > >
> > > This feature adds an option to skip changes of all tables in specified
> > > schema while creating publication.
> > > This feature is helpful for use cases where the user wants to
> > > subscribe to all the changes except for the changes present in a few
> > > schemas.
> > > Ex:
> > > CREATE PUBLICATION pub1 FOR ALL TABLES SKIP ALL TABLES IN SCHEMA s1,s2;
> > > OR
> > > ALTER PUBLICATION pub1 ADD SKIP ALL TABLES IN SCHEMA s1,s2;
> > >
> > > A new column pnskip is added to table "pg_publication_namespace", to
> > > maintain the schemas that the user wants to skip publishing through
> > > the publication. Modified the output plugin (pgoutput) to skip
> > > publishing the changes if the relation is part of skip schema
> > > publication.
> > > As a continuation to this, I will work on implementing skipping tables
> > > from all tables in schema and skipping tables from all tables
> > > publication.
> > >
> > > Attached patch has the implementation for this.
> >
> > The patch was not applying on top of HEAD because of the recent
> > commits, attached patch is rebased on top of HEAD.
>
> The patch does not apply on top of HEAD because of the recent commit,
> attached patch is rebased on top of HEAD.
>
> I have also included the implementation for skipping a few tables from
> all tables publication, the 0002 patch has the implementation for the
> same.
> This feature is helpful for use cases where the user wants to
> subscribe to all the changes except for the changes present in a few
> tables.
> Ex:
> CREATE PUBLICATION pub1 FOR ALL TABLES SKIP TABLE t1,t2;
> OR
> ALTER PUBLICATION pub1 ADD SKIP TABLE t1,t2;
>

For the second syntax (Alter Publication ...), isn't it better to
avoid using ADD? It looks odd to me because we are not adding anything
in publication with this sytax.

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-12 10:46:53
Message-ID: CALDaNm1v+jwrWLeYqANn7pfaka88BwUS2mrVTykSR8tJ8xQN1w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Apr 12, 2022 at 12:19 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Tue, Apr 12, 2022 at 11:53 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > On Sat, Mar 26, 2022 at 7:37 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > >
> > > On Tue, Mar 22, 2022 at 12:38 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > > >
> > > > Hi,
> > > >
> > > > This feature adds an option to skip changes of all tables in specified
> > > > schema while creating publication.
> > > > This feature is helpful for use cases where the user wants to
> > > > subscribe to all the changes except for the changes present in a few
> > > > schemas.
> > > > Ex:
> > > > CREATE PUBLICATION pub1 FOR ALL TABLES SKIP ALL TABLES IN SCHEMA s1,s2;
> > > > OR
> > > > ALTER PUBLICATION pub1 ADD SKIP ALL TABLES IN SCHEMA s1,s2;
> > > >
> > > > A new column pnskip is added to table "pg_publication_namespace", to
> > > > maintain the schemas that the user wants to skip publishing through
> > > > the publication. Modified the output plugin (pgoutput) to skip
> > > > publishing the changes if the relation is part of skip schema
> > > > publication.
> > > > As a continuation to this, I will work on implementing skipping tables
> > > > from all tables in schema and skipping tables from all tables
> > > > publication.
> > > >
> > > > Attached patch has the implementation for this.
> > >
> > > The patch was not applying on top of HEAD because of the recent
> > > commits, attached patch is rebased on top of HEAD.
> >
> > The patch does not apply on top of HEAD because of the recent commit,
> > attached patch is rebased on top of HEAD.
> >
> > I have also included the implementation for skipping a few tables from
> > all tables publication, the 0002 patch has the implementation for the
> > same.
> > This feature is helpful for use cases where the user wants to
> > subscribe to all the changes except for the changes present in a few
> > tables.
> > Ex:
> > CREATE PUBLICATION pub1 FOR ALL TABLES SKIP TABLE t1,t2;
> > OR
> > ALTER PUBLICATION pub1 ADD SKIP TABLE t1,t2;
> >
>
> For the second syntax (Alter Publication ...), isn't it better to
> avoid using ADD? It looks odd to me because we are not adding anything
> in publication with this sytax.

I was thinking of the scenario where user initially creates the
publication for all tables:
CREATE PUBLICATION pub1 FOR ALL TABLES;

After that user decides to skip few tables ex: t1, t2
ALTER PUBLICATION pub1 ADD SKIP TABLE t1,t2;

I thought of supporting this syntax if incase user decides to add the
skipping of a few tables later.
Thoughts?

Regards,
Vignesh


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-12 11:16:28
Message-ID: CAA4eK1JjfmfCz8evCpLx2EVKoH4m8rEgeRciEA7tMkjGx87cyQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Apr 12, 2022 at 4:17 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Tue, Apr 12, 2022 at 12:19 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> >
> > For the second syntax (Alter Publication ...), isn't it better to
> > avoid using ADD? It looks odd to me because we are not adding anything
> > in publication with this sytax.
>
> I was thinking of the scenario where user initially creates the
> publication for all tables:
> CREATE PUBLICATION pub1 FOR ALL TABLES;
>
> After that user decides to skip few tables ex: t1, t2
> ALTER PUBLICATION pub1 ADD SKIP TABLE t1,t2;
>
> I thought of supporting this syntax if incase user decides to add the
> skipping of a few tables later.
>

I understand that part but what I pointed out was that it might be
better to avoid using ADD keyword in this syntax like: ALTER
PUBLICATION pub1 SKIP TABLE t1,t2;

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-13 03:15:10
Message-ID: CALDaNm3pqo_Ej6M5yE77y78TDJMXEP0_SChwaHzn_WNsfqp-3Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Apr 12, 2022 at 4:46 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Tue, Apr 12, 2022 at 4:17 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > On Tue, Apr 12, 2022 at 12:19 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> > >
> > >
> > > For the second syntax (Alter Publication ...), isn't it better to
> > > avoid using ADD? It looks odd to me because we are not adding anything
> > > in publication with this sytax.
> >
> > I was thinking of the scenario where user initially creates the
> > publication for all tables:
> > CREATE PUBLICATION pub1 FOR ALL TABLES;
> >
> > After that user decides to skip few tables ex: t1, t2
> > ALTER PUBLICATION pub1 ADD SKIP TABLE t1,t2;
> >
> > I thought of supporting this syntax if incase user decides to add the
> > skipping of a few tables later.
> >
>
> I understand that part but what I pointed out was that it might be
> better to avoid using ADD keyword in this syntax like: ALTER
> PUBLICATION pub1 SKIP TABLE t1,t2;

Currently we are supporting Alter publication using the following syntax:
ALTER PUBLICATION pub1 ADD TABLE t1;
ALTER PUBLICATION pub1 SET TABLE t1;
ALTER PUBLICATION pub1 DROP TABLE T1;
ALTER PUBLICATION pub1 ADD ALL TABLES IN SCHEMA sch1;
ALTER PUBLICATION pub1 SET ALL TABLES IN SCHEMA sch1;
ALTER PUBLICATION pub1 DROP ALL TABLES IN SCHEMA sch1;

I have extended the new syntax in similar lines:
ALTER PUBLICATION pub1 ADD SKIP TABLE t1;
ALTER PUBLICATION pub1 SET SKIP TABLE t1;
ALTER PUBLICATION pub1 DROP SKIP TABLE T1;

I did it like this to maintain consistency.
But I'm fine doing it either way to keep it simple for the user.

Regards,
Vignesh


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-13 04:39:51
Message-ID: CAA4eK1L-+c9Au_RL3aKottAeHOiUgEtVwgQJobZazxpFqzsBbw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Apr 13, 2022 at 8:45 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Tue, Apr 12, 2022 at 4:46 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> > I understand that part but what I pointed out was that it might be
> > better to avoid using ADD keyword in this syntax like: ALTER
> > PUBLICATION pub1 SKIP TABLE t1,t2;
>
> Currently we are supporting Alter publication using the following syntax:
> ALTER PUBLICATION pub1 ADD TABLE t1;
> ALTER PUBLICATION pub1 SET TABLE t1;
> ALTER PUBLICATION pub1 DROP TABLE T1;
> ALTER PUBLICATION pub1 ADD ALL TABLES IN SCHEMA sch1;
> ALTER PUBLICATION pub1 SET ALL TABLES IN SCHEMA sch1;
> ALTER PUBLICATION pub1 DROP ALL TABLES IN SCHEMA sch1;
>
> I have extended the new syntax in similar lines:
> ALTER PUBLICATION pub1 ADD SKIP TABLE t1;
> ALTER PUBLICATION pub1 SET SKIP TABLE t1;
> ALTER PUBLICATION pub1 DROP SKIP TABLE T1;
>
> I did it like this to maintain consistency.
>

What is the difference between ADD and SET variants? I understand we
need some way to remove the SKIP table setting but not sure if DROP is
the best alternative.

The other ideas could be:
To set skip tables: ALTER PUBLICATION pub1 SKIP TABLE t1, t2...;
To reset skip tables: ALTER PUBLICATION pub1 SKIP TABLE; /* basically
an empty list*/
Yet another way to reset skip tables: ALTER PUBLICATION pub1 RESET
SKIP TABLE; /* Here we need to introduce RESET. */

--
With Regards,
Amit Kapila.


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-13 07:35:39
Message-ID: CAHut+PtoZmyi_0cW_nyChqXBrZ=aO8e_BN+F7aVAjW5J-KnQLQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Apr 13, 2022 at 2:40 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Wed, Apr 13, 2022 at 8:45 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > On Tue, Apr 12, 2022 at 4:46 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> > >
> > > I understand that part but what I pointed out was that it might be
> > > better to avoid using ADD keyword in this syntax like: ALTER
> > > PUBLICATION pub1 SKIP TABLE t1,t2;
> >
> > Currently we are supporting Alter publication using the following syntax:
> > ALTER PUBLICATION pub1 ADD TABLE t1;
> > ALTER PUBLICATION pub1 SET TABLE t1;
> > ALTER PUBLICATION pub1 DROP TABLE T1;
> > ALTER PUBLICATION pub1 ADD ALL TABLES IN SCHEMA sch1;
> > ALTER PUBLICATION pub1 SET ALL TABLES IN SCHEMA sch1;
> > ALTER PUBLICATION pub1 DROP ALL TABLES IN SCHEMA sch1;
> >
> > I have extended the new syntax in similar lines:
> > ALTER PUBLICATION pub1 ADD SKIP TABLE t1;
> > ALTER PUBLICATION pub1 SET SKIP TABLE t1;
> > ALTER PUBLICATION pub1 DROP SKIP TABLE T1;
> >
> > I did it like this to maintain consistency.
> >
>
> What is the difference between ADD and SET variants? I understand we
> need some way to remove the SKIP table setting but not sure if DROP is
> the best alternative.
>
> The other ideas could be:
> To set skip tables: ALTER PUBLICATION pub1 SKIP TABLE t1, t2...;
> To reset skip tables: ALTER PUBLICATION pub1 SKIP TABLE; /* basically
> an empty list*/
> Yet another way to reset skip tables: ALTER PUBLICATION pub1 RESET
> SKIP TABLE; /* Here we need to introduce RESET. */
>

When you were talking about SKIP TABLE then I liked the idea of:

ALTER ... SET SKIP TABLE; /* empty list to reset the table skips */
ALTER ... SET SKIP TABLE t1,t2; /* non-empty list to replace the table skips */

But when you apply that rule to SKIP ALL TABLES IN SCHEMA, then the
reset syntax looks too awkward.

ALTER ... SET SKIP ALL TABLES IN SCHEMA; /* empty list to reset the
schema skips */
ALTER ... SET SKIP ALL TABLES IN SCHEMA s1,s2; /* non-empty list to
replace the schema skips */

~~~

IMO it might be simpler to do it like:

ALTER ... DROP SKIP; /* reset/remove the skip */
ALTER ... SET SKIP TABLE t1,t2; /* non-empty list to replace table skips */
ALTER ... SET SKIP ALL TABLES IS SCHEMA s1,s2; /* non-empty list to
replace schema skips */

I don't really think that the ALTER ... SET SKIP empty list should be
supported (because reason above)
I don't really think that the ALTER ... ADD SKIP should be supported.

===

More questions - What happens if the skip table or skip schema no
longer exists exist? Does that mean error? Maybe there is a
dependency on it but OTOH it might be annoying - e.g. to disallow a
DROP TABLE when the only dependency was that the user wanted to SKIP
it...

------
Kind Regards,
Peter Smith.
Fujitsu Australia


From: "shiy(dot)fnst(at)fujitsu(dot)com" <shiy(dot)fnst(at)fujitsu(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Skipping schema changes in publication
Date: 2022-04-14 08:55:01
Message-ID: OSZPR01MB6310F8C2400C054D7E784B3DFDEF9@OSZPR01MB6310.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Apr 12, 2022 2:23 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> The patch does not apply on top of HEAD because of the recent commit,
> attached patch is rebased on top of HEAD.
>

Thanks for your patch. Here are some comments for 0001 patch.

1. doc/src/sgml/catalogs.sgml
@@ -6438,6 +6438,15 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
A null value indicates that all columns are published.
</para></entry>
</row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>pnskip</structfield> <type>bool</type>
+ </para>
+ <para>
+ True if the schema is skip schema
+ </para></entry>
+ </row>
</tbody>
</tgroup>
</table>

This change is added to pg_publication_rel, I think it should be added to
pg_publication_namespace, right?

2.
postgres=# alter publication p1 add skip all tables in schema s1,s2;
ERROR: schema "s1" is already member of publication "p1"

This error message seems odd to me, can we improve it? Something like:
schema "s1" is already skipped in publication "p1"

3.
create table tbl (a int primary key);
create schema s1;
create schema s2;
create table s1.tbl (a int);
create publication p1 for all tables skip all tables in schema s1,s2;

postgres=# \dRp+
Publication p1
Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
----------+------------+---------+---------+---------+-----------+----------
postgres | t | t | t | t | t | f
Skip tables from schemas:
"s1"
"s2"

postgres=# select * from pg_publication_tables;
pubname | schemaname | tablename
---------+------------+-----------
p1 | public | tbl
p1 | s1 | tbl
(2 rows)

There shouldn't be a record of s1.tbl, since all tables in schema s1 are skipped.

I found that it is caused by the following code:

src/backend/catalog/pg_publication.c
+ foreach(cell, pubschemalist)
+ {
+ PublicationSchInfo *pubsch = (PublicationSchInfo *) lfirst(cell);
+
+ skipschemaidlist = lappend_oid(result, pubsch->oid);
+ }

The first argument to append_oid() seems wrong, should it be:

skipschemaidlist = lappend_oid(skipschemaidlist, pubsch->oid);

4. src/backend/commands/publicationcmds.c

/*
* Convert the PublicationObjSpecType list into schema oid list and
* PublicationTable list.
*/
static void
ObjectsInPublicationToOids(List *pubobjspec_list, ParseState *pstate,
List **rels, List **schemas)

Should we modify the comment of ObjectsInPublicationToOids()?
"schema oid list" should be "PublicationSchInfo list".

Regards,
Shi yu


From: "wangw(dot)fnst(at)fujitsu(dot)com" <wangw(dot)fnst(at)fujitsu(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Skipping schema changes in publication
Date: 2022-04-14 09:33:15
Message-ID: OS3PR01MB6275C6E3901B8C918B0CF0AB9EEF9@OS3PR01MB6275.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Apr 12, 2022 at 2:23 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> The patch does not apply on top of HEAD because of the recent commit,
> attached patch is rebased on top of HEAD.
Thanks for your patches.

Here are some comments for v1-0001:
1.
I found the patch add the following two new functions in gram.y:
preprocess_alltables_pubobj_list, check_skip_in_pubobj_list.
These two functions look similar. So could we just add one new function?
Besides, do we need the API `location` in new function
preprocess_alltables_pubobj_list? It seems that "location" is not used in this
new function.
In addition, the location of error cursor in the messages seems has a little
problem. For example:
postgres=# create publication pub for all TABLES skip all tables in schema public, table test;
ERROR: only SKIP ALL TABLES IN SCHEMA or SKIP TABLE can be specified with ALL TABLES option
LINE 1: create publication pub for all TABLES skip all tables in sch...
^
(The location of error cursor is under 'create')

2. I think maybe there is a minor missing in function
preprocess_alltables_pubobj_list and check_skip_in_pubobj_list:
We seem to be missing the CURRENT_SCHEMA case.
For example(In function preprocess_alltables_pubobj_list) :
+ /* Only SKIP ALL TABLES IN SCHEMA option supported with ALL TABLES */
+ if (pubobj->pubobjtype != PUBLICATIONOBJ_TABLES_IN_SCHEMA ||
+ !pubobj->skip)
maybe need to be changed like this:
+ /* Only SKIP ALL TABLES IN SCHEMA option supported with ALL TABLES */
+ if ((pubobj->pubobjtype != PUBLICATIONOBJ_TABLES_IN_SCHEMA &&
+ pubobj->pubobjtype != PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA) &&
+ pubobj->skip)

3. I think maybe there are some minor missing in create_publication.sgml.
+ [ FOR ALL TABLES [SKIP ALL TABLES IN SCHEMA { <replaceable class="parameter">schema_name</replaceable> | CURRENT_SCHEMA }]
maybe need to be changed to this:
+ [ FOR ALL TABLES [SKIP ALL TABLES IN SCHEMA { <replaceable class="parameter">schema_name</replaceable> | CURRENT_SCHEMA } [, ... ]]

4. The error message of function CreatePublication.
Does the message below need to be modified like the comment?
In addition, I think maybe "FOR/SKIP" is better.
@@ -835,18 +843,21 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
- /* FOR ALL TABLES IN SCHEMA requires superuser */
+ /* FOR [SKIP] ALL TABLES IN SCHEMA requires superuser */
if (list_length(schemaidlist) > 0 && !superuser())
ereport(ERROR,
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to create FOR ALL TABLES IN SCHEMA publication"));

5.
I think there are some minor missing in tab-complete.c.
+ Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "SKIP", "ALL", "TABLES", "IN", "SCHEMA"))
maybe need to be changed to this:
+ Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "SKIP", "ALL", "TABLES", "IN", "SCHEMA"))

+ Matches("CREATE", "PUBLICATION", MatchAny, "SKIP", "FOR", "ALL", "TABLES", "IN", "SCHEMA", MatchAny)) &&
maybe need to be changed to this:
+ Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "SKIP", "ALL", "TABLES", "IN", "SCHEMA", MatchAny)) &&

6.
In function get_rel_sync_entry, do we need `if (!publish)` in below code?
I think `publish` is always false here, as we delete the check for
"pub->alltables".
```
- /*
- * If this is a FOR ALL TABLES publication, pick the partition root
- * and set the ancestor level accordingly.
- */
- if (pub->alltables)
- {
- ......
- }
-
if (!publish)
```

Regards,
Wang wei


From: Peter Eisentraut <peter(dot)eisentraut(at)enterprisedb(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-14 13:47:58
Message-ID: a2004f08-eb2f-b124-115c-f8f18667e585@enterprisedb.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On 12.04.22 08:23, vignesh C wrote:
> I have also included the implementation for skipping a few tables from
> all tables publication, the 0002 patch has the implementation for the
> same.
> This feature is helpful for use cases where the user wants to
> subscribe to all the changes except for the changes present in a few
> tables.
> Ex:
> CREATE PUBLICATION pub1 FOR ALL TABLES SKIP TABLE t1,t2;
> OR
> ALTER PUBLICATION pub1 ADD SKIP TABLE t1,t2;

We have already allocated the "skip" terminology for skipping
transactions, which is a dynamic run-time action. We are also using the
term "skip" elsewhere to skip locked rows, which is similarly a run-time
action. I think it would be confusing to use the term SKIP for DDL
construction.

Let's find another term like "omit", "except", etc.

I would also think about this in broader terms. For example, sometimes
people want features like "all columns except these" in certain places.
The syntax for those things should be similar.

That said, I'm not sure this feature is worth the trouble. If this is
useful, what about "whole database except these schemas"? What about
"create this database from this template except these schemas". This
could get out of hand. I think we should encourage users to group their
object the way they want and not offer these complicated negative
selection mechanisms.


From: "Euler Taveira" <euler(at)eulerto(dot)com>
To: "Peter Eisentraut" <peter(dot)eisentraut(at)enterprisedb(dot)com>, "vignesh C" <vignesh21(at)gmail(dot)com>, "PostgreSQL Hackers" <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-14 19:55:24
Message-ID: 00afeb42-19b3-47a6-821e-e78d366eb0b0@www.fastmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Apr 14, 2022, at 10:47 AM, Peter Eisentraut wrote:
> On 12.04.22 08:23, vignesh C wrote:
> > I have also included the implementation for skipping a few tables from
> > all tables publication, the 0002 patch has the implementation for the
> > same.
> > This feature is helpful for use cases where the user wants to
> > subscribe to all the changes except for the changes present in a few
> > tables.
> > Ex:
> > CREATE PUBLICATION pub1 FOR ALL TABLES SKIP TABLE t1,t2;
> > OR
> > ALTER PUBLICATION pub1 ADD SKIP TABLE t1,t2;
>
> We have already allocated the "skip" terminology for skipping
> transactions, which is a dynamic run-time action. We are also using the
> term "skip" elsewhere to skip locked rows, which is similarly a run-time
> action. I think it would be confusing to use the term SKIP for DDL
> construction.
I didn't like the SKIP choice too. We already have EXCEPT for IMPORT FOREIGN
SCHEMA and if I were to suggest a keyword, it would be EXCEPT.

> I would also think about this in broader terms. For example, sometimes
> people want features like "all columns except these" in certain places.
> The syntax for those things should be similar.
The questions are:
What kind of issues does it solve?
Do we have a workaround for it?

> That said, I'm not sure this feature is worth the trouble. If this is
> useful, what about "whole database except these schemas"? What about
> "create this database from this template except these schemas". This
> could get out of hand. I think we should encourage users to group their
> object the way they want and not offer these complicated negative
> selection mechanisms.
I have the same impression too. We already provide a way to:

* include individual tables;
* include all tables;
* include all tables in a certain schema.

Doesn't it cover the majority of the use cases? We don't need to cover all
possible cases in one DDL command. IMO the current grammar for CREATE
PUBLICATION is already complicated after the ALL TABLES IN SCHEMA. You are
proposing to add "ALL TABLES SKIP ALL TABLES" that sounds repetitive but it is
not; doesn't seem well-thought-out. I'm also concerned about possible gotchas
for this proposal. The first command above suggests that it skips all tables in a
certain schema. What happen if I decide to include a particular table of the
skipped schema (second command)?

ALTER PUBLICATION pub1 ADD SKIP ALL TABLES IN SCHEMA s1,s2;
ALTER PUBLICATION pub1 ADD TABLE s1.foo;

Having said that I'm not wedded to this proposal. Unless someone provides
compelling use cases for this additional syntax, I think we should leave the
publication syntax as is.

--
Euler Taveira
EDB https://www.enterprisedb.com/


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Euler Taveira <euler(at)eulerto(dot)com>
Cc: Peter Eisentraut <peter(dot)eisentraut(at)enterprisedb(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-18 07:01:59
Message-ID: CAA4eK1KikfJMVggZ_aNWPio7zrdObVdidG3SZVWEZ_LOU=vXkg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Apr 15, 2022 at 1:26 AM Euler Taveira <euler(at)eulerto(dot)com> wrote:
>
> On Thu, Apr 14, 2022, at 10:47 AM, Peter Eisentraut wrote:
>
> On 12.04.22 08:23, vignesh C wrote:
> > I have also included the implementation for skipping a few tables from
> > all tables publication, the 0002 patch has the implementation for the
> > same.
> > This feature is helpful for use cases where the user wants to
> > subscribe to all the changes except for the changes present in a few
> > tables.
> > Ex:
> > CREATE PUBLICATION pub1 FOR ALL TABLES SKIP TABLE t1,t2;
> > OR
> > ALTER PUBLICATION pub1 ADD SKIP TABLE t1,t2;
>
> We have already allocated the "skip" terminology for skipping
> transactions, which is a dynamic run-time action. We are also using the
> term "skip" elsewhere to skip locked rows, which is similarly a run-time
> action. I think it would be confusing to use the term SKIP for DDL
> construction.
>
> I didn't like the SKIP choice too. We already have EXCEPT for IMPORT FOREIGN
> SCHEMA and if I were to suggest a keyword, it would be EXCEPT.
>

+1 for EXCEPT.

> I would also think about this in broader terms. For example, sometimes
> people want features like "all columns except these" in certain places.
> The syntax for those things should be similar.
>
> The questions are:
> What kind of issues does it solve?

As far as I understand, it is for usability, otherwise, users need to
list all required columns' names even if they don't want to hide most
of the columns in the table. Consider user doesn't want to publish the
'salary' or other sensitive information of executives/employees but
would like to publish all other columns. I feel in such cases it will
be a lot of work for the user especially when the table has many
columns. I see that Oracle has a similar feature [1]. I think without
this it will be difficult for users to use this feature in some cases.

> Do we have a workaround for it?
>

I can't think of any except the user needs to manually input all
required columns. Can you think of any other workaround?

> That said, I'm not sure this feature is worth the trouble. If this is
> useful, what about "whole database except these schemas"? What about
> "create this database from this template except these schemas". This
> could get out of hand. I think we should encourage users to group their
> object the way they want and not offer these complicated negative
> selection mechanisms.
>
> I have the same impression too. We already provide a way to:
>
> * include individual tables;
> * include all tables;
> * include all tables in a certain schema.
>
> Doesn't it cover the majority of the use cases?
>

Similar to columns, the same applies to tables. Users need to manually
add all tables for a database even when she wants to avoid only a
handful of tables from the database say because they contain sensitive
information or are not required. I think we don't need to cover all
possible exceptions but a few where users can avoid some tables would
be useful. If not, what kind of alternative do users have except for
listing all columns or all tables that are required.

[1] - https://docs.oracle.com/en/cloud/paas/goldengate-cloud/gwuad/selecting-columns.html#GUID-9A851C8B-48F7-43DF-8D98-D086BE069E20

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Eisentraut <peter(dot)eisentraut(at)enterprisedb(dot)com>
Cc: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-18 09:40:46
Message-ID: CALDaNm1rS+tde7RSD0VSEbdmER6QmHVyZGz5MZ9KmBeDLY2JRA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Apr 14, 2022 at 7:18 PM Peter Eisentraut
<peter(dot)eisentraut(at)enterprisedb(dot)com> wrote:
>
> On 12.04.22 08:23, vignesh C wrote:
> > I have also included the implementation for skipping a few tables from
> > all tables publication, the 0002 patch has the implementation for the
> > same.
> > This feature is helpful for use cases where the user wants to
> > subscribe to all the changes except for the changes present in a few
> > tables.
> > Ex:
> > CREATE PUBLICATION pub1 FOR ALL TABLES SKIP TABLE t1,t2;
> > OR
> > ALTER PUBLICATION pub1 ADD SKIP TABLE t1,t2;
>
> We have already allocated the "skip" terminology for skipping
> transactions, which is a dynamic run-time action. We are also using the
> term "skip" elsewhere to skip locked rows, which is similarly a run-time
> action. I think it would be confusing to use the term SKIP for DDL
> construction.
>
> Let's find another term like "omit", "except", etc.

+1 for Except

> I would also think about this in broader terms. For example, sometimes
> people want features like "all columns except these" in certain places.
> The syntax for those things should be similar.
>
> That said, I'm not sure this feature is worth the trouble. If this is
> useful, what about "whole database except these schemas"? What about
> "create this database from this template except these schemas". This
> could get out of hand. I think we should encourage users to group their
> object the way they want and not offer these complicated negative
> selection mechanisms.

I thought this feature would help when there are many many tables in
the database and the user wants only certain confidential tables like
credit card information. In this case instead of specifying the whole
table list it will be better to specify "ALL TABLES EXCEPT
cred_info_tbl".
I had seen that mysql also has a similar option replicate-ignore-table
to ignore the changes on specific tables as mentioned in [1].
Similar use case exists in pg_dump too. pg_dump has an option
exclude-table that will be used for not dumping any tables that are
matching the table specified as in [2].

[1] - https://dev.mysql.com/doc/refman/5.7/en/change-replication-filter.html
[2] - https://www.postgresql.org/docs/devel/app-pgdump.html

Regards,
Vignesh


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Euler Taveira <euler(at)eulerto(dot)com>, Peter Eisentraut <peter(dot)eisentraut(at)enterprisedb(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-21 03:15:07
Message-ID: CALDaNm2KJRmQMcpOn0QPoKm6ET93Z-PSmbwwdm8O0Lr3eWqkTw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Apr 18, 2022 at 12:32 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Fri, Apr 15, 2022 at 1:26 AM Euler Taveira <euler(at)eulerto(dot)com> wrote:
> >
> > On Thu, Apr 14, 2022, at 10:47 AM, Peter Eisentraut wrote:
> >
> > On 12.04.22 08:23, vignesh C wrote:
> > > I have also included the implementation for skipping a few tables from
> > > all tables publication, the 0002 patch has the implementation for the
> > > same.
> > > This feature is helpful for use cases where the user wants to
> > > subscribe to all the changes except for the changes present in a few
> > > tables.
> > > Ex:
> > > CREATE PUBLICATION pub1 FOR ALL TABLES SKIP TABLE t1,t2;
> > > OR
> > > ALTER PUBLICATION pub1 ADD SKIP TABLE t1,t2;
> >
> > We have already allocated the "skip" terminology for skipping
> > transactions, which is a dynamic run-time action. We are also using the
> > term "skip" elsewhere to skip locked rows, which is similarly a run-time
> > action. I think it would be confusing to use the term SKIP for DDL
> > construction.
> >
> > I didn't like the SKIP choice too. We already have EXCEPT for IMPORT FOREIGN
> > SCHEMA and if I were to suggest a keyword, it would be EXCEPT.
> >
>
> +1 for EXCEPT.

Updated patch by changing the syntax to use EXCEPT instead of SKIP.

Regards,
Vignesh

Attachment Content-Type Size
v2-0001-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch text/x-patch 61.7 KB

From: Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-22 16:09:24
Message-ID: CALj2ACVOzhs+BD+abFV2x4oKJdsDNd6SgsE7r8UjnZDCKGEckA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 22, 2022 at 12:39 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> Hi,
>
> This feature adds an option to skip changes of all tables in specified
> schema while creating publication.
> This feature is helpful for use cases where the user wants to
> subscribe to all the changes except for the changes present in a few
> schemas.
> Ex:
> CREATE PUBLICATION pub1 FOR ALL TABLES SKIP ALL TABLES IN SCHEMA s1,s2;
> OR
> ALTER PUBLICATION pub1 ADD SKIP ALL TABLES IN SCHEMA s1,s2;
>
> A new column pnskip is added to table "pg_publication_namespace", to
> maintain the schemas that the user wants to skip publishing through
> the publication. Modified the output plugin (pgoutput) to skip
> publishing the changes if the relation is part of skip schema
> publication.
> As a continuation to this, I will work on implementing skipping tables
> from all tables in schema and skipping tables from all tables
> publication.
>
> Attached patch has the implementation for this.
> This feature is for the pg16 version.
> Thoughts?

The feature seems to be useful especially when there are lots of
schemas in a database. However, I don't quite like the syntax. Do we
have 'SKIP' identifier in any of the SQL statements in SQL standard?
Can we think of adding skip_schema_list as an option, something like
below?

CREATE PUBLICATION foo FOR ALL TABLES (skip_schema_list = 's1, s2');
ALTER PUBLICATION foo SET (skip_schema_list = 's1, s2'); - to set
ALTER PUBLICATION foo SET (skip_schema_list = ''); - to reset

Regards,
Bharath Rupireddy.


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-26 01:55:21
Message-ID: CAHut+PuEJ212wbiDG903uLOWAjNKYaneBNDDbuYW8-9iSOrrYg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, Apr 23, 2022 at 2:09 AM Bharath Rupireddy
<bharath(dot)rupireddyforpostgres(at)gmail(dot)com> wrote:
>
> On Tue, Mar 22, 2022 at 12:39 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > Hi,
> >
> > This feature adds an option to skip changes of all tables in specified
> > schema while creating publication.
> > This feature is helpful for use cases where the user wants to
> > subscribe to all the changes except for the changes present in a few
> > schemas.
> > Ex:
> > CREATE PUBLICATION pub1 FOR ALL TABLES SKIP ALL TABLES IN SCHEMA s1,s2;
> > OR
> > ALTER PUBLICATION pub1 ADD SKIP ALL TABLES IN SCHEMA s1,s2;
> >
> > A new column pnskip is added to table "pg_publication_namespace", to
> > maintain the schemas that the user wants to skip publishing through
> > the publication. Modified the output plugin (pgoutput) to skip
> > publishing the changes if the relation is part of skip schema
> > publication.
> > As a continuation to this, I will work on implementing skipping tables
> > from all tables in schema and skipping tables from all tables
> > publication.
> >
> > Attached patch has the implementation for this.
> > This feature is for the pg16 version.
> > Thoughts?
>
> The feature seems to be useful especially when there are lots of
> schemas in a database. However, I don't quite like the syntax. Do we
> have 'SKIP' identifier in any of the SQL statements in SQL standard?
> Can we think of adding skip_schema_list as an option, something like
> below?
>
> CREATE PUBLICATION foo FOR ALL TABLES (skip_schema_list = 's1, s2');
> ALTER PUBLICATION foo SET (skip_schema_list = 's1, s2'); - to set
> ALTER PUBLICATION foo SET (skip_schema_list = ''); - to reset
>

I had been wondering for some time if there was any way to introduce a
more flexible pattern matching into PUBLICATION but without bloating
the syntax. Maybe your idea to use an option for the "skip" gives a
way to do it...

For example, if we could use regex (for <schemaname>.<tablename>
patterns) for the option value then....

~~

e.g.1. Exclude certain tables:

// do NOT publish any tables of schemas s1,s2
CREATE PUBLICATION foo FOR ALL TABLES (exclude_match = '(s1\..*)|(s2\..*)');

// do NOT publish my secret tables (those called "mysecretXXX")
CREATE PUBLICATION foo FOR ALL TABLES (exclude_match = '(.*\.mysecret.*)');

~~

e.g.2. Only allow certain tables.

// ONLY publish my tables (those called "mytableXXX")
CREATE PUBLICATION foo FOR ALL TABLES (subset_match = '(.*\.mytable.*)');

// So following is equivalent to FOR ALL TABLES IN SCHEMA s1
CREATE PUBLICATION foo FOR ALL TABLES (subset_match = '(s1\..*)');

------
Kind Regards,
Peter Smith.
Fujitsu Australia


From: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>
To: 'vignesh C' <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Euler Taveira <euler(at)eulerto(dot)com>, Peter Eisentraut <peter(dot)eisentraut(at)enterprisedb(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Skipping schema changes in publication
Date: 2022-04-26 06:02:46
Message-ID: TYCPR01MB8373FE72A4CDBE7A5E8886EBEDFB9@TYCPR01MB8373.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thursday, April 21, 2022 12:15 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> Updated patch by changing the syntax to use EXCEPT instead of SKIP.
Hi

This is my review comments on the v2 patch.

(1) gram.y

I think we can make a unified function that merges
preprocess_alltables_pubobj_list with check_except_in_pubobj_list.

With regard to preprocess_alltables_pubobj_list,
we don't use the 2nd argument "location" in this function.

(2) create_publication.sgml

+ <para>
+ Create a publication that publishes all changes in all the tables except for
+ the changes of <structname>users</structname> and
+ <structname>departments</structname> table;

This sentence should end ":" not ";".

(3) publication.out & publication.sql

+-- fail - can't set except table to schema publication
+ALTER PUBLICATION testpub_forschema SET EXCEPT TABLE testpub_tbl1;

There is one unnecessary space in the comment.
Kindly change from "schema publication" to "schema publication".

(4) pg_dump.c & describe.c

In your first email of this thread, you explained this feature
is for PG16. Don't we need additional branch for PG16 ?

@@ -6322,6 +6328,21 @@ describePublications(const char *pattern)
}
}

+ if (pset.sversion >= 150000)
+ {

@@ -4162,7 +4164,7 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
/* Collect all publication membership info. */
if (fout->remoteVersion >= 150000)
appendPQExpBufferStr(query,
- "SELECT tableoid, oid, prpubid, prrelid, "
+ "SELECT tableoid, oid, prpubid, prrelid, prexcept,"

(5) psql-ref.sgml

+ If <literal>+</literal> is appended to the command name, the tables,
+ except tables and schemas associated with each publication are shown as
+ well.

I'm not sure if "except tables" is a good description.
I suggest "excluded tables". This applies to the entire patch,
in case if this is reasonable suggestion.

Best Regards,
Takamichi Osumi


From: vignesh C <vignesh21(at)gmail(dot)com>
To: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Euler Taveira <euler(at)eulerto(dot)com>, Peter Eisentraut <peter(dot)eisentraut(at)enterprisedb(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-27 12:50:11
Message-ID: CALDaNm3bpBwQSFMCAXuKm-UFNAD4J27M4Ey+o=_87NRW9YBcJg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Apr 26, 2022 at 11:32 AM osumi(dot)takamichi(at)fujitsu(dot)com
<osumi(dot)takamichi(at)fujitsu(dot)com> wrote:
>
> On Thursday, April 21, 2022 12:15 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > Updated patch by changing the syntax to use EXCEPT instead of SKIP.
> Hi
>
>
> This is my review comments on the v2 patch.
>
> (1) gram.y
>
> I think we can make a unified function that merges
> preprocess_alltables_pubobj_list with check_except_in_pubobj_list.
>
> With regard to preprocess_alltables_pubobj_list,
> we don't use the 2nd argument "location" in this function.

Removed location and made a unified function.

> (2) create_publication.sgml
>
> + <para>
> + Create a publication that publishes all changes in all the tables except for
> + the changes of <structname>users</structname> and
> + <structname>departments</structname> table;
>
> This sentence should end ":" not ";".

Modified

> (3) publication.out & publication.sql
>
> +-- fail - can't set except table to schema publication
> +ALTER PUBLICATION testpub_forschema SET EXCEPT TABLE testpub_tbl1;
>
> There is one unnecessary space in the comment.
> Kindly change from "schema publication" to "schema publication".

Modified

> (4) pg_dump.c & describe.c
>
> In your first email of this thread, you explained this feature
> is for PG16. Don't we need additional branch for PG16 ?
>
> @@ -6322,6 +6328,21 @@ describePublications(const char *pattern)
> }
> }
>
> + if (pset.sversion >= 150000)
> + {
>
>
> @@ -4162,7 +4164,7 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
> /* Collect all publication membership info. */
> if (fout->remoteVersion >= 150000)
> appendPQExpBufferStr(query,
> - "SELECT tableoid, oid, prpubid, prrelid, "
> + "SELECT tableoid, oid, prpubid, prrelid, prexcept,"
>

Modified by adding a comment saying "FIXME: 150000 should be changed
to 160000 later for PG16."

> (5) psql-ref.sgml
>
> + If <literal>+</literal> is appended to the command name, the tables,
> + except tables and schemas associated with each publication are shown as
> + well.
>
> I'm not sure if "except tables" is a good description.
> I suggest "excluded tables". This applies to the entire patch,
> in case if this is reasonable suggestion.

Modified it in most of the places where it was applicable. I felt the
usage was ok in a few places.

Thanks for the comments, the attached v3 patch has the changes for the same.

Regards.
Vignesh

Attachment Content-Type Size
v3-0001-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch text/x-patch 62.6 KB

From: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>
To: 'vignesh C' <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Euler Taveira <euler(at)eulerto(dot)com>, Peter Eisentraut <peter(dot)eisentraut(at)enterprisedb(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Skipping schema changes in publication
Date: 2022-04-28 11:20:52
Message-ID: TYCPR01MB8373047EB3D48C7FE7109428EDFD9@TYCPR01MB8373.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wednesday, April 27, 2022 9:50 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> Thanks for the comments, the attached v3 patch has the changes for the same.
Hi

Thank you for updating the patch. Several minor comments on v3.

(1) commit message

The new syntax allows specifying schemas. For example:
CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE t1,t2;
OR
ALTER PUBLICATION pub1 ADD EXCEPT TABLE t1,t2;

We have above sentence, but it looks better
to make the description a bit more accurate.

Kindly change
From :
"The new syntax allows specifying schemas"
To :
"The new syntax allows specifying excluded relations"

Also, kindly change "OR" to "or",
because this description is not syntax.

(2) publication_add_relation

@@ -396,6 +400,9 @@ publication_add_relation(Oid pubid, PublicationRelInfo *pri,
ObjectIdGetDatum(pubid);
values[Anum_pg_publication_rel_prrelid - 1] =
ObjectIdGetDatum(relid);
+ values[Anum_pg_publication_rel_prexcept - 1] =
+ BoolGetDatum(pri->except);
+

/* Add qualifications, if available */

It would be better to remove the blank line,
because with this change, we'll have two blank
lines in a row.

(3) pg_dump.h & pg_dump_sort.c

@@ -80,6 +80,7 @@ typedef enum
DO_REFRESH_MATVIEW,
DO_POLICY,
DO_PUBLICATION,
+ DO_PUBLICATION_EXCEPT_REL,
DO_PUBLICATION_REL,
DO_PUBLICATION_TABLE_IN_SCHEMA,
DO_SUBSCRIPTION

@@ -90,6 +90,7 @@ enum dbObjectTypePriorities
PRIO_FK_CONSTRAINT,
PRIO_POLICY,
PRIO_PUBLICATION,
+ PRIO_PUBLICATION_EXCEPT_REL,
PRIO_PUBLICATION_REL,
PRIO_PUBLICATION_TABLE_IN_SCHEMA,
PRIO_SUBSCRIPTION,
@@ -144,6 +145,7 @@ static const int dbObjectTypePriority[] =
PRIO_REFRESH_MATVIEW, /* DO_REFRESH_MATVIEW */
PRIO_POLICY, /* DO_POLICY */
PRIO_PUBLICATION, /* DO_PUBLICATION */
+ PRIO_PUBLICATION_EXCEPT_REL, /* DO_PUBLICATION_EXCEPT_REL */
PRIO_PUBLICATION_REL, /* DO_PUBLICATION_REL */
PRIO_PUBLICATION_TABLE_IN_SCHEMA, /* DO_PUBLICATION_TABLE_IN_SCHEMA */
PRIO_SUBSCRIPTION /* DO_SUBSCRIPTION */

How about having similar order between
pg_dump.h and pg_dump_sort.c, like
we'll add DO_PUBLICATION_EXCEPT_REL
after DO_PUBLICATION_REL in pg_dump.h ?

(4) GetAllTablesPublicationRelations

+ /*
+ * pg_publication_rel and pg_publication_namespace will only have except
+ * tables in case of all tables publication, no need to pass except flag
+ * to get the relations.
+ */
+ List *exceptpubtablelist = GetPublicationRelations(pubid, PUBLICATION_PART_ALL);
+

There is one unnecessary space in a comment
"...pg_publication_namespace will only have...". Kindly remove it.

Then, how about diving the variable declaration and
the insertion of the return value of GetPublicationRelations ?
That might be aligned with other places in this file.

(5) GetTopMostAncestorInPublication

@@ -302,8 +303,9 @@ GetTopMostAncestorInPublication(Oid puboid, List *ancestors, int *ancestor_level
foreach(lc, ancestors)
{
Oid ancestor = lfirst_oid(lc);
- List *apubids = GetRelationPublications(ancestor);
+ List *apubids = GetRelationPublications(ancestor, false);
List *aschemaPubids = NIL;
+ List *aexceptpubids;

level++;

@@ -317,7 +319,9 @@ GetTopMostAncestorInPublication(Oid puboid, List *ancestors, int *ancestor_level
else
{
aschemaPubids = GetSchemaPublications(get_rel_namespace(ancestor));
- if (list_member_oid(aschemaPubids, puboid))
+ aexceptpubids = GetRelationPublications(ancestor, true);
+ if (list_member_oid(aschemaPubids, puboid) ||
+ (puballtables && !list_member_oid(aexceptpubids, puboid)))
{
topmost_relid = ancestor;

It seems we forgot to call list_free for "aexceptpubids".

Best Regards,
Takamichi Osumi


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-28 11:31:53
Message-ID: CAA4eK1K6Kr88d2S0zFdHRMyuoaZeNh+ktU+oigmCuD09_x_-+g@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Apr 22, 2022 at 9:39 PM Bharath Rupireddy
<bharath(dot)rupireddyforpostgres(at)gmail(dot)com> wrote:
>
> On Tue, Mar 22, 2022 at 12:39 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > This feature adds an option to skip changes of all tables in specified
> > schema while creating publication.
> > This feature is helpful for use cases where the user wants to
> > subscribe to all the changes except for the changes present in a few
> > schemas.
> > Ex:
> > CREATE PUBLICATION pub1 FOR ALL TABLES SKIP ALL TABLES IN SCHEMA s1,s2;
> > OR
> > ALTER PUBLICATION pub1 ADD SKIP ALL TABLES IN SCHEMA s1,s2;
> >
>
> The feature seems to be useful especially when there are lots of
> schemas in a database. However, I don't quite like the syntax. Do we
> have 'SKIP' identifier in any of the SQL statements in SQL standard?
>

After discussion, it seems EXCEPT is a preferred choice and the same
is used in the other existing syntax as well.

> Can we think of adding skip_schema_list as an option, something like
> below?
>
> CREATE PUBLICATION foo FOR ALL TABLES (skip_schema_list = 's1, s2');
> ALTER PUBLICATION foo SET (skip_schema_list = 's1, s2'); - to set
> ALTER PUBLICATION foo SET (skip_schema_list = ''); - to reset
>

Yeah, that is also an option but it seems it will be difficult to
extend if want to support "all columns except (c1, ..)" for the column
list feature.

The other thing to decide is for which all objects we want to support
EXCEPT clause as it may not be useful for everything as indicated by
Peter E. and Euler. We have seen that Oracle supports "all columns
except (c1, ..)" [1] and MySQL seems to support for tables [2]. I
guess we should restrict ourselves to those two cases for now and then
we can extend it later for schemas if required or people agree. Also,
we should see the syntax we choose here should be extendable.

Another idea that occurred to me today for tables this is as follows:
1. Allow to mention except during create publication ... For All Tables.
CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE t1,t2;
2. Allow to Reset it. This new syntax will reset all objects in the
publications.
Alter Publication ... RESET;
3. Allow to add it to an existing publication
Alter Publication ... Add ALL TABLES [EXCEPT TABLE t1,t2];

I think it can be extended in a similar way for schema syntax as well.

[1] - https://dev.mysql.com/doc/refman/5.7/en/change-replication-filter.html
[2] - https://docs.oracle.com/en/cloud/paas/goldengate-cloud/gwuad/selecting-columns.html#GUID-9A851C8B-48F7-43DF-8D98-D086BE069E20

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Euler Taveira <euler(at)eulerto(dot)com>, Peter Eisentraut <peter(dot)eisentraut(at)enterprisedb(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-04-29 11:42:59
Message-ID: CALDaNm3BRtpcWBj+h3jG_Yzp+0y-CAaenkgcktN26a-ycwQ4DA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Apr 28, 2022 at 4:50 PM osumi(dot)takamichi(at)fujitsu(dot)com
<osumi(dot)takamichi(at)fujitsu(dot)com> wrote:
>
> On Wednesday, April 27, 2022 9:50 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > Thanks for the comments, the attached v3 patch has the changes for the same.
> Hi
>
> Thank you for updating the patch. Several minor comments on v3.
>
> (1) commit message
>
> The new syntax allows specifying schemas. For example:
> CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE t1,t2;
> OR
> ALTER PUBLICATION pub1 ADD EXCEPT TABLE t1,t2;
>
> We have above sentence, but it looks better
> to make the description a bit more accurate.
>
> Kindly change
> From :
> "The new syntax allows specifying schemas"
> To :
> "The new syntax allows specifying excluded relations"
>
> Also, kindly change "OR" to "or",
> because this description is not syntax.

Slightly reworded and modified

> (2) publication_add_relation
>
> @@ -396,6 +400,9 @@ publication_add_relation(Oid pubid, PublicationRelInfo *pri,
> ObjectIdGetDatum(pubid);
> values[Anum_pg_publication_rel_prrelid - 1] =
> ObjectIdGetDatum(relid);
> + values[Anum_pg_publication_rel_prexcept - 1] =
> + BoolGetDatum(pri->except);
> +
>
> /* Add qualifications, if available */
>
> It would be better to remove the blank line,
> because with this change, we'll have two blank
> lines in a row.

Modified

> (3) pg_dump.h & pg_dump_sort.c
>
> @@ -80,6 +80,7 @@ typedef enum
> DO_REFRESH_MATVIEW,
> DO_POLICY,
> DO_PUBLICATION,
> + DO_PUBLICATION_EXCEPT_REL,
> DO_PUBLICATION_REL,
> DO_PUBLICATION_TABLE_IN_SCHEMA,
> DO_SUBSCRIPTION
>
> @@ -90,6 +90,7 @@ enum dbObjectTypePriorities
> PRIO_FK_CONSTRAINT,
> PRIO_POLICY,
> PRIO_PUBLICATION,
> + PRIO_PUBLICATION_EXCEPT_REL,
> PRIO_PUBLICATION_REL,
> PRIO_PUBLICATION_TABLE_IN_SCHEMA,
> PRIO_SUBSCRIPTION,
> @@ -144,6 +145,7 @@ static const int dbObjectTypePriority[] =
> PRIO_REFRESH_MATVIEW, /* DO_REFRESH_MATVIEW */
> PRIO_POLICY, /* DO_POLICY */
> PRIO_PUBLICATION, /* DO_PUBLICATION */
> + PRIO_PUBLICATION_EXCEPT_REL, /* DO_PUBLICATION_EXCEPT_REL */
> PRIO_PUBLICATION_REL, /* DO_PUBLICATION_REL */
> PRIO_PUBLICATION_TABLE_IN_SCHEMA, /* DO_PUBLICATION_TABLE_IN_SCHEMA */
> PRIO_SUBSCRIPTION /* DO_SUBSCRIPTION */
>
> How about having similar order between
> pg_dump.h and pg_dump_sort.c, like
> we'll add DO_PUBLICATION_EXCEPT_REL
> after DO_PUBLICATION_REL in pg_dump.h ?
>

Modified

> (4) GetAllTablesPublicationRelations
>
> + /*
> + * pg_publication_rel and pg_publication_namespace will only have except
> + * tables in case of all tables publication, no need to pass except flag
> + * to get the relations.
> + */
> + List *exceptpubtablelist = GetPublicationRelations(pubid, PUBLICATION_PART_ALL);
> +
>
> There is one unnecessary space in a comment
> "...pg_publication_namespace will only have...". Kindly remove it.
>
> Then, how about diving the variable declaration and
> the insertion of the return value of GetPublicationRelations ?
> That might be aligned with other places in this file.

Modified

> (5) GetTopMostAncestorInPublication
>
>
> @@ -302,8 +303,9 @@ GetTopMostAncestorInPublication(Oid puboid, List *ancestors, int *ancestor_level
> foreach(lc, ancestors)
> {
> Oid ancestor = lfirst_oid(lc);
> - List *apubids = GetRelationPublications(ancestor);
> + List *apubids = GetRelationPublications(ancestor, false);
> List *aschemaPubids = NIL;
> + List *aexceptpubids;
>
> level++;
>
> @@ -317,7 +319,9 @@ GetTopMostAncestorInPublication(Oid puboid, List *ancestors, int *ancestor_level
> else
> {
> aschemaPubids = GetSchemaPublications(get_rel_namespace(ancestor));
> - if (list_member_oid(aschemaPubids, puboid))
> + aexceptpubids = GetRelationPublications(ancestor, true);
> + if (list_member_oid(aschemaPubids, puboid) ||
> + (puballtables && !list_member_oid(aexceptpubids, puboid)))
> {
> topmost_relid = ancestor;
>
> It seems we forgot to call list_free for "aexceptpubids".

Modified

The attached v4 patch has the changes for the same.

Regards,
Vignesh

Attachment Content-Type Size
v4-0001-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch text/x-patch 62.9 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-03 08:54:33
Message-ID: CAHut+PsRvMjCf-wyEwUUSUMMtqh1htkMyrAAZw=VKdBEFwY9LA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Apr 28, 2022 at 9:32 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
...
> Another idea that occurred to me today for tables this is as follows:
> 1. Allow to mention except during create publication ... For All Tables.
> CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE t1,t2;
> 2. Allow to Reset it. This new syntax will reset all objects in the
> publications.
> Alter Publication ... RESET;
> 3. Allow to add it to an existing publication
> Alter Publication ... Add ALL TABLES [EXCEPT TABLE t1,t2];
>
> I think it can be extended in a similar way for schema syntax as well.
>

Consider if the user does
CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE t1,t2;
ALTER PUBLICATION pub1 ADD ALL TABLES EXCEPT t3,t4;

What does it mean?
e.g. Is there only one exception list that is modified? Or did the ADD
ALL TABLES override all meaning of the original list?
e.g. Are we now skipping t1,t2,t3,t4, or are we now only skipping t3,t4?

~~~

Here is a similar example, where the ADD TABLE seems confusing to me
when it intersects with a prior EXCEPT
e.g.
CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT t1,t2; // ok
ALTER PUBLICATION pub1 ADD TABLE t1; ???

What does it mean?
e.g. Does the explicit ADD TABLE override the original exception list?
e.g. Is t1 published now or should that ALTER have caused an error?

~~

It feels like there are too many tricky rules when using EXCEPT with
ALTER PUBLICATION. I guess complexities can be described in the
documentation but IMO it would be better if the ALTER syntax could be
unambiguous in the first place. So perhaps the rules should be more
restrictive (e.g. just disallow ALTER ... ADD any table that overlaps
the existing EXCEPT list ??)

------
Kind Regards,
Peter Smith.
Fujitsu Australia.


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-04 04:14:53
Message-ID: CAA4eK1KhNt2f2Pgj_PWy1pvpRyrvw7kNv+RP1Q6n=+hD8X=2QQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, May 3, 2022 at 2:24 PM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> On Thu, Apr 28, 2022 at 9:32 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> ...
> > Another idea that occurred to me today for tables this is as follows:
> > 1. Allow to mention except during create publication ... For All Tables.
> > CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE t1,t2;
> > 2. Allow to Reset it. This new syntax will reset all objects in the
> > publications.
> > Alter Publication ... RESET;
> > 3. Allow to add it to an existing publication
> > Alter Publication ... Add ALL TABLES [EXCEPT TABLE t1,t2];
> >
> > I think it can be extended in a similar way for schema syntax as well.
> >
>
> Consider if the user does
> CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE t1,t2;
> ALTER PUBLICATION pub1 ADD ALL TABLES EXCEPT t3,t4;
>
> What does it mean?
> e.g. Is there only one exception list that is modified? Or did the ADD
> ALL TABLES override all meaning of the original list?
> e.g. Are we now skipping t1,t2,t3,t4, or are we now only skipping t3,t4?
>

This won't be allowed. We won't allow changing ALL TABLES publication
unless the user first performs RESET. This is the purpose of providing
the RESET variant.

> ~~~
>
> Here is a similar example, where the ADD TABLE seems confusing to me
> when it intersects with a prior EXCEPT
> e.g.
> CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT t1,t2; // ok
> ALTER PUBLICATION pub1 ADD TABLE t1; ???
>
> What does it mean?
> e.g. Does the explicit ADD TABLE override the original exception list?
> e.g. Is t1 published now or should that ALTER have caused an error?
>

This won't be allowed either. We don't allow to Add/Drop from All
Tables publication unless the user performs a RESET. This is true even
today except that we don't have a RESET syntax.

> ~~
>
> It feels like there are too many tricky rules when using EXCEPT with
> ALTER PUBLICATION. I guess complexities can be described in the
> documentation but IMO it would be better if the ALTER syntax could be
> unambiguous in the first place.
>

Agreed.

> So perhaps the rules should be more
> restrictive (e.g. just disallow ALTER ... ADD any table that overlaps
> the existing EXCEPT list ??)
>

I think the current proposal seems to be restrictive enough to avoid
any tricky issues. Do you see any other problem?

--
With Regards,
Amit Kapila.


From: Peter Eisentraut <peter(dot)eisentraut(at)enterprisedb(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-04 13:34:54
Message-ID: 4f4867da-f581-0330-974f-da9031ac3e1c@enterprisedb.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On 14.04.22 15:47, Peter Eisentraut wrote:
> That said, I'm not sure this feature is worth the trouble.  If this is
> useful, what about "whole database except these schemas"?  What about
> "create this database from this template except these schemas".  This
> could get out of hand.  I think we should encourage users to group their
> object the way they want and not offer these complicated negative
> selection mechanisms.

Another problem in general with this "all except these" way of
specifying things is that you need to track negative dependencies.

For example, assume you can't add a table to a publication unless it has
a replica identity. Now, if you have a publication p1 that says
includes "all tables except t1", you now have to check p1 whenever a new
table is created, even though the new table has no direct dependency
link with p1. So in more general cases, you would have to check all
existing objects to see whether their specification is in conflict with
the new object being created.

Now publications don't actually work that way, so it's not a real
problem right now, but similar things could work like that. So I think
it's worth thinking this through a bit.


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Peter Eisentraut <peter(dot)eisentraut(at)enterprisedb(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-05 03:50:36
Message-ID: CAA4eK1K=9wJGfN0b0CghP1phh7DTb-FXO1zQwWEF3o0G_JFj=A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, May 4, 2022 at 7:05 PM Peter Eisentraut
<peter(dot)eisentraut(at)enterprisedb(dot)com> wrote:
>
> On 14.04.22 15:47, Peter Eisentraut wrote:
> > That said, I'm not sure this feature is worth the trouble. If this is
> > useful, what about "whole database except these schemas"? What about
> > "create this database from this template except these schemas". This
> > could get out of hand. I think we should encourage users to group their
> > object the way they want and not offer these complicated negative
> > selection mechanisms.
>
> Another problem in general with this "all except these" way of
> specifying things is that you need to track negative dependencies.
>
> For example, assume you can't add a table to a publication unless it has
> a replica identity. Now, if you have a publication p1 that says
> includes "all tables except t1", you now have to check p1 whenever a new
> table is created, even though the new table has no direct dependency
> link with p1. So in more general cases, you would have to check all
> existing objects to see whether their specification is in conflict with
> the new object being created.
>

Yes, I think we should avoid adding such negative dependencies. We
have carefully avoided such dependencies during row filter, column
list work where we don't try to perform DDL time verification.
However, it is not clear to me how this proposal is related to this
example or in general about tracking negative dependencies? AFAIR, we
currently have such a check while changing persistence of logged table
(logged to unlogged, see ATPrepChangePersistence) where we cannot
allow changing persistence if that relation is part of some
publication. But as per my understanding, this feature shouldn't add
any such new dependencies. I agree that we have to ensure that
existing checks shouldn't break due to this feature.

> Now publications don't actually work that way, so it's not a real
> problem right now, but similar things could work like that. So I think
> it's worth thinking this through a bit.
>

This is a good point and I agree that we should be careful to not add
some new negative dependencies unless it is really required but I
can't see how this proposal will make it more prone to such checks.

--
With Regards,
Amit Kapila.


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Peter Eisentraut <peter(dot)eisentraut(at)enterprisedb(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-05 04:12:32
Message-ID: CAA4eK1Jsb6mRyxyBgkxibPT6D2e7=L1T-Tge723_10z7BH2Qiw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, May 5, 2022 at 9:20 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Wed, May 4, 2022 at 7:05 PM Peter Eisentraut
> <peter(dot)eisentraut(at)enterprisedb(dot)com> wrote:
> >
> > On 14.04.22 15:47, Peter Eisentraut wrote:
> > > That said, I'm not sure this feature is worth the trouble. If this is
> > > useful, what about "whole database except these schemas"? What about
> > > "create this database from this template except these schemas". This
> > > could get out of hand. I think we should encourage users to group their
> > > object the way they want and not offer these complicated negative
> > > selection mechanisms.
> >
> > Another problem in general with this "all except these" way of
> > specifying things is that you need to track negative dependencies.
> >
> > For example, assume you can't add a table to a publication unless it has
> > a replica identity. Now, if you have a publication p1 that says
> > includes "all tables except t1", you now have to check p1 whenever a new
> > table is created, even though the new table has no direct dependency
> > link with p1. So in more general cases, you would have to check all
> > existing objects to see whether their specification is in conflict with
> > the new object being created.
> >
>
> Yes, I think we should avoid adding such negative dependencies. We
> have carefully avoided such dependencies during row filter, column
> list work where we don't try to perform DDL time verification.
> However, it is not clear to me how this proposal is related to this
> example or in general about tracking negative dependencies?
>

I mean to say that even if we have such a restriction, it would apply
to "for all tables" or other publications as well. In your example,
consider one wants to Alter a table and remove its replica identity,
we have to check whether the table is part of any publication similar
to what we are doing for relation persistence in
ATPrepChangePersistence.

> AFAIR, we
> currently have such a check while changing persistence of logged table
> (logged to unlogged, see ATPrepChangePersistence) where we cannot
> allow changing persistence if that relation is part of some
> publication. But as per my understanding, this feature shouldn't add
> any such new dependencies. I agree that we have to ensure that
> existing checks shouldn't break due to this feature.
>
> > Now publications don't actually work that way, so it's not a real
> > problem right now, but similar things could work like that. So I think
> > it's worth thinking this through a bit.
> >
>
> This is a good point and I agree that we should be careful to not add
> some new negative dependencies unless it is really required but I
> can't see how this proposal will make it more prone to such checks.
>

--
With Regards,
Amit Kapila.


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-06 02:35:16
Message-ID: CAHut+PsvC-NezO3MJkdyEz=G1QRje2LntjwhQiEeVbmhOQuBMA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Apr 28, 2022 at 9:32 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
...
>
> Another idea that occurred to me today for tables this is as follows:
> 1. Allow to mention except during create publication ... For All Tables.
> CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE t1,t2;
> 2. Allow to Reset it. This new syntax will reset all objects in the
> publications.
> Alter Publication ... RESET;
> 3. Allow to add it to an existing publication
> Alter Publication ... Add ALL TABLES [EXCEPT TABLE t1,t2];
>
> I think it can be extended in a similar way for schema syntax as well.
>

If the proposed syntax ALTER PUBLICATION ... RESET will reset all the
objects in the publication then there still seems simple way to remove
only the EXCEPT list but leave everything else intact. IIUC to clear
just the EXCEPT list would require a 2 step process - 1) ALTER ...
RESET then 2) ALTER ... ADD ALL TABLES again.

I was wondering if it might be useful to have a variation that *only*
resets the EXCEPT list, but still leaves everything else as-is?

So, instead of:
ALTER PUBLICATION pubname RESET

use a syntax something like:
ALTER PUBLICATION pubname RESET {ALL | EXCEPT}
or
ALTER PUBLICATION pubname RESET [EXCEPT]

------
Kind Regards,
Peter Smith.
Fujitsu Australia


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-10 03:38:48
Message-ID: CALDaNm18VH2j8cTqfELHQ=0ZNognbGBhbHPteJenWQC6C2dueQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, May 6, 2022 at 8:05 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> On Thu, Apr 28, 2022 at 9:32 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> ...
> >
> > Another idea that occurred to me today for tables this is as follows:
> > 1. Allow to mention except during create publication ... For All Tables.
> > CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE t1,t2;
> > 2. Allow to Reset it. This new syntax will reset all objects in the
> > publications.
> > Alter Publication ... RESET;
> > 3. Allow to add it to an existing publication
> > Alter Publication ... Add ALL TABLES [EXCEPT TABLE t1,t2];
> >
> > I think it can be extended in a similar way for schema syntax as well.
> >
>
> If the proposed syntax ALTER PUBLICATION ... RESET will reset all the
> objects in the publication then there still seems simple way to remove
> only the EXCEPT list but leave everything else intact. IIUC to clear
> just the EXCEPT list would require a 2 step process - 1) ALTER ...
> RESET then 2) ALTER ... ADD ALL TABLES again.
>
> I was wondering if it might be useful to have a variation that *only*
> resets the EXCEPT list, but still leaves everything else as-is?
>
> So, instead of:
> ALTER PUBLICATION pubname RESET

+1 for this syntax as this syntax can be extendable to include options
like (except/all/etc) later.
Currently we can support this syntax and can be extended later based
on the requirements.

The new feature will handle the various use cases based on the
behavior given below:
-- CREATE Publication with EXCEPT TABLE syntax
CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE t1,t2; -- ok
Alter Publication pub1 RESET;
-- All Tables and options are reset similar to creating publication
without any publication object and publication option (create
publication pub1)
\dRp+ pub1
Publication pub2
Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
---------+------------+---------+---------+---------+-----------+----------
vignesh | f | t | t | t | t | f
(1 row)

-- Can add except table after reset of publication
ALTER PUBLICATION pub1 Add ALL TABLES EXCEPT TABLE t1,t2; -- ok

-- Cannot add except table without reset of publication
ALTER PUBLICATION pub1 Add EXCEPT TABLE t3,t4; -- not ok, need to be reset

Alter Publication pub1 RESET;
-- Cannot add table to ALL TABLES Publication
ALTER PUBLICATION pub1 Add ALL TABLES EXCEPT TABLE t1,t2, t3, t4,
TABLE t5; -- not ok, ALL TABLES Publications does not support
including of TABLES

Alter Publication pub1 RESET;
-- Cannot add table to ALL TABLES Publication
ALTER PUBLICATION pub1 Add ALL TABLES TABLE t1,t2; -- not ok, ALL
TABLES Publications does not support including of TABLES

-- Cannot add ALL TABLES IN SCHEMA to ALL TABLES Publication
ALTER PUBLICATION pub1 Add ALL TABLES ALL TABLES IN SCHEMA sch1, sch2;
-- not ok, ALL TABLES Publications does not support including of ALL
TABLES IN SCHEMA

-- Existing syntax should work as it is
CREATE PUBLICATION pub1 FOR TABLE t1;
ALTER PUBLICATION pub1 ADD TABLE t1; -- ok, existing ALTER should work
as it is (ok without reset)
ALTER PUBLICATION pub1 ADD ALL TABLES IN SCHEMA sch1; -- ok, existing
ALTER should work as it is (ok without reset)
ALTER PUBLICATION pub1 DROP TABLE t1; -- ok, existing ALTER should
work as it is (ok without reset)
ALTER PUBLICATION pub1 DROP ALL TABLES IN SCHEMA sch1; -- ok, existing
ALTER should work as it is (ok without reset)
ALTER PUBLICATION pub1 SET TABLE t1; -- ok, existing ALTER should work
as it is (ok without reset)
ALTER PUBLICATION pub1 SET ALL TABLES IN SCHEMA sch1; -- ok, existing
ALTER should work as it is (ok without reset)

I will modify the patch to handle this.

Regards,
Vignesh


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-12 04:24:39
Message-ID: CALDaNm0k_0Ccj47wzJzzPFwgQB7w=R5+Q2_nSqYrmMmjhmcRUw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, May 10, 2022 at 9:08 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Fri, May 6, 2022 at 8:05 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >
> > On Thu, Apr 28, 2022 at 9:32 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> > >
> > ...
> > >
> > > Another idea that occurred to me today for tables this is as follows:
> > > 1. Allow to mention except during create publication ... For All Tables.
> > > CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE t1,t2;
> > > 2. Allow to Reset it. This new syntax will reset all objects in the
> > > publications.
> > > Alter Publication ... RESET;
> > > 3. Allow to add it to an existing publication
> > > Alter Publication ... Add ALL TABLES [EXCEPT TABLE t1,t2];
> > >
> > > I think it can be extended in a similar way for schema syntax as well.
> > >
> >
> > If the proposed syntax ALTER PUBLICATION ... RESET will reset all the
> > objects in the publication then there still seems simple way to remove
> > only the EXCEPT list but leave everything else intact. IIUC to clear
> > just the EXCEPT list would require a 2 step process - 1) ALTER ...
> > RESET then 2) ALTER ... ADD ALL TABLES again.
> >
> > I was wondering if it might be useful to have a variation that *only*
> > resets the EXCEPT list, but still leaves everything else as-is?
> >
> > So, instead of:
> > ALTER PUBLICATION pubname RESET
>
> +1 for this syntax as this syntax can be extendable to include options
> like (except/all/etc) later.
> Currently we can support this syntax and can be extended later based
> on the requirements.

The attached patch has the implementation for "ALTER PUBLICATION
pubname RESET". This command will reset the publication to default
state which includes resetting the publication options, setting ALL
TABLES option to false and dropping the relations and schemas that are
associated with the publication.

Regards,
Vignesh

Attachment Content-Type Size
v1-0001-Add-RESET-option-to-Alter-Publication-which-will-.patch text/x-patch 15.0 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-13 04:07:17
Message-ID: CAHut+Pv_0DwyWoGQNMF+G2AGqMuJTzWQKRtmxaC+=zLTPL-Zkw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, May 12, 2022 at 2:24 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
...
> The attached patch has the implementation for "ALTER PUBLICATION
> pubname RESET". This command will reset the publication to default
> state which includes resetting the publication options, setting ALL
> TABLES option to false and dropping the relations and schemas that are
> associated with the publication.
>

Please see below my review comments for the v1-0001 (RESET) patch

======

1. Commit message

This patch adds a new RESET option to ALTER PUBLICATION which

Wording: "RESET option" -> "RESET clause"

~~~

2. doc/src/sgml/ref/alter_publication.sgml

+ <para>
+ The <literal>RESET</literal> clause will reset the publication to default
+ state which includes resetting the publication options, setting
+ <literal>ALL TABLES</literal> option to <literal>false</literal>
and drop the
+ relations and schemas that are associated with the publication.
</para>

2a. Wording: "to default state" -> "to the default state"

2b. Wording: "and drop the relations..." -> "and dropping all relations..."

~~~

3. doc/src/sgml/ref/alter_publication.sgml

+ invoking user to be a superuser. <literal>RESET</literal> of publication
+ requires invoking user to be a superuser. To alter the owner, you must also

Wording: "requires invoking user" -> "requires the invoking user"

~~~

4. doc/src/sgml/ref/alter_publication.sgml - Example

@@ -207,6 +220,12 @@ ALTER PUBLICATION sales_publication ADD ALL
TABLES IN SCHEMA marketing, sales;
<structname>production_publication</structname>:
<programlisting>
ALTER PUBLICATION production_publication ADD TABLE users,
departments, ALL TABLES IN SCHEMA production;
+</programlisting></para>
+
+ <para>
+ Resetting the publication <structname>production_publication</structname>:
+<programlisting>
+ALTER PUBLICATION production_publication RESET;

Wording: "Resetting the publication" -> "Reset the publication"

~~~

5. src/backend/commands/publicationcmds.c

+ /* Check and reset the options */

IMO the code can just reset all these options unconditionally. I did
not see the point to check for existing option values first. I feel
the simpler code outweighs any negligible performance difference in
this case.

~~~

6. src/backend/commands/publicationcmds.c

+ /* Check and reset the options */

Somehow it seemed a pity having to hardcode all these default values
true/false in multiple places; e.g. the same is already hardcoded in
the parse_publication_options function.

To avoid multiple hard coded bools you could just call the
parse_publication_options with an empty options list. That would set
the defaults which you can then use:
values[Anum_pg_publication_pubinsert - 1] = BoolGetDatum(pubactiondefs->insert);

Alternatively, maybe there should be #defines to use instead of having
the scattered hardcoded bool defaults:
#define PUBACTION_DEFAULT_INSERT true
#define PUBACTION_DEFAULT_UPDATE true
etc

~~~

7. src/include/nodes/parsenodes.h

@@ -4033,7 +4033,8 @@ typedef enum AlterPublicationAction
{
AP_AddObjects, /* add objects to publication */
AP_DropObjects, /* remove objects from publication */
- AP_SetObjects /* set list of objects */
+ AP_SetObjects, /* set list of objects */
+ AP_ReSetPublication /* reset the publication */
} AlterPublicationAction;

Unusual case: "AP_ReSetPublication" -> "AP_ResetPublication"

~~~

8. src/test/regress/sql/publication.sql

8a.
+-- Test for RESET PUBLICATION
SUGGESTED
+-- Tests for ALTER PUBLICATION ... RESET

8b.
+-- Verify that 'ALL TABLES' option is reset
SUGGESTED:
+-- Verify that 'ALL TABLES' flag is reset

8c.
+-- Verify that publish option and publish via root option is reset
SUGGESTED:
+-- Verify that publish options and publish_via_partition_root option are reset

8d.
+-- Verify that only superuser can execute RESET publication
SUGGESTED
+-- Verify that only superuser can reset a publication

------
Kind Regards,
Peter Smith.
Fujitsu Australia


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-14 13:32:54
Message-ID: CALDaNm2-GJt2HsYTkLqQ=ecm=R-vOBw1=aM_d2EiYbz39x_cTQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, May 13, 2022 at 9:37 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> On Thu, May 12, 2022 at 2:24 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> ...
> > The attached patch has the implementation for "ALTER PUBLICATION
> > pubname RESET". This command will reset the publication to default
> > state which includes resetting the publication options, setting ALL
> > TABLES option to false and dropping the relations and schemas that are
> > associated with the publication.
> >
>
> Please see below my review comments for the v1-0001 (RESET) patch
>
> ======
>
> 1. Commit message
>
> This patch adds a new RESET option to ALTER PUBLICATION which
>
> Wording: "RESET option" -> "RESET clause"

Modified

> ~~~
>
> 2. doc/src/sgml/ref/alter_publication.sgml
>
> + <para>
> + The <literal>RESET</literal> clause will reset the publication to default
> + state which includes resetting the publication options, setting
> + <literal>ALL TABLES</literal> option to <literal>false</literal>
> and drop the
> + relations and schemas that are associated with the publication.
> </para>
>
> 2a. Wording: "to default state" -> "to the default state"

Modified

> 2b. Wording: "and drop the relations..." -> "and dropping all relations..."

Modified

> ~~~
>
> 3. doc/src/sgml/ref/alter_publication.sgml
>
> + invoking user to be a superuser. <literal>RESET</literal> of publication
> + requires invoking user to be a superuser. To alter the owner, you must also
>
> Wording: "requires invoking user" -> "requires the invoking user"

Modified

> ~~~
>
> 4. doc/src/sgml/ref/alter_publication.sgml - Example
>
> @@ -207,6 +220,12 @@ ALTER PUBLICATION sales_publication ADD ALL
> TABLES IN SCHEMA marketing, sales;
> <structname>production_publication</structname>:
> <programlisting>
> ALTER PUBLICATION production_publication ADD TABLE users,
> departments, ALL TABLES IN SCHEMA production;
> +</programlisting></para>
> +
> + <para>
> + Resetting the publication <structname>production_publication</structname>:
> +<programlisting>
> +ALTER PUBLICATION production_publication RESET;
>
> Wording: "Resetting the publication" -> "Reset the publication"

Modified

> ~~~
>
> 5. src/backend/commands/publicationcmds.c
>
> + /* Check and reset the options */
>
> IMO the code can just reset all these options unconditionally. I did
> not see the point to check for existing option values first. I feel
> the simpler code outweighs any negligible performance difference in
> this case.

Modified

> ~~~
>
> 6. src/backend/commands/publicationcmds.c
>
> + /* Check and reset the options */
>
> Somehow it seemed a pity having to hardcode all these default values
> true/false in multiple places; e.g. the same is already hardcoded in
> the parse_publication_options function.
>
> To avoid multiple hard coded bools you could just call the
> parse_publication_options with an empty options list. That would set
> the defaults which you can then use:
> values[Anum_pg_publication_pubinsert - 1] = BoolGetDatum(pubactiondefs->insert);
>
> Alternatively, maybe there should be #defines to use instead of having
> the scattered hardcoded bool defaults:
> #define PUBACTION_DEFAULT_INSERT true
> #define PUBACTION_DEFAULT_UPDATE true
> etc

I have used #define for default value and used it in both the functions.

> ~~~
>
> 7. src/include/nodes/parsenodes.h
>
> @@ -4033,7 +4033,8 @@ typedef enum AlterPublicationAction
> {
> AP_AddObjects, /* add objects to publication */
> AP_DropObjects, /* remove objects from publication */
> - AP_SetObjects /* set list of objects */
> + AP_SetObjects, /* set list of objects */
> + AP_ReSetPublication /* reset the publication */
> } AlterPublicationAction;
>
> Unusual case: "AP_ReSetPublication" -> "AP_ResetPublication"

Modified

> ~~~
>
> 8. src/test/regress/sql/publication.sql
>
> 8a.
> +-- Test for RESET PUBLICATION
> SUGGESTED
> +-- Tests for ALTER PUBLICATION ... RESET

Modified

> 8b.
> +-- Verify that 'ALL TABLES' option is reset
> SUGGESTED:
> +-- Verify that 'ALL TABLES' flag is reset

Modified

> 8c.
> +-- Verify that publish option and publish via root option is reset
> SUGGESTED:
> +-- Verify that publish options and publish_via_partition_root option are reset

Modified

> 8d.
> +-- Verify that only superuser can execute RESET publication
> SUGGESTED
> +-- Verify that only superuser can reset a publication

Modified

Thanks for the comments, the attached v5 patch has the changes for the
same. Also I have made the changes for SKIP Table based on the new
syntax, the changes for the same are available in
v5-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch.

Regards,
Vignesh

Attachment Content-Type Size
v5-0001-Add-RESET-clause-to-Alter-Publication-which-will-.patch text/x-patch 16.2 KB
v5-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch text/x-patch 63.6 KB

From: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>
To: 'vignesh C' <vignesh21(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Skipping schema changes in publication
Date: 2022-05-16 03:02:26
Message-ID: TYCPR01MB8373C3120C2B3112001ED6F1EDCF9@TYCPR01MB8373.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Saturday, May 14, 2022 10:33 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> Thanks for the comments, the attached v5 patch has the changes for the same.
> Also I have made the changes for SKIP Table based on the new syntax, the
> changes for the same are available in
> v5-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch.
Hi,

Thank you for updating the patch.
I'll share few minor review comments on v5-0001.

(1) doc/src/sgml/ref/alter_publication.sgml

@@ -73,12 +85,13 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
Adding a table to a publication additionally requires owning that table.
The <literal>ADD ALL TABLES IN SCHEMA</literal> and
<literal>SET ALL TABLES IN SCHEMA</literal> to a publication requires the
- invoking user to be a superuser. To alter the owner, you must also be a
- direct or indirect member of the new owning role. The new owner must have
- <literal>CREATE</literal> privilege on the database. Also, the new owner
- of a <literal>FOR ALL TABLES</literal> or <literal>FOR ALL TABLES IN
- SCHEMA</literal> publication must be a superuser. However, a superuser can
- change the ownership of a publication regardless of these restrictions.
+ invoking user to be a superuser. <literal>RESET</literal> of publication
+ requires the invoking user to be a superuser. To alter the owner, you must
...

I suggest to combine the first part of your change with one existing sentence
before your change, to make our description concise.

FROM:
"The <literal>ADD ALL TABLES IN SCHEMA</literal> and
<literal>SET ALL TABLES IN SCHEMA</literal> to a publication requires the
invoking user to be a superuser. <literal>RESET</literal> of publication
requires the invoking user to be a superuser."

TO:
"The <literal>ADD ALL TABLES IN SCHEMA</literal>,
<literal>SET ALL TABLES IN SCHEMA</literal> to a publication and
<literal>RESET</literal> of publication requires the invoking user to be a superuser."

(2) typo

+++ b/src/backend/commands/publicationcmds.c
@@ -53,6 +53,13 @@
#include "utils/syscache.h"
#include "utils/varlena.h"

+#define PUB_ATION_INSERT_DEFAULT true
+#define PUB_ACTION_UPDATE_DEFAULT true

Kindly change
FROM:
"PUB_ATION_INSERT_DEFAULT"
TO:
"PUB_ACTION_INSERT_DEFAULT"

(3) src/test/regress/expected/publication.out

+-- Verify that only superuser can reset a publication
+ALTER PUBLICATION testpub_reset OWNER TO regress_publication_user2;
+SET ROLE regress_publication_user2;
+ALTER PUBLICATION testpub_reset RESET; -- fail

We have "-- fail" for one case in this patch.
On the other hand, isn't better to add "-- ok" (or "-- success") for
other successful statements,
when we consider the entire tests description consistency ?

Best Regards,
Takamichi Osumi


From: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>
To: 'vignesh C' <vignesh21(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Skipping schema changes in publication
Date: 2022-05-16 08:29:58
Message-ID: TYCPR01MB83737C28187A6E0BADAE98F0EDCF9@TYCPR01MB8373.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Saturday, May 14, 2022 10:33 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> Thanks for the comments, the attached v5 patch has the changes for the same.
> Also I have made the changes for SKIP Table based on the new syntax, the
> changes for the same are available in
> v5-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch.
Hi,

Several comments on v5-0002.

(1) One unnecessary space before "except_pub_obj_list" syntax definition

+ except_pub_obj_list: ExceptPublicationObjSpec
+ { $$ = list_make1($1); }
+ | except_pub_obj_list ',' ExceptPublicationObjSpec
+ { $$ = lappend($1, $3); }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+

From above part, kindly change
FROM:
" except_pub_obj_list: ExceptPublicationObjSpec"
TO:
"except_pub_obj_list: ExceptPublicationObjSpec"

(2) doc/src/sgml/ref/create_publication.sgml

(2-1)

@@ -22,7 +22,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
- [ FOR ALL TABLES
+ [ FOR ALL TABLES [EXCEPT TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [, ... ]]
| FOR <replaceable class="parameter">publication_object</replaceable> [, ... ] ]
[ WITH ( <replaceable class="parameter">publication_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] ) ]

Here I think we need to add two more whitespaces around square brackets.
Please change
FROM:
"[ FOR ALL TABLES [EXCEPT TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [, ... ]]"
TO:
"[ FOR ALL TABLES [ EXCEPT TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [, ... ] ]"

When I check other documentations, I see whitespaces before/after square brackets.

(2-2)
This whitespace alignment applies to alter_publication.sgml as well.

(3)

@@ -156,6 +156,24 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
</listitem>
</varlistentry>

+
+ <varlistentry>
+ <term><literal>EXCEPT TABLE</literal></term>
+ <listitem>
+ <para>
+ Marks the publication as one that excludes replicating changes for the
+ specified tables.
+ </para>
+
+ <para>
+ <literal>EXCEPT TABLE</literal> can be specified only for
+ <literal>FOR ALL TABLES</literal> publication. It is not supported for
+ <literal>FOR ALL TABLES IN SCHEMA </literal> publication and
+ <literal>FOR TABLE</literal> publication.
+ </para>
+ </listitem>
+ </varlistentry>
+

This EXCEPT TABLE clause is only for FOR ALL TABLES.
So, how about extracting the main message from above part and
moving it to an exising paragraph below, instead of having one independent paragraph ?

<varlistentry>
<term><literal>FOR ALL TABLES</literal></term>
<listitem>
<para>
Marks the publication as one that replicates changes for all tables in
the database, including tables created in the future.
</para>
</listitem>
</varlistentry>

Something like
"Marks the publication as one that replicates changes for all tables in
the database, including tables created in the future. EXCEPT TABLE indicates
excluded tables for the defined publication.
"

(4) One minor confirmation about the syntax

Currently, we allow one way of writing to indicate excluded tables like below.

(example) CREATE PUBLICATION mypub FOR ALL TABLES EXCEPT TABLE tab3, tab4, EXCEPT TABLE tab5;

This is because we define ExceptPublicationObjSpec with EXCEPT TABLE.
Is it OK to have a room to write duplicate "EXCEPT TABLE" clauses ?
I think there is no harm in having this,
but I'd like to confirm whether this syntax might be better to be adjusted or not.

(5) CheckAlterPublication

+
+ if (excepttable && !stmt->for_all_tables)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("publication \"%s\" is not defined as FOR ALL TABLES",
+ NameStr(pubform->pubname)),
+ errdetail("except table cannot be added to, dropped from, or set on NON ALL TABLES publications.")));

Could you please add a test for this ?

Best Regards,
Takamichi Osumi


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-16 09:23:14
Message-ID: CAHut+PtskkbsV6h=9jNF4zoeWFK0L3vWAWjmmGdbR6FYkecVzA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Below are my review comments for v5-0001.

There is some overlap with comments recently posted by Osumi-san [1].

(I also have review comments for v5-0002; will post them tomorrow)

======

1. Commit message

This patch adds a new RESET clause to ALTER PUBLICATION which will reset
the publication to default state which includes resetting the publication
options, setting ALL TABLES option to false and dropping the relations and
schemas that are associated with the publication.

SUGGEST
"to default state" -> "to the default state"
"ALL TABLES option" -> "ALL TABLES flag"

~~~

2. doc/src/sgml/ref/alter_publication.sgml

+ <para>
+ The <literal>RESET</literal> clause will reset the publication to the
+ default state which includes resetting the publication options, setting
+ <literal>ALL TABLES</literal> option to <literal>false</literal> and
+ dropping all relations and schemas that are associated with the publication.
</para>

"ALL TABLES option" -> "ALL TABLES flag"

~~~

3. doc/src/sgml/ref/alter_publication.sgml

+ invoking user to be a superuser. <literal>RESET</literal> of publication
+ requires the invoking user to be a superuser. To alter the owner, you must

SUGGESTION
To <literal>RESET</literal> a publication requires the invoking user
to be a superuser.

~~~

4. src/backend/commands/publicationcmds.c

@@ -53,6 +53,13 @@
#include "utils/syscache.h"
#include "utils/varlena.h"

+#define PUB_ATION_INSERT_DEFAULT true
+#define PUB_ACTION_UPDATE_DEFAULT true
+#define PUB_ACTION_DELETE_DEFAULT true
+#define PUB_ACTION_TRUNCATE_DEFAULT true
+#define PUB_VIA_ROOT_DEFAULT false
+#define PUB_ALL_TABLES_DEFAULT false

4a.
Typo: "ATION" -> "ACTION"

4b.
I think these #defines deserve a 1 line comment.
e.g.
/* CREATE PUBLICATION default values for flags and options */

4c.
Since the "_DEFAULT" is a common part of all the names, maybe it is
tidier if it comes first.
e.g.
#define PUB_DEFAULT_ACTION_INSERT true
#define PUB_DEFAULT_ACTION_UPDATE true
#define PUB_DEFAULT_ACTION_DELETE true
#define PUB_DEFAULT_ACTION_TRUNCATE true
#define PUB_DEFAULT_VIA_ROOT false
#define PUB_DEFAULT_ALL_TABLES false

------
[1] https://www.postgresql.org/message-id/TYCPR01MB8373C3120C2B3112001ED6F1EDCF9%40TYCPR01MB8373.jpnprd01.prod.outlook.com

Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-17 02:04:57
Message-ID: CAHut+PtrtNu-YsBCk3ZySENBHtiwYw=Xqn86gdPAzd0AhfXOZg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Below are my review comments for v5-0002.

There may be an overlap with comments recently posted by Osumi-san [1].

(I also have review comments for v5-0002; will post them tomorrow)

======

1. General

Is it really necessary to have to say "EXCEPT TABLE" instead of just
"EXCEPT". It seems unnecessarily verbose and redundant when you write
"FOR ALL TABLES EXCEPT TABLE...".

If you want to keep this TABLE keyword (maybe you have plans for other
kinds of except?) then IMO perhaps at least it can be the optional
default except type. e.g. EXCEPT [TABLE].

~~~

2. General

(I was unsure whether to even mention this one).

I understand the "EXCEPT" is chosen as the user-facing syntax, but it
still seems strange when reading the patch to see attribute members
and column names called 'except'. I think the problem is that "except"
is not a verb, so saying except=t/f just does not make much sense.
Sometimes I feel that for all the internal usage
(code/comments/catalog) using "skip" and "skip-list" etc would be a
much better choice of names. OTOH I can see that having consistency
with the outside syntax might also be good. Anyway, please consider -
maybe other people feel the same?

~~~

3. General

The ONLY keyword seems supported by the syntax for tables of the
except-list (more on this in later comments) but:
a) I am not sure if the patch code is accounting for that, and
b) There are no test cases using ONLY.

~~~

4. Commit message

A new option "EXCEPT TABLE" in Create/Alter Publication allows
one or more tables to be excluded, publisher will exclude sending the data
of the excluded tables to the subscriber.

SUGGESTION
A new "EXCEPT TABLE" clause for CREATE/ALTER PUBLICATION allows one or
more tables to be excluded. The publisher will not send the data of
excluded tables to the subscriber.

~~

5. Commit message

The new syntax allows specifying exclude relations while creating a publication
or exclude relations in alter publication. For example:

SUGGESTION
The new syntax allows specifying excluded relations when creating or
altering a publication. For example:

~~~

6. Commit message

A new column prexcept is added to table "pg_publication_rel", to maintain
the relations that the user wants to exclude publishing through the publication.

SUGGESTION
A new column "prexcept" is added to table "pg_publication_rel", to
maintain the relations that the user wants to exclude from the
publications.

~~~

7. Commit message

Modified the output plugin (pgoutput) to exclude publishing the changes of the
excluded tables.

I did not feel it was necessary to say this. It is already said above
that the data is not sent, so that seems enough.

~~~

8. Commit message

Updates pg_dump to identify and dump the excluded tables of the publications.
Updates the \d family of commands to display excluded tables of the
publications and \dRp+ variant will now display associated except tables if any.

SUGGESTION
pg_dump is updated to identify and dump the excluded tables of the publications.

The psql \d family of commands to display excluded tables. e.g. psql
\dRp+ variant will now display associated "except tables" if any.

~~~

9. doc/src/sgml/catalogs.sgml

@@ -6426,6 +6426,15 @@ SCRAM-SHA-256$<replaceable>&lt;iteration
count&gt;</replaceable>:<replaceable>&l
if there is no publication qualifying condition.</para></entry>
</row>

+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>prexcept</structfield> <type>bool</type>
+ </para>
+ <para>
+ True if the table must be excluded
+ </para></entry>
+ </row>

Other descriptions on this page refer to "relation" instead of
"table". Probably this should do the same to be consistent.

~~~

10. doc/src/sgml/logical-replication.sgml

@@ -1167,8 +1167,9 @@ CONTEXT: processing remote data for replication
origin "pg_16395" during "INSER
<para>
To add tables to a publication, the user must have ownership rights on the
table. To add all tables in schema to a publication, the user must be a
- superuser. To create a publication that publishes all tables or
all tables in
- schema automatically, the user must be a superuser.
+ superuser. To add all tables to a publication, the user must be a superuser.
+ To create a publication that publishes all tables or all tables in schema
+ automatically, the user must be a superuser.
</para>

It seems like a valid change but how is this related to this EXCEPT
patch. Maybe this fix should be patched separately?

~~~

11. doc/src/sgml/ref/alter_publication.sgml

@@ -22,6 +22,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
ADD <replaceable class="parameter">publication_object</replaceable> [,
...]
+ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
ADD ALL TABLES [EXCEPT TABLE [ ONLY ] <replaceable
class="parameter">table_name</replaceable> [ * ] [, ... ]]

The [ONLY] looks misplaced when the syntax is described like this. For
example, in practice it is possible to write "EXCEPT TABLE ONLY t1,
ONLY t2, t3, ONLY t4" but it doesn't seem that way by looking at these
PG DOCS.

IMO would be better described like this:

[ FOR ALL TABLES [ EXCEPT TABLE exception_object [,...] ]]

where exception_object is:

[ ONLY ] table_name [ * ]

~~~

12. doc/src/sgml/ref/alter_publication.sgml

@@ -82,8 +83,8 @@ ALTER PUBLICATION <replaceable
class="parameter">name</replaceable> RESET

<para>
You must own the publication to use <command>ALTER PUBLICATION</command>.
- Adding a table to a publication additionally requires owning that table.
- The <literal>ADD ALL TABLES IN SCHEMA</literal> and
+ Adding a table or excluding a table to a publication additionally requires
+ owning that table. The <literal>ADD ALL TABLES IN SCHEMA</literal> and

SUGGESTION
Adding a table to or excluding a table from a publication additionally
requires owning that table.

~~~

13. doc/src/sgml/ref/alter_publication.sgml

@@ -213,6 +214,14 @@ ALTER PUBLICATION sales_publication ADD ALL
TABLES IN SCHEMA marketing, sales;
</programlisting>
</para>

+ <para>
+ Alter publication <structname>production_publication</structname> that
+ publishes all tables except <structname>users</structname> and
+ <structname>departments</structname> tables:
+<programlisting>

"that publishes" -> "to publish"

~~~

14. doc/src/sgml/ref/create_publication.sgml

(Same comment about the ONLY syntax as #11)

~~~

15. doc/src/sgml/ref/create_publication.sgml

+ <varlistentry>
+ <term><literal>EXCEPT TABLE</literal></term>
+ <listitem>
+ <para>
+ Marks the publication as one that excludes replicating changes for the
+ specified tables.
+ </para>
+
+ <para>
+ <literal>EXCEPT TABLE</literal> can be specified only for
+ <literal>FOR ALL TABLES</literal> publication. It is not supported for
+ <literal>FOR ALL TABLES IN SCHEMA </literal> publication and
+ <literal>FOR TABLE</literal> publication.
+ </para>
+ </listitem>
+ </varlistentry>

IMO you can remove all that "It is not supported for..." sentence. You
don't need to spell that out again when it is already clear from the
syntax.

~~~

16. doc/src/sgml/ref/psql-ref.sgml

@@ -1868,8 +1868,9 @@ testdb=&gt;
If <replaceable class="parameter">pattern</replaceable> is
specified, only those publications whose names match the pattern are
listed.
- If <literal>+</literal> is appended to the command name, the tables and
- schemas associated with each publication are shown as well.
+ If <literal>+</literal> is appended to the command name, the tables,
+ excluded tables and schemas associated with each publication
are shown as
+ well.
</para>

Perhaps this is OK just as-is, but OTOH I felt that the change was
almost unnecessary because saying it displays "the tables" kind of
implies it would also have to account for the "excluded tables" too.

~~~

17. src/backend/catalog/pg_publication.c - GetTopMostAncestorInPublication

@@ -302,8 +303,9 @@ GetTopMostAncestorInPublication(Oid puboid, List
*ancestors, int *ancestor_level
foreach(lc, ancestors)
{
Oid ancestor = lfirst_oid(lc);
- List *apubids = GetRelationPublications(ancestor);
+ List *apubids = GetRelationPublications(ancestor, false);
List *aschemaPubids = NIL;
+ List *aexceptpubids = NIL;

17a.
I think the var "aschemaPubids" and "aexceptpubids" are only used in
the 'else' block so it seems better they can be declared and freed in
that block too instead of always.

17b.
Also, the camel-case of those variables is inconsistent so may fix
that at the same time.

~~~

18. src/backend/catalog/pg_publication.c - GetRelationPublications

@@ -666,7 +673,7 @@ publication_add_schema(Oid pubid, Oid schemaid,
bool if_not_exists)

/* Gets list of publication oids for a relation */
List *
-GetRelationPublications(Oid relid)
+GetRelationPublications(Oid relid, bool bexcept)

18a.
I felt that "except_flag" is a better name than "bexcept" for this param.

18b.
The function comment should be updated to say only relations matching
this except_flag are returned in the list.

~~~

19. src/backend/catalog/pg_publication.c - GetAllTablesPublicationRelations

@@ -787,6 +795,15 @@ GetAllTablesPublicationRelations(bool pubviaroot)
HeapTuple tuple;
List *result = NIL;

+ /*
+ * pg_publication_rel and pg_publication_namespace will only have excluded
+ * tables in case of all tables publication, no need to pass except flag
+ * to get the relations.
+ */
+ List *exceptpubtablelist;
+
+ exceptpubtablelist = GetPublicationRelations(pubid, PUBLICATION_PART_ALL);
+

19a.
I wasn't very sure of the meaning/intent of the comment, but IIUC it
seems to be explaining why it is not necessary to use an "except_flag"
parameter in this code. Is it necessary/helpful to explain parameters
that do NOT exist?

19b.
The var name "exceptpubtablelist" seems a bit overkill. (e.g.
"excepttablelist" or "exceptlist" etc... are shorter but seem equally
informative).

~~~

20. src/backend/commands/publicationcmds.c - CreatePublication

@@ -843,54 +849,52 @@ CreatePublication(ParseState *pstate,
CreatePublicationStmt *stmt)
/* Make the changes visible. */
CommandCounterIncrement();

- /* Associate objects with the publication. */
- if (stmt->for_all_tables)
- {
- /* Invalidate relcache so that publication info is rebuilt. */
- CacheInvalidateRelcacheAll();
- }
- else
- {
- ObjectsInPublicationToOids(stmt->pubobjects, pstate, &relations,
- &schemaidlist);
+ ObjectsInPublicationToOids(stmt->pubobjects, pstate, &relations,
+ &schemaidlist);

- /* FOR ALL TABLES IN SCHEMA requires superuser */
- if (list_length(schemaidlist) > 0 && !superuser())
- ereport(ERROR,
- errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to create FOR ALL TABLES IN SCHEMA publication"));
+ /* FOR ALL TABLES IN SCHEMA requires superuser */
+ if (list_length(schemaidlist) > 0 && !superuser())
+ ereport(ERROR,
+ errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to create FOR ALL TABLES IN SCHEMA publication"));

- if (list_length(relations) > 0)
- {
- List *rels;
+ if (list_length(relations) > 0)
+ {
+ List *rels;

- rels = OpenTableList(relations);
- CheckObjSchemaNotAlreadyInPublication(rels, schemaidlist,
- PUBLICATIONOBJ_TABLE);
+ rels = OpenTableList(relations);
+ CheckObjSchemaNotAlreadyInPublication(rels, schemaidlist,
+ PUBLICATIONOBJ_TABLE);

- TransformPubWhereClauses(rels, pstate->p_sourcetext,
- publish_via_partition_root);
+ TransformPubWhereClauses(rels, pstate->p_sourcetext,
+ publish_via_partition_root);

- CheckPubRelationColumnList(rels, pstate->p_sourcetext,
- publish_via_partition_root);
+ CheckPubRelationColumnList(rels, pstate->p_sourcetext,
+ publish_via_partition_root);

- PublicationAddTables(puboid, rels, true, NULL);
- CloseTableList(rels);
- }
+ PublicationAddTables(puboid, rels, true, NULL);
+ CloseTableList(rels);
+ }

- if (list_length(schemaidlist) > 0)
- {
- /*
- * Schema lock is held until the publication is created to prevent
- * concurrent schema deletion.
- */
- LockSchemaList(schemaidlist);
- PublicationAddSchemas(puboid, schemaidlist, true, NULL);
- }
+ if (list_length(schemaidlist) > 0)
+ {
+ /*
+ * Schema lock is held until the publication is created to prevent
+ * concurrent schema deletion.
+ */
+ LockSchemaList(schemaidlist);
+ PublicationAddSchemas(puboid, schemaidlist, true, NULL);
}

table_close(rel, RowExclusiveLock);

+ /* Associate objects with the publication. */
+ if (stmt->for_all_tables)
+ {
+ /* Invalidate relcache so that publication info is rebuilt. */
+ CacheInvalidateRelcacheAll();
+ }
+

This function is refactored a lot to not use "if/else" as it did
before. But AFAIK (maybe I misunderstood) this refactor doesn't seem
to actually have anything to do with the EXCEPT patch. If it really is
unrelated maybe it should not be part of this patch.

~~~

21. src/backend/commands/publicationcmds.c - CheckPublicationDefValues

+ if (pubform->puballtables)
+ return false;
+
+ if (!pubform->pubinsert || !pubform->pubupdate || !pubform->pubdelete ||
+ !pubform->pubtruncate || pubform->pubviaroot)
+ return false;

Now you have all the #define for the PUB_DEFAULT_XXX values, perhaps
this function should be using them instead of the hardcoded
assumptions what the default values are.

e.g.

if (pubform->puballtables != PUB_DEFAULT_ALL_TABLES) return false;
if (pubform->pubinsert != PUB_DEFAULT_ACTION_INSERT) return false;
...
etc.

~~~

22. src/backend/commands/publicationcmds.c - CheckAlterPublication

@@ -1442,6 +1516,19 @@ CheckAlterPublication(AlterPublicationStmt
*stmt, HeapTuple tup,
List *tables, List *schemaidlist)
{
Form_pg_publication pubform = (Form_pg_publication) GETSTRUCT(tup);
+ ListCell *lc;
+ bool nonexcepttable = false;
+ bool excepttable = false;
+
+ foreach(lc, tables)
+ {
+ PublicationTable *pub_table = lfirst_node(PublicationTable, lc);
+
+ if (!pub_table->except)
+ nonexcepttable = true;
+ else
+ excepttable = true;
+ }

22a.
The names are very confusing. e.g. "nonexcepttable" is like a double-negative.

SUGGEST:
bool has_tables = false;
bool has_except_tables = false;

22b.
Reverse the "if" condition to be positive instead of negative (remove !)
e.g.
if (pub_table->except)
has_except_table = true;
else
has_table = true;

~~~

23. src/backend/commands/publicationcmds.c - CheckAlterPublication

@@ -1461,12 +1548,19 @@ CheckAlterPublication(AlterPublicationStmt
*stmt, HeapTuple tup,
errdetail("Tables from schema cannot be added to, dropped from, or
set on FOR ALL TABLES publications.")));

/* Check that user is allowed to manipulate the publication tables. */
- if (tables && pubform->puballtables)
+ if (nonexcepttable && tables && pubform->puballtables)
ereport(ERROR,

Seems no reason for "tables" to be in the condition since
"nonexcepttable" can't be true if "tables" is NIL.

~~~

24. src/backend/commands/publicationcmds.c - CheckAlterPublication

+
+ if (excepttable && !stmt->for_all_tables)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("publication \"%s\" is not defined as FOR ALL TABLES",
+ NameStr(pubform->pubname)),
+ errdetail("except table cannot be added to, dropped from, or set on
NON ALL TABLES publications.")));

The errdetail message seems over-complex.

SUGGESTION
"EXCEPT TABLE clause is only allowed for FOR ALL TABLES publications."

~~~

25. src/backend/commands/publicationcmds.c - AlterPublication

@@ -1500,6 +1594,20 @@ AlterPublication(ParseState *pstate,
AlterPublicationStmt *stmt)
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION,
stmt->pubname);

+ if (stmt->for_all_tables)
+ {
+ bool isdefault = CheckPublicationDefValues(tup);
+
+ if (!isdefault)
+ ereport(ERROR,
+ errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("Setting ALL TABLES requires publication \"%s\" to have
default values",
+ stmt->pubname),
+ errhint("Either the publication has tables/schemas associated or
does not have default publication options or ALL TABLES option is
set."));

The errhint message seems over-complex.

SUGGESTION
"Use ALTER PUBLICATION ... RESET"

~~~

26. src/bin/pg_dump/pg_dump.c - dumpPublication

@@ -3980,8 +3982,34 @@ dumpPublication(Archive *fout, const
PublicationInfo *pubinfo)
qpubname);

if (pubinfo->puballtables)
+ {
+ SimplePtrListCell *cell;
+ bool first = true;
appendPQExpBufferStr(query, " FOR ALL TABLES");

+ /* Include exception tables if the publication has except tables */
+ for (cell = exceptinfo.head; cell; cell = cell->next)
+ {
+ PublicationRelInfo *pubrinfo = (PublicationRelInfo *) cell->ptr;
+ PublicationInfo *relpubinfo = pubrinfo->publication;
+ TableInfo *tbinfo;
+
+ if (pubinfo == relpubinfo)
+ {
+ tbinfo = pubrinfo->pubtable;
+
+ if (first)
+ {
+ appendPQExpBufferStr(query, " EXCEPT TABLE ONLY");
+ first = false;
+ }
+ else
+ appendPQExpBufferStr(query, ", ");
+ appendPQExpBuffer(query, " %s", fmtQualifiedDumpable(tbinfo));
+ }
+ }
+ }
+

IIUC this usage of ONLY looks incorrect.

26a.
Firstly, if you want to hardwire ONLY then shouldn't it apply to every
of the except-list table, not just the first one? e.g. "EXCEPT TABLE
ONLY t1, ONLY t2, ONLY t3..."

26b.
Secondly, is it even correct to unconditionally hardwire the ONLY? How
do you know that is how the user wanted it?

~~~

27. src/bin/pg_dump/pg_dump.c

@@ -127,6 +127,8 @@ static SimpleOidList foreign_servers_include_oids
= {NULL, NULL};
static SimpleStringList extension_include_patterns = {NULL, NULL};
static SimpleOidList extension_include_oids = {NULL, NULL};

+static SimplePtrList exceptinfo = {NULL, NULL};
+

Probably I just did not understand how this logic works, but how does
this static work properly if there are multiple publications and 2
different EXCEPT lists? E.g. where is it clearing the "exceptinfo" so
that multiple EXCEPT TABLE lists don't become muddled?

~~~

28. src/bin/pg_dump/pg_dump.c - dumpPublicationTable

@@ -4330,8 +4378,11 @@ dumpPublicationTable(Archive *fout, const
PublicationRelInfo *pubrinfo)

query = createPQExpBuffer();

- appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD TABLE ONLY",
+ appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD ",
fmtId(pubinfo->dobj.name));
+
+ appendPQExpBufferStr(query, "TABLE ONLY");
+

That code refactor does not seem necessary for this patch.

~~~

29. src/bin/pg_dump/pg_dump_sort.c

@@ -90,6 +90,7 @@ enum dbObjectTypePriorities
PRIO_FK_CONSTRAINT,
PRIO_POLICY,
PRIO_PUBLICATION,
+ PRIO_PUBLICATION_EXCEPT_REL,
PRIO_PUBLICATION_REL,
PRIO_PUBLICATION_TABLE_IN_SCHEMA,
PRIO_SUBSCRIPTION,

I'm not sure how this enum is used (so perhaps this makes no
difference) but judging by the enum comment why did you put the sort
priority order PRIO_PUBLICATION_EXCEPT_REL before
PRIO_PUBLICATION_REL. Wouldn’t it make more sense the other way
around?

~~~

30. src/bin/psql/describe.c

@@ -2950,17 +2950,34 @@ describeOneTableDetails(const char *schemaname,
" WHERE attrelid = pr.prrelid AND attnum = prattrs[s])\n"
" ELSE NULL END) "
"FROM pg_catalog.pg_publication p\n"
- " JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
- " JOIN pg_catalog.pg_class c ON c.oid = pr.prrelid\n"
- "WHERE pr.prrelid = '%s'\n"
- "UNION\n"
+ " JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
+ " JOIN pg_catalog.pg_class c ON c.oid = pr.prrelid\n"
+ "WHERE pr.prrelid = '%s'",
+ oid, oid, oid);

I feel that trailing "\n" ("WHERE pr.prrelid = '%s'\n") should not
have been removed.

~~~

31. src/bin/psql/describe.c

+ /* FIXME: 150000 should be changed to 160000 later for PG16. */
+ if (pset.sversion >= 150000)
+ appendPQExpBufferStr(&buf, " AND pr.prexcept = 'f'\n");
+
+ appendPQExpBuffer(&buf, "UNION\n"

The "UNION\n" param might be better wrapped onto the next line like it
used to be.

~~~

32. src/bin/psql/describe.c

+ /* FIXME: 150000 should be changed to 160000 later for PG16. */
+ if (pset.sversion >= 150000)
+ appendPQExpBuffer(&buf,
+ " AND NOT EXISTS (SELECT 1\n"
+ " FROM pg_catalog.pg_publication_rel pr\n"
+ " JOIN pg_catalog.pg_class pc\n"
+ " ON pr.prrelid = pc.oid\n"
+ " WHERE pr.prrelid = '%s' AND pr.prpubid = p.oid)\n",
+ oid);

The whitespace indents in the SQL seem excessive here.

~~~

33. src/bin/psql/describe.c - describePublications

@@ -6322,6 +6344,22 @@ describePublications(const char *pattern)
}
}

+ /* FIXME: 150000 should be changed to 160000 later for PG16. */
+ if (pset.sversion >= 150000)
+ {
+ /* Get the excluded tables for the specified publication */
+ printfPQExpBuffer(&buf,
+ "SELECT concat(c.relnamespace::regnamespace, '.', c.relname)\n"
+ "FROM pg_catalog.pg_class c\n"
+ " JOIN pg_catalog.pg_publication_rel pr ON c.oid = pr.prrelid\n"
+ "WHERE pr.prpubid = '%s'\n"
+ " AND pr.prexcept = 't'\n"
+ "ORDER BY 1", pubid);
+ if (!addFooterToPublicationDesc(&buf, "Except tables:",
+ true, &cont))
+ goto error_return;
+ }
+

I think this code is misplaced. Shouldn't it be if/else and be above
the other 150000 check, otherwise when you change this to PG16 it may
not work as expected?

~~~

34. src/bin/psql/describe.c - describePublications

+ if (!addFooterToPublicationDesc(&buf, "Except tables:",
+ true, &cont))
+ goto error_return;
+ }

Should this be using the _T() macros same as the other prompts for translation?

~~~

35. src/include/catalog/pg_publication.h

I thought the param "bexpect" should be "except_flag".

(same comment as #18a)

~~~

36. src/include/catalog/pg_publication_rel.h

@@ -31,6 +31,7 @@ CATALOG(pg_publication_rel,6106,PublicationRelRelationId)
Oid oid; /* oid */
Oid prpubid BKI_LOOKUP(pg_publication); /* Oid of the publication */
Oid prrelid BKI_LOOKUP(pg_class); /* Oid of the relation */
+ bool prexcept BKI_DEFAULT(f); /* except the relation */

SUGGEST (comment)
/* skip the relation */

~~~

37. src/include/commands/publicationcmds.h

@@ -32,8 +32,8 @@ extern ObjectAddress AlterPublicationOwner(const
char *name, Oid newOwnerId);
extern void AlterPublicationOwner_oid(Oid pubid, Oid newOwnerId);
extern void InvalidatePublicationRels(List *relids);
extern bool pub_rf_contains_invalid_column(Oid pubid, Relation relation,
- List *ancestors, bool pubviaroot);
+ List *ancestors, bool pubviaroot, bool alltables);
extern bool pub_collist_contains_invalid_column(Oid pubid, Relation relation,
- List *ancestors, bool pubviaroot);
+ List *ancestors, bool pubviaroot, bool alltables);

Elsewhere in this patch, a similarly added param is called
"puballtables" (not "alltables"). Please check all places and use a
consistent param name for all of them.

~~~

38. src/test/regress/sql/publication.sql

There don't seem to be any tests for more than one EXCEPT TABLE (e.g.
no list tests?)

~~~

38. src/test/regress/sql/publication.sql

Maybe adjust all the below comments (a-d) to say "EXCEPT TABLES"
intead of "except tables"

38a.
+-- can't add except table to 'FOR ALL TABLES' publication

38b.
+-- can't add except table to 'FOR TABLE' publication

38c.
+-- can't add except table to 'FOR ALL TABLES IN SCHEMA' publication

38d.
+-- can't add except table when publish_via_partition_root option does not
+-- have default value

38e.
+-- can't add except table when the publication options does not have default
+-- values

SUGGESTION
can't add EXCEPT TABLE when the publication options are not the default values

~~~

39. .../t/032_rep_changes_except_table.pl

39a.
+# Check the table data does not sync for excluded table
+my $result = $node_subscriber->safe_psql('postgres',
+ "SELECT count(*), min(a), max(a) FROM sch1.tab1");
+is($result, qq(0||), 'check tablesync is excluded for excluded tables');

Maybe the "is" message should say "check there is no initial data
copied for the excluded table"

~~~

40 .../t/032_rep_changes_except_table.pl

+# Insert some data into few tables and verify that inserted data is not
+# replicated
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO sch1.tab1 VALUES(generate_series(11,20))");

The comment is not quite correct. You are inserting into only one
table here - not "few tables".

~~~

41. .../t/032_rep_changes_except_table.pl

+# Alter publication to exclude data changes in public.tab1 and verify that
+# subscriber does not get the new table data.

"new table data" -> "changed data for this table"

------
[1] https://www.postgresql.org/message-id/TYCPR01MB83737C28187A6E0BADAE98F0EDCF9%40TYCPR01MB8373.jpnprd01.prod.outlook.com

Kind Regards,
Peter Smith.
Fujitsu Australia


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-17 03:56:28
Message-ID: CAA4eK1JEKs8qwwhRb1BCiMNduJ5ePUtFnTscrZt86UKWBkLxwg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, May 17, 2022 at 7:35 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Below are my review comments for v5-0002.
>
> There may be an overlap with comments recently posted by Osumi-san [1].
>
> (I also have review comments for v5-0002; will post them tomorrow)
>
> ======
>
> 1. General
>
> Is it really necessary to have to say "EXCEPT TABLE" instead of just
> "EXCEPT". It seems unnecessarily verbose and redundant when you write
> "FOR ALL TABLES EXCEPT TABLE...".
>
> If you want to keep this TABLE keyword (maybe you have plans for other
> kinds of except?)
>

I don't think there is an immediate plan but one can imagine using
EXCEPT SCHEMA. Then for column lists, one may want to use the syntax
Create Publication pub1 For Table t1 Except Cols (c1, ..);

> then IMO perhaps at least it can be the optional
> default except type. e.g. EXCEPT [TABLE].
>

Yeah, that might be okay, so, even if we plan to extend this in the
future, by default we will consider the list of tables after EXCEPT
but if the user mentions EXCEPT SCHEMA or something else then we can
use a different object. Is that sound okay?

>
> 3. General
>
> The ONLY keyword seems supported by the syntax for tables of the
> except-list (more on this in later comments) but:
> a) I am not sure if the patch code is accounting for that, and
> b) There are no test cases using ONLY.
>
> ~~~
>

Isn't it better to map ONLY with the way it can already be specified
in CREATE PUBLICATION? I am not sure what exactly is proposed and what
is your suggestion? Can you please explain if it is different from the
way we use it for CREATE PUBLICATION?

--
With Regards,
Amit Kapila.


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-17 04:29:33
Message-ID: CAHut+Ps17ZshcLKqmaFVVhMKMrHozVGAykSDbTBZ=Pd=YqUDdg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, May 17, 2022 at 1:56 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Tue, May 17, 2022 at 7:35 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >
> > Below are my review comments for v5-0002.
> >
> > There may be an overlap with comments recently posted by Osumi-san [1].
> >
> > (I also have review comments for v5-0002; will post them tomorrow)
> >
> > ======
> >
> > 1. General
> >
> > Is it really necessary to have to say "EXCEPT TABLE" instead of just
> > "EXCEPT". It seems unnecessarily verbose and redundant when you write
> > "FOR ALL TABLES EXCEPT TABLE...".
> >
> > If you want to keep this TABLE keyword (maybe you have plans for other
> > kinds of except?)
> >
>
> I don't think there is an immediate plan but one can imagine using
> EXCEPT SCHEMA. Then for column lists, one may want to use the syntax
> Create Publication pub1 For Table t1 Except Cols (c1, ..);
>
> > then IMO perhaps at least it can be the optional
> > default except type. e.g. EXCEPT [TABLE].
> >
>
> Yeah, that might be okay, so, even if we plan to extend this in the
> future, by default we will consider the list of tables after EXCEPT
> but if the user mentions EXCEPT SCHEMA or something else then we can
> use a different object. Is that sound okay?

Yes. That is what I meant.

>
> >
> > 3. General
> >
> > The ONLY keyword seems supported by the syntax for tables of the
> > except-list (more on this in later comments) but:
> > a) I am not sure if the patch code is accounting for that, and
> > b) There are no test cases using ONLY.
> >
> > ~~~
> >
>
> Isn't it better to map ONLY with the way it can already be specified
> in CREATE PUBLICATION? I am not sure what exactly is proposed and what
> is your suggestion? Can you please explain if it is different from the
> way we use it for CREATE PUBLICATION?
>

Yes, I am not proposing anything different to how ONLY already works
for published tables. I was only questioning whether the patch behaves
correctly when ONLY is specified for the tables of the EXCEPT list. I
had some doubt about it because there are a few other review comments
I wrote (e.g. in pg_dump.c), and also I did not find any ONLY tests,

------
Kind Regards,
Peter Smith.
Fujitsu Australia


From: "shiy(dot)fnst(at)fujitsu(dot)com" <shiy(dot)fnst(at)fujitsu(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Skipping schema changes in publication
Date: 2022-05-18 03:00:38
Message-ID: TYAPR01MB6315FF450C5D10253BA7C7FFFDD19@TYAPR01MB6315.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, May 14, 2022 9:33 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> Thanks for the comments, the attached v5 patch has the changes for the
> same. Also I have made the changes for SKIP Table based on the new
> syntax, the changes for the same are available in
> v5-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch.
>

Thanks for your patch. Here are some comments on v5-0001 patch.

+ Oid relid = lfirst_oid(lc);
+
+ prid = GetSysCacheOid2(PUBLICATIONRELMAP, Anum_pg_publication_rel_oid,
+ ObjectIdGetDatum(relid),
+ ObjectIdGetDatum(pubid));
+ if (!OidIsValid(prid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("relation \"%s\" is not part of the publication",
+ RelationGetRelationName(rel))));

I think the relation in the error message should be the one whose oid is
"relid", instead of relation "rel".

Besides, I think it might be better not to report an error in this case. If
"prid" is invalid, just ignore this relation. Because in RESET cases, we want to
drop all tables in the publications, and there is no specific table.
(If you agree with that, similarly missing_ok should be set to true when calling
PublicationDropSchemas().)

Regards,
Shi yu


From: vignesh C <vignesh21(at)gmail(dot)com>
To: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-18 17:45:08
Message-ID: CALDaNm0iZZDB300Dez_97S8G6_RW5QpQ8ef6X3wq8tyK-8wnXQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, May 16, 2022 at 8:32 AM osumi(dot)takamichi(at)fujitsu(dot)com
<osumi(dot)takamichi(at)fujitsu(dot)com> wrote:
>
> On Saturday, May 14, 2022 10:33 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > Thanks for the comments, the attached v5 patch has the changes for the same.
> > Also I have made the changes for SKIP Table based on the new syntax, the
> > changes for the same are available in
> > v5-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch.
> Hi,
>
>
> Thank you for updating the patch.
> I'll share few minor review comments on v5-0001.
>
>
> (1) doc/src/sgml/ref/alter_publication.sgml
>
> @@ -73,12 +85,13 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
> Adding a table to a publication additionally requires owning that table.
> The <literal>ADD ALL TABLES IN SCHEMA</literal> and
> <literal>SET ALL TABLES IN SCHEMA</literal> to a publication requires the
> - invoking user to be a superuser. To alter the owner, you must also be a
> - direct or indirect member of the new owning role. The new owner must have
> - <literal>CREATE</literal> privilege on the database. Also, the new owner
> - of a <literal>FOR ALL TABLES</literal> or <literal>FOR ALL TABLES IN
> - SCHEMA</literal> publication must be a superuser. However, a superuser can
> - change the ownership of a publication regardless of these restrictions.
> + invoking user to be a superuser. <literal>RESET</literal> of publication
> + requires the invoking user to be a superuser. To alter the owner, you must
> ...
>
>
> I suggest to combine the first part of your change with one existing sentence
> before your change, to make our description concise.
>
> FROM:
> "The <literal>ADD ALL TABLES IN SCHEMA</literal> and
> <literal>SET ALL TABLES IN SCHEMA</literal> to a publication requires the
> invoking user to be a superuser. <literal>RESET</literal> of publication
> requires the invoking user to be a superuser."
>
> TO:
> "The <literal>ADD ALL TABLES IN SCHEMA</literal>,
> <literal>SET ALL TABLES IN SCHEMA</literal> to a publication and
> <literal>RESET</literal> of publication requires the invoking user to be a superuser."

Modified

>
> (2) typo
>
> +++ b/src/backend/commands/publicationcmds.c
> @@ -53,6 +53,13 @@
> #include "utils/syscache.h"
> #include "utils/varlena.h"
>
> +#define PUB_ATION_INSERT_DEFAULT true
> +#define PUB_ACTION_UPDATE_DEFAULT true
>
>
> Kindly change
> FROM:
> "PUB_ATION_INSERT_DEFAULT"
> TO:
> "PUB_ACTION_INSERT_DEFAULT"

Modified

>
> (3) src/test/regress/expected/publication.out
>
> +-- Verify that only superuser can reset a publication
> +ALTER PUBLICATION testpub_reset OWNER TO regress_publication_user2;
> +SET ROLE regress_publication_user2;
> +ALTER PUBLICATION testpub_reset RESET; -- fail
>
>
> We have "-- fail" for one case in this patch.
> On the other hand, isn't better to add "-- ok" (or "-- success") for
> other successful statements,
> when we consider the entire tests description consistency ?

We generally do not mention success comments for all the success cases
as that might be an overkill. I felt it is better to keep it as it is.
Thoughts?

The attached v6 patch has the changes for the same.

Regards,
Vignesh

Attachment Content-Type Size
v6-0001-Add-RESET-clause-to-Alter-Publication-which-will-.patch text/x-patch 16.3 KB
v6-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch text/x-patch 65.8 KB

From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-18 17:47:27
Message-ID: CALDaNm3JSTRTWOvv=dGesO5Gb98kfoyZT9DSu+yP_LeUL=40zA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, May 16, 2022 at 2:53 PM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Below are my review comments for v5-0001.
>
> There is some overlap with comments recently posted by Osumi-san [1].
>
> (I also have review comments for v5-0002; will post them tomorrow)
>
> ======
>
> 1. Commit message
>
> This patch adds a new RESET clause to ALTER PUBLICATION which will reset
> the publication to default state which includes resetting the publication
> options, setting ALL TABLES option to false and dropping the relations and
> schemas that are associated with the publication.
>
> SUGGEST
> "to default state" -> "to the default state"
> "ALL TABLES option" -> "ALL TABLES flag"

Modified

> ~~~
>
> 2. doc/src/sgml/ref/alter_publication.sgml
>
> + <para>
> + The <literal>RESET</literal> clause will reset the publication to the
> + default state which includes resetting the publication options, setting
> + <literal>ALL TABLES</literal> option to <literal>false</literal> and
> + dropping all relations and schemas that are associated with the publication.
> </para>
>
> "ALL TABLES option" -> "ALL TABLES flag"

Modified

> ~~~
>
> 3. doc/src/sgml/ref/alter_publication.sgml
>
> + invoking user to be a superuser. <literal>RESET</literal> of publication
> + requires the invoking user to be a superuser. To alter the owner, you must
>
> SUGGESTION
> To <literal>RESET</literal> a publication requires the invoking user
> to be a superuser.

I have combined it with the earlier sentence.

> ~~~
>
> 4. src/backend/commands/publicationcmds.c
>
> @@ -53,6 +53,13 @@
> #include "utils/syscache.h"
> #include "utils/varlena.h"
>
> +#define PUB_ATION_INSERT_DEFAULT true
> +#define PUB_ACTION_UPDATE_DEFAULT true
> +#define PUB_ACTION_DELETE_DEFAULT true
> +#define PUB_ACTION_TRUNCATE_DEFAULT true
> +#define PUB_VIA_ROOT_DEFAULT false
> +#define PUB_ALL_TABLES_DEFAULT false
>
> 4a.
> Typo: "ATION" -> "ACTION"

Modified

> 4b.
> I think these #defines deserve a 1 line comment.
> e.g.
> /* CREATE PUBLICATION default values for flags and options */

Added comment

> 4c.
> Since the "_DEFAULT" is a common part of all the names, maybe it is
> tidier if it comes first.
> e.g.
> #define PUB_DEFAULT_ACTION_INSERT true
> #define PUB_DEFAULT_ACTION_UPDATE true
> #define PUB_DEFAULT_ACTION_DELETE true
> #define PUB_DEFAULT_ACTION_TRUNCATE true
> #define PUB_DEFAULT_VIA_ROOT false
> #define PUB_DEFAULT_ALL_TABLES false

Modified

The v6 patch attached at [1] has the changes for the same.
[1] - https://www.postgresql.org/message-id/CALDaNm0iZZDB300Dez_97S8G6_RW5QpQ8ef6X3wq8tyK-8wnXQ%40mail.gmail.com

Regards,
Vignesh


From: vignesh C <vignesh21(at)gmail(dot)com>
To: "shiy(dot)fnst(at)fujitsu(dot)com" <shiy(dot)fnst(at)fujitsu(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-18 17:49:01
Message-ID: CALDaNm3PcrbmLcgBi38oL_268TnERWBG1c5kFDuNViTszP_K2Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, May 18, 2022 at 8:30 AM shiy(dot)fnst(at)fujitsu(dot)com
<shiy(dot)fnst(at)fujitsu(dot)com> wrote:
>
> On Sat, May 14, 2022 9:33 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > Thanks for the comments, the attached v5 patch has the changes for the
> > same. Also I have made the changes for SKIP Table based on the new
> > syntax, the changes for the same are available in
> > v5-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch.
> >
>
> Thanks for your patch. Here are some comments on v5-0001 patch.
>
> + Oid relid = lfirst_oid(lc);
> +
> + prid = GetSysCacheOid2(PUBLICATIONRELMAP, Anum_pg_publication_rel_oid,
> + ObjectIdGetDatum(relid),
> + ObjectIdGetDatum(pubid));
> + if (!OidIsValid(prid))
> + ereport(ERROR,
> + (errcode(ERRCODE_UNDEFINED_OBJECT),
> + errmsg("relation \"%s\" is not part of the publication",
> + RelationGetRelationName(rel))));
>
> I think the relation in the error message should be the one whose oid is
> "relid", instead of relation "rel".

Modified it

> Besides, I think it might be better not to report an error in this case. If
> "prid" is invalid, just ignore this relation. Because in RESET cases, we want to
> drop all tables in the publications, and there is no specific table.
> (If you agree with that, similarly missing_ok should be set to true when calling
> PublicationDropSchemas().)

Ideally this scenario should not happen, but if it happens I felt we
should throw an error in this case.

The v6 patch attached at [1] has the changes for the same.
[1] - https://www.postgresql.org/message-id/CALDaNm0iZZDB300Dez_97S8G6_RW5QpQ8ef6X3wq8tyK-8wnXQ%40mail.gmail.com

Regards,
Vignesh


From: vignesh C <vignesh21(at)gmail(dot)com>
To: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-18 17:54:02
Message-ID: CALDaNm3XiwZKFVkfQ+Q0GobWkyMb3ygKqghWQWuDj7ZxR9rUMw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, May 16, 2022 at 2:00 PM osumi(dot)takamichi(at)fujitsu(dot)com
<osumi(dot)takamichi(at)fujitsu(dot)com> wrote:
>
> On Saturday, May 14, 2022 10:33 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > Thanks for the comments, the attached v5 patch has the changes for the same.
> > Also I have made the changes for SKIP Table based on the new syntax, the
> > changes for the same are available in
> > v5-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch.
> Hi,
>
>
>
> Several comments on v5-0002.
>
> (1) One unnecessary space before "except_pub_obj_list" syntax definition
>
> + except_pub_obj_list: ExceptPublicationObjSpec
> + { $$ = list_make1($1); }
> + | except_pub_obj_list ',' ExceptPublicationObjSpec
> + { $$ = lappend($1, $3); }
> + | /*EMPTY*/ { $$ = NULL; }
> + ;
> +
>
> From above part, kindly change
> FROM:
> " except_pub_obj_list: ExceptPublicationObjSpec"
> TO:
> "except_pub_obj_list: ExceptPublicationObjSpec"
>

Modified

> (2) doc/src/sgml/ref/create_publication.sgml
>
> (2-1)
>
> @@ -22,7 +22,7 @@ PostgreSQL documentation
> <refsynopsisdiv>
> <synopsis>
> CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
> - [ FOR ALL TABLES
> + [ FOR ALL TABLES [EXCEPT TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [, ... ]]
> | FOR <replaceable class="parameter">publication_object</replaceable> [, ... ] ]
> [ WITH ( <replaceable class="parameter">publication_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] ) ]
>
>
> Here I think we need to add two more whitespaces around square brackets.
> Please change
> FROM:
> "[ FOR ALL TABLES [EXCEPT TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [, ... ]]"
> TO:
> "[ FOR ALL TABLES [ EXCEPT TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [, ... ] ]"
>
> When I check other documentations, I see whitespaces before/after square brackets.
>
> (2-2)
> This whitespace alignment applies to alter_publication.sgml as well.

Modified

> (3)
>
>
> @@ -156,6 +156,24 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
> </listitem>
> </varlistentry>
>
> +
> + <varlistentry>
> + <term><literal>EXCEPT TABLE</literal></term>
> + <listitem>
> + <para>
> + Marks the publication as one that excludes replicating changes for the
> + specified tables.
> + </para>
> +
> + <para>
> + <literal>EXCEPT TABLE</literal> can be specified only for
> + <literal>FOR ALL TABLES</literal> publication. It is not supported for
> + <literal>FOR ALL TABLES IN SCHEMA </literal> publication and
> + <literal>FOR TABLE</literal> publication.
> + </para>
> + </listitem>
> + </varlistentry>
> +
>
> This EXCEPT TABLE clause is only for FOR ALL TABLES.
> So, how about extracting the main message from above part and
> moving it to an exising paragraph below, instead of having one independent paragraph ?
>
> <varlistentry>
> <term><literal>FOR ALL TABLES</literal></term>
> <listitem>
> <para>
> Marks the publication as one that replicates changes for all tables in
> the database, including tables created in the future.
> </para>
> </listitem>
> </varlistentry>
>
> Something like
> "Marks the publication as one that replicates changes for all tables in
> the database, including tables created in the future. EXCEPT TABLE indicates
> excluded tables for the defined publication.
> "
>

Modified

> (4) One minor confirmation about the syntax
>
> Currently, we allow one way of writing to indicate excluded tables like below.
>
> (example) CREATE PUBLICATION mypub FOR ALL TABLES EXCEPT TABLE tab3, tab4, EXCEPT TABLE tab5;
>
> This is because we define ExceptPublicationObjSpec with EXCEPT TABLE.
> Is it OK to have a room to write duplicate "EXCEPT TABLE" clauses ?
> I think there is no harm in having this,
> but I'd like to confirm whether this syntax might be better to be adjusted or not.

Changed it to allow except table only once

>
> (5) CheckAlterPublication
>
> +
> + if (excepttable && !stmt->for_all_tables)
> + ereport(ERROR,
> + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> + errmsg("publication \"%s\" is not defined as FOR ALL TABLES",
> + NameStr(pubform->pubname)),
> + errdetail("except table cannot be added to, dropped from, or set on NON ALL TABLES publications.")));
>
> Could you please add a test for this ?

This code can be removed because of grammar optimization, it will not
allow tables without "ALL TABLES". Removed this code

The v6 patch attached at [1] has the changes for the same.
[1] - https://www.postgresql.org/message-id/CALDaNm0iZZDB300Dez_97S8G6_RW5QpQ8ef6X3wq8tyK-8wnXQ%40mail.gmail.com

Regards,
Vignesh


From: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>
To: 'vignesh C' <vignesh21(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Skipping schema changes in publication
Date: 2022-05-19 01:58:27
Message-ID: TYWPR01MB836287A8EC85F88973056F85EDD09@TYWPR01MB8362.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thursday, May 19, 2022 2:45 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> On Mon, May 16, 2022 at 8:32 AM osumi(dot)takamichi(at)fujitsu(dot)com
> <osumi(dot)takamichi(at)fujitsu(dot)com> wrote:
> > (3) src/test/regress/expected/publication.out
> >
> > +-- Verify that only superuser can reset a publication ALTER
> > +PUBLICATION testpub_reset OWNER TO regress_publication_user2; SET
> > +ROLE regress_publication_user2; ALTER PUBLICATION testpub_reset
> > +RESET; -- fail
> >
> >
> > We have "-- fail" for one case in this patch.
> > On the other hand, isn't better to add "-- ok" (or "-- success") for
> > other successful statements, when we consider the entire tests
> > description consistency ?
>
> We generally do not mention success comments for all the success cases as
> that might be an overkill. I felt it is better to keep it as it is.
> Thoughts?
Thank you for updating the patches !

In terms of this point,
I meant to say we add "-- ok" for each successful
"ALTER PUBLICATION testpub_reset RESET;" statement.
That means, we'll have just three places to add "--ok"
and I thought this was not an overkill.

*But*, I'm also OK with your idea.
Please don't change the comments
and keep them as it is like v6.

Best Regards,
Takamichi Osumi


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-19 02:57:02
Message-ID: CALDaNm20_cEDm1=YP0xxUpdQYbAw3vJ=YceuzrZBV2kuMbTpbQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, May 17, 2022 at 7:35 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Below are my review comments for v5-0002.
>
> There may be an overlap with comments recently posted by Osumi-san [1].
>
> (I also have review comments for v5-0002; will post them tomorrow)
>
> ======
>
> 1. General
>
> Is it really necessary to have to say "EXCEPT TABLE" instead of just
> "EXCEPT". It seems unnecessarily verbose and redundant when you write
> "FOR ALL TABLES EXCEPT TABLE...".
>
> If you want to keep this TABLE keyword (maybe you have plans for other
> kinds of except?) then IMO perhaps at least it can be the optional
> default except type. e.g. EXCEPT [TABLE].

I have made TABLE optional.

> ~~~
>
> 2. General
>
> (I was unsure whether to even mention this one).
>
> I understand the "EXCEPT" is chosen as the user-facing syntax, but it
> still seems strange when reading the patch to see attribute members
> and column names called 'except'. I think the problem is that "except"
> is not a verb, so saying except=t/f just does not make much sense.
> Sometimes I feel that for all the internal usage
> (code/comments/catalog) using "skip" and "skip-list" etc would be a
> much better choice of names. OTOH I can see that having consistency
> with the outside syntax might also be good. Anyway, please consider -
> maybe other people feel the same?

Earlier we had discussed whether to use SKIP, but felt SKIP was not
appropriate and planned to use except as in [1]. Let's use except
unless we find a better alternative.

> ~~~
>
> 3. General
>
> The ONLY keyword seems supported by the syntax for tables of the
> except-list (more on this in later comments) but:
> a) I am not sure if the patch code is accounting for that, and

I have kept the behavior similar to FOR TABLE

> b) There are no test cases using ONLY.

Added tests for the same

> ~~~
>
> 4. Commit message
>
> A new option "EXCEPT TABLE" in Create/Alter Publication allows
> one or more tables to be excluded, publisher will exclude sending the data
> of the excluded tables to the subscriber.
>
> SUGGESTION
> A new "EXCEPT TABLE" clause for CREATE/ALTER PUBLICATION allows one or
> more tables to be excluded. The publisher will not send the data of
> excluded tables to the subscriber.

Modified

> ~~
>
> 5. Commit message
>
> The new syntax allows specifying exclude relations while creating a publication
> or exclude relations in alter publication. For example:
>
> SUGGESTION
> The new syntax allows specifying excluded relations when creating or
> altering a publication. For example:

Modified

> ~~~
>
> 6. Commit message
>
> A new column prexcept is added to table "pg_publication_rel", to maintain
> the relations that the user wants to exclude publishing through the publication.
>
> SUGGESTION
> A new column "prexcept" is added to table "pg_publication_rel", to
> maintain the relations that the user wants to exclude from the
> publications.

Modified

> ~~~
>
> 7. Commit message
>
> Modified the output plugin (pgoutput) to exclude publishing the changes of the
> excluded tables.
>
> I did not feel it was necessary to say this. It is already said above
> that the data is not sent, so that seems enough.

Modified

> ~~~
>
> 8. Commit message
>
> Updates pg_dump to identify and dump the excluded tables of the publications.
> Updates the \d family of commands to display excluded tables of the
> publications and \dRp+ variant will now display associated except tables if any.
>
> SUGGESTION
> pg_dump is updated to identify and dump the excluded tables of the publications.
>
> The psql \d family of commands to display excluded tables. e.g. psql
> \dRp+ variant will now display associated "except tables" if any.

Modified

> ~~~
>
> 9. doc/src/sgml/catalogs.sgml
>
> @@ -6426,6 +6426,15 @@ SCRAM-SHA-256$<replaceable>&lt;iteration
> count&gt;</replaceable>:<replaceable>&l
> if there is no publication qualifying condition.</para></entry>
> </row>
>
> + <row>
> + <entry role="catalog_table_entry"><para role="column_definition">
> + <structfield>prexcept</structfield> <type>bool</type>
> + </para>
> + <para>
> + True if the table must be excluded
> + </para></entry>
> + </row>
>
> Other descriptions on this page refer to "relation" instead of
> "table". Probably this should do the same to be consistent.

Modified

> ~~~
>
> 10. doc/src/sgml/logical-replication.sgml
>
> @@ -1167,8 +1167,9 @@ CONTEXT: processing remote data for replication
> origin "pg_16395" during "INSER
> <para>
> To add tables to a publication, the user must have ownership rights on the
> table. To add all tables in schema to a publication, the user must be a
> - superuser. To create a publication that publishes all tables or
> all tables in
> - schema automatically, the user must be a superuser.
> + superuser. To add all tables to a publication, the user must be a superuser.
> + To create a publication that publishes all tables or all tables in schema
> + automatically, the user must be a superuser.
> </para>
>
> It seems like a valid change but how is this related to this EXCEPT
> patch. Maybe this fix should be patched separately?

Earlier we were not allowed to add ALL TABLES, while altering
publication. This is mentioned in this patch as we suport:
ALTER PUBLICATION pubname ADD ALL TABLES syntax.

> ~~~
>
> 11. doc/src/sgml/ref/alter_publication.sgml
>
> @@ -22,6 +22,7 @@ PostgreSQL documentation
> <refsynopsisdiv>
> <synopsis>
> ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
> ADD <replaceable class="parameter">publication_object</replaceable> [,
> ...]
> +ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
> ADD ALL TABLES [EXCEPT TABLE [ ONLY ] <replaceable
> class="parameter">table_name</replaceable> [ * ] [, ... ]]
>
> The [ONLY] looks misplaced when the syntax is described like this. For
> example, in practice it is possible to write "EXCEPT TABLE ONLY t1,
> ONLY t2, t3, ONLY t4" but it doesn't seem that way by looking at these
> PG DOCS.
>
> IMO would be better described like this:
>
> [ FOR ALL TABLES [ EXCEPT TABLE exception_object [,...] ]]
>
> where exception_object is:
>
> [ ONLY ] table_name [ * ]

Modified

> ~~~
>
> 12. doc/src/sgml/ref/alter_publication.sgml
>
> @@ -82,8 +83,8 @@ ALTER PUBLICATION <replaceable
> class="parameter">name</replaceable> RESET
>
> <para>
> You must own the publication to use <command>ALTER PUBLICATION</command>.
> - Adding a table to a publication additionally requires owning that table.
> - The <literal>ADD ALL TABLES IN SCHEMA</literal> and
> + Adding a table or excluding a table to a publication additionally requires
> + owning that table. The <literal>ADD ALL TABLES IN SCHEMA</literal> and
>
> SUGGESTION
> Adding a table to or excluding a table from a publication additionally
> requires owning that table.

Modified

> ~~~
>
> 13. doc/src/sgml/ref/alter_publication.sgml
>
> @@ -213,6 +214,14 @@ ALTER PUBLICATION sales_publication ADD ALL
> TABLES IN SCHEMA marketing, sales;
> </programlisting>
> </para>
>
> + <para>
> + Alter publication <structname>production_publication</structname> that
> + publishes all tables except <structname>users</structname> and
> + <structname>departments</structname> tables:
> +<programlisting>
>
> "that publishes" -> "to publish"

Modified

> ~~~
>
> 14. doc/src/sgml/ref/create_publication.sgml
>
> (Same comment about the ONLY syntax as #11)

Modified

> ~~~
>
> 15. doc/src/sgml/ref/create_publication.sgml
>
> + <varlistentry>
> + <term><literal>EXCEPT TABLE</literal></term>
> + <listitem>
> + <para>
> + Marks the publication as one that excludes replicating changes for the
> + specified tables.
> + </para>
> +
> + <para>
> + <literal>EXCEPT TABLE</literal> can be specified only for
> + <literal>FOR ALL TABLES</literal> publication. It is not supported for
> + <literal>FOR ALL TABLES IN SCHEMA </literal> publication and
> + <literal>FOR TABLE</literal> publication.
> + </para>
> + </listitem>
> + </varlistentry>
>
> IMO you can remove all that "It is not supported for..." sentence. You
> don't need to spell that out again when it is already clear from the
> syntax.

Modified

> ~~~
>
> 16. doc/src/sgml/ref/psql-ref.sgml
>
> @@ -1868,8 +1868,9 @@ testdb=&gt;
> If <replaceable class="parameter">pattern</replaceable> is
> specified, only those publications whose names match the pattern are
> listed.
> - If <literal>+</literal> is appended to the command name, the tables and
> - schemas associated with each publication are shown as well.
> + If <literal>+</literal> is appended to the command name, the tables,
> + excluded tables and schemas associated with each publication
> are shown as
> + well.
> </para>
>
> Perhaps this is OK just as-is, but OTOH I felt that the change was
> almost unnecessary because saying it displays "the tables" kind of
> implies it would also have to account for the "excluded tables" too.

I mentioned it that way so that it is clearer and to avoid confusions
to be pointed out by other members later. I felt let's keep it this
way.

> ~~~
>
> 17. src/backend/catalog/pg_publication.c - GetTopMostAncestorInPublication
>
> @@ -302,8 +303,9 @@ GetTopMostAncestorInPublication(Oid puboid, List
> *ancestors, int *ancestor_level
> foreach(lc, ancestors)
> {
> Oid ancestor = lfirst_oid(lc);
> - List *apubids = GetRelationPublications(ancestor);
> + List *apubids = GetRelationPublications(ancestor, false);
> List *aschemaPubids = NIL;
> + List *aexceptpubids = NIL;
>
> 17a.
> I think the var "aschemaPubids" and "aexceptpubids" are only used in
> the 'else' block so it seems better they can be declared and freed in
> that block too instead of always.

Modified

> 17b.
> Also, the camel-case of those variables is inconsistent so may fix
> that at the same time.

Modified

> ~~~
>
> 18. src/backend/catalog/pg_publication.c - GetRelationPublications
>
> @@ -666,7 +673,7 @@ publication_add_schema(Oid pubid, Oid schemaid,
> bool if_not_exists)
>
> /* Gets list of publication oids for a relation */
> List *
> -GetRelationPublications(Oid relid)
> +GetRelationPublications(Oid relid, bool bexcept)
>
> 18a.
> I felt that "except_flag" is a better name than "bexcept" for this param.

Modified

> 18b.
> The function comment should be updated to say only relations matching
> this except_flag are returned in the list.

Modified

> ~~~
>
> 19. src/backend/catalog/pg_publication.c - GetAllTablesPublicationRelations
>
> @@ -787,6 +795,15 @@ GetAllTablesPublicationRelations(bool pubviaroot)
> HeapTuple tuple;
> List *result = NIL;
>
> + /*
> + * pg_publication_rel and pg_publication_namespace will only have excluded
> + * tables in case of all tables publication, no need to pass except flag
> + * to get the relations.
> + */
> + List *exceptpubtablelist;
> +
> + exceptpubtablelist = GetPublicationRelations(pubid, PUBLICATION_PART_ALL);
> +
>
> 19a.
> I wasn't very sure of the meaning/intent of the comment, but IIUC it
> seems to be explaining why it is not necessary to use an "except_flag"
> parameter in this code. Is it necessary/helpful to explain parameters
> that do NOT exist?

I have removed it

> 19b.
> The var name "exceptpubtablelist" seems a bit overkill. (e.g.
> "excepttablelist" or "exceptlist" etc... are shorter but seem equally
> informative).

Modified

> ~~~
>
> 20. src/backend/commands/publicationcmds.c - CreatePublication
>
> @@ -843,54 +849,52 @@ CreatePublication(ParseState *pstate,
> CreatePublicationStmt *stmt)
> /* Make the changes visible. */
> CommandCounterIncrement();
>
> - /* Associate objects with the publication. */
> - if (stmt->for_all_tables)
> - {
> - /* Invalidate relcache so that publication info is rebuilt. */
> - CacheInvalidateRelcacheAll();
> - }
> - else
> - {
> - ObjectsInPublicationToOids(stmt->pubobjects, pstate, &relations,
> - &schemaidlist);
> + ObjectsInPublicationToOids(stmt->pubobjects, pstate, &relations,
> + &schemaidlist);
>
> - /* FOR ALL TABLES IN SCHEMA requires superuser */
> - if (list_length(schemaidlist) > 0 && !superuser())
> - ereport(ERROR,
> - errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> - errmsg("must be superuser to create FOR ALL TABLES IN SCHEMA publication"));
> + /* FOR ALL TABLES IN SCHEMA requires superuser */
> + if (list_length(schemaidlist) > 0 && !superuser())
> + ereport(ERROR,
> + errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> + errmsg("must be superuser to create FOR ALL TABLES IN SCHEMA publication"));
>
> - if (list_length(relations) > 0)
> - {
> - List *rels;
> + if (list_length(relations) > 0)
> + {
> + List *rels;
>
> - rels = OpenTableList(relations);
> - CheckObjSchemaNotAlreadyInPublication(rels, schemaidlist,
> - PUBLICATIONOBJ_TABLE);
> + rels = OpenTableList(relations);
> + CheckObjSchemaNotAlreadyInPublication(rels, schemaidlist,
> + PUBLICATIONOBJ_TABLE);
>
> - TransformPubWhereClauses(rels, pstate->p_sourcetext,
> - publish_via_partition_root);
> + TransformPubWhereClauses(rels, pstate->p_sourcetext,
> + publish_via_partition_root);
>
> - CheckPubRelationColumnList(rels, pstate->p_sourcetext,
> - publish_via_partition_root);
> + CheckPubRelationColumnList(rels, pstate->p_sourcetext,
> + publish_via_partition_root);
>
> - PublicationAddTables(puboid, rels, true, NULL);
> - CloseTableList(rels);
> - }
> + PublicationAddTables(puboid, rels, true, NULL);
> + CloseTableList(rels);
> + }
>
> - if (list_length(schemaidlist) > 0)
> - {
> - /*
> - * Schema lock is held until the publication is created to prevent
> - * concurrent schema deletion.
> - */
> - LockSchemaList(schemaidlist);
> - PublicationAddSchemas(puboid, schemaidlist, true, NULL);
> - }
> + if (list_length(schemaidlist) > 0)
> + {
> + /*
> + * Schema lock is held until the publication is created to prevent
> + * concurrent schema deletion.
> + */
> + LockSchemaList(schemaidlist);
> + PublicationAddSchemas(puboid, schemaidlist, true, NULL);
> }
>
> table_close(rel, RowExclusiveLock);
>
> + /* Associate objects with the publication. */
> + if (stmt->for_all_tables)
> + {
> + /* Invalidate relcache so that publication info is rebuilt. */
> + CacheInvalidateRelcacheAll();
> + }
> +
>
> This function is refactored a lot to not use "if/else" as it did
> before. But AFAIK (maybe I misunderstood) this refactor doesn't seem
> to actually have anything to do with the EXCEPT patch. If it really is
> unrelated maybe it should not be part of this patch.

Earlier tables cannot be specified with all tables, now except tables
can be specified with all tables, except tables should be added to
pg_publication_rel, to handle it the code changes are required.

> ~~~
>
> 21. src/backend/commands/publicationcmds.c - CheckPublicationDefValues
>
> + if (pubform->puballtables)
> + return false;
> +
> + if (!pubform->pubinsert || !pubform->pubupdate || !pubform->pubdelete ||
> + !pubform->pubtruncate || pubform->pubviaroot)
> + return false;
>
> Now you have all the #define for the PUB_DEFAULT_XXX values, perhaps
> this function should be using them instead of the hardcoded
> assumptions what the default values are.
>
> e.g.
>
> if (pubform->puballtables != PUB_DEFAULT_ALL_TABLES) return false;
> if (pubform->pubinsert != PUB_DEFAULT_ACTION_INSERT) return false;
> ...
> etc.

Modified

> ~~~
>
> 22. src/backend/commands/publicationcmds.c - CheckAlterPublication
>
>
> @@ -1442,6 +1516,19 @@ CheckAlterPublication(AlterPublicationStmt
> *stmt, HeapTuple tup,
> List *tables, List *schemaidlist)
> {
> Form_pg_publication pubform = (Form_pg_publication) GETSTRUCT(tup);
> + ListCell *lc;
> + bool nonexcepttable = false;
> + bool excepttable = false;
> +
> + foreach(lc, tables)
> + {
> + PublicationTable *pub_table = lfirst_node(PublicationTable, lc);
> +
> + if (!pub_table->except)
> + nonexcepttable = true;
> + else
> + excepttable = true;
> + }
>
> 22a.
> The names are very confusing. e.g. "nonexcepttable" is like a double-negative.
>
> SUGGEST:
> bool has_tables = false;
> bool has_except_tables = false;
>
> 22b.
> Reverse the "if" condition to be positive instead of negative (remove !)
> e.g.
> if (pub_table->except)
> has_except_table = true;
> else
> has_table = true;

This code can be removed because of grammar optimization, it will not
allow except table without "ALL TABLES". Removed these changes.

> ~~~
>
> 23. src/backend/commands/publicationcmds.c - CheckAlterPublication
>
> @@ -1461,12 +1548,19 @@ CheckAlterPublication(AlterPublicationStmt
> *stmt, HeapTuple tup,
> errdetail("Tables from schema cannot be added to, dropped from, or
> set on FOR ALL TABLES publications.")));
>
> /* Check that user is allowed to manipulate the publication tables. */
> - if (tables && pubform->puballtables)
> + if (nonexcepttable && tables && pubform->puballtables)
> ereport(ERROR,
>
> Seems no reason for "tables" to be in the condition since
> "nonexcepttable" can't be true if "tables" is NIL.

This code can be removed because of grammar optimization, it will not
allow except table without "ALL TABLES". Removed these changes.

> ~~~
>
> 24. src/backend/commands/publicationcmds.c - CheckAlterPublication
>
> +
> + if (excepttable && !stmt->for_all_tables)
> + ereport(ERROR,
> + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> + errmsg("publication \"%s\" is not defined as FOR ALL TABLES",
> + NameStr(pubform->pubname)),
> + errdetail("except table cannot be added to, dropped from, or set on
> NON ALL TABLES publications.")));
>
> The errdetail message seems over-complex.
>
> SUGGESTION
> "EXCEPT TABLE clause is only allowed for FOR ALL TABLES publications."

This code can be removed because of grammar optimization, it will not
allow except table without "ALL TABLES". Removed this code

> ~~~
>
> 25. src/backend/commands/publicationcmds.c - AlterPublication
>
> @@ -1500,6 +1594,20 @@ AlterPublication(ParseState *pstate,
> AlterPublicationStmt *stmt)
> aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION,
> stmt->pubname);
>
> + if (stmt->for_all_tables)
> + {
> + bool isdefault = CheckPublicationDefValues(tup);
> +
> + if (!isdefault)
> + ereport(ERROR,
> + errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
> + errmsg("Setting ALL TABLES requires publication \"%s\" to have
> default values",
> + stmt->pubname),
> + errhint("Either the publication has tables/schemas associated or
> does not have default publication options or ALL TABLES option is
> set."));
>
> The errhint message seems over-complex.
>
> SUGGESTION
> "Use ALTER PUBLICATION ... RESET"

Modified

> ~~~
>
> 26. src/bin/pg_dump/pg_dump.c - dumpPublication
>
> @@ -3980,8 +3982,34 @@ dumpPublication(Archive *fout, const
> PublicationInfo *pubinfo)
> qpubname);
>
> if (pubinfo->puballtables)
> + {
> + SimplePtrListCell *cell;
> + bool first = true;
> appendPQExpBufferStr(query, " FOR ALL TABLES");
>
> + /* Include exception tables if the publication has except tables */
> + for (cell = exceptinfo.head; cell; cell = cell->next)
> + {
> + PublicationRelInfo *pubrinfo = (PublicationRelInfo *) cell->ptr;
> + PublicationInfo *relpubinfo = pubrinfo->publication;
> + TableInfo *tbinfo;
> +
> + if (pubinfo == relpubinfo)
> + {
> + tbinfo = pubrinfo->pubtable;
> +
> + if (first)
> + {
> + appendPQExpBufferStr(query, " EXCEPT TABLE ONLY");
> + first = false;
> + }
> + else
> + appendPQExpBufferStr(query, ", ");
> + appendPQExpBuffer(query, " %s", fmtQualifiedDumpable(tbinfo));
> + }
> + }
> + }
> +
>
> IIUC this usage of ONLY looks incorrect.
>
> 26a.
> Firstly, if you want to hardwire ONLY then shouldn't it apply to every
> of the except-list table, not just the first one? e.g. "EXCEPT TABLE
> ONLY t1, ONLY t2, ONLY t3..."

Modified, included ONLY for all the tables

> 26b.
> Secondly, is it even correct to unconditionally hardwire the ONLY? How
> do you know that is how the user wanted it?

The table ONLY selection is handled appropriately while creating
publication and stored in pg_publication_rel. When we dump all the
parent and child table will be included specifying ONLY will handle
both scenarios with and without ONLY. This is the same behavior as in
FOR TABLE publication

> ~~~
>
> 27. src/bin/pg_dump/pg_dump.c
>
> @@ -127,6 +127,8 @@ static SimpleOidList foreign_servers_include_oids
> = {NULL, NULL};
> static SimpleStringList extension_include_patterns = {NULL, NULL};
> static SimpleOidList extension_include_oids = {NULL, NULL};
>
> +static SimplePtrList exceptinfo = {NULL, NULL};
> +
>
> Probably I just did not understand how this logic works, but how does
> this static work properly if there are multiple publications and 2
> different EXCEPT lists? E.g. where is it clearing the "exceptinfo" so
> that multiple EXCEPT TABLE lists don't become muddled?

Currently exceptinfo holds all the exception tables and the
corresponding publications. When we dump the publication it will
select the appropriate exception tables that correspond to the
publication and dump the exception tables associated for this
publication. Since this is a special syntax "CREATE PUBLICATION FOR
ALL TABLES EXCEPT TABLE tb1 .." all the except tables should be
specified in a single statement unlike the other publication objects.

> ~~~
>
> 28. src/bin/pg_dump/pg_dump.c - dumpPublicationTable
>
> @@ -4330,8 +4378,11 @@ dumpPublicationTable(Archive *fout, const
> PublicationRelInfo *pubrinfo)
>
> query = createPQExpBuffer();
>
> - appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD TABLE ONLY",
> + appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD ",
> fmtId(pubinfo->dobj.name));
> +
> + appendPQExpBufferStr(query, "TABLE ONLY");
> +
>
> That code refactor does not seem necessary for this patch.

Modified

> ~~~
>
> 29. src/bin/pg_dump/pg_dump_sort.c
>
> @@ -90,6 +90,7 @@ enum dbObjectTypePriorities
> PRIO_FK_CONSTRAINT,
> PRIO_POLICY,
> PRIO_PUBLICATION,
> + PRIO_PUBLICATION_EXCEPT_REL,
> PRIO_PUBLICATION_REL,
> PRIO_PUBLICATION_TABLE_IN_SCHEMA,
> PRIO_SUBSCRIPTION,
>
> I'm not sure how this enum is used (so perhaps this makes no
> difference) but judging by the enum comment why did you put the sort
> priority order PRIO_PUBLICATION_EXCEPT_REL before
> PRIO_PUBLICATION_REL. Wouldn’t it make more sense the other way
> around?

This order does not matter, since the new syntax is like "CREATE
PUBLICATION.. FOR ALL TABLES EXCEPT TABLE ....", all the except tables
need to be accumulated and handled during dump publication. This code
changes take care of accumulating the exception table which will be
used later by dump publication

> ~~~
>
> 30. src/bin/psql/describe.c
>
> @@ -2950,17 +2950,34 @@ describeOneTableDetails(const char *schemaname,
> " WHERE attrelid = pr.prrelid AND attnum = prattrs[s])\n"
> " ELSE NULL END) "
> "FROM pg_catalog.pg_publication p\n"
> - " JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
> - " JOIN pg_catalog.pg_class c ON c.oid = pr.prrelid\n"
> - "WHERE pr.prrelid = '%s'\n"
> - "UNION\n"
> + " JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
> + " JOIN pg_catalog.pg_class c ON c.oid = pr.prrelid\n"
> + "WHERE pr.prrelid = '%s'",
> + oid, oid, oid);
>
> I feel that trailing "\n" ("WHERE pr.prrelid = '%s'\n") should not
> have been removed.

Modified

> ~~~
>
> 31. src/bin/psql/describe.c
>
> + /* FIXME: 150000 should be changed to 160000 later for PG16. */
> + if (pset.sversion >= 150000)
> + appendPQExpBufferStr(&buf, " AND pr.prexcept = 'f'\n");
> +
> + appendPQExpBuffer(&buf, "UNION\n"
>
> The "UNION\n" param might be better wrapped onto the next line like it
> used to be.

Modified

> ~~~
>
> 32. src/bin/psql/describe.c
>
> + /* FIXME: 150000 should be changed to 160000 later for PG16. */
> + if (pset.sversion >= 150000)
> + appendPQExpBuffer(&buf,
> + " AND NOT EXISTS (SELECT 1\n"
> + " FROM pg_catalog.pg_publication_rel pr\n"
> + " JOIN pg_catalog.pg_class pc\n"
> + " ON pr.prrelid = pc.oid\n"
> + " WHERE pr.prrelid = '%s' AND pr.prpubid = p.oid)\n",
> + oid);
>
> The whitespace indents in the SQL seem excessive here.

Modified

> ~~~
>
> 33. src/bin/psql/describe.c - describePublications
>
> @@ -6322,6 +6344,22 @@ describePublications(const char *pattern)
> }
> }
>
> + /* FIXME: 150000 should be changed to 160000 later for PG16. */
> + if (pset.sversion >= 150000)
> + {
> + /* Get the excluded tables for the specified publication */
> + printfPQExpBuffer(&buf,
> + "SELECT concat(c.relnamespace::regnamespace, '.', c.relname)\n"
> + "FROM pg_catalog.pg_class c\n"
> + " JOIN pg_catalog.pg_publication_rel pr ON c.oid = pr.prrelid\n"
> + "WHERE pr.prpubid = '%s'\n"
> + " AND pr.prexcept = 't'\n"
> + "ORDER BY 1", pubid);
> + if (!addFooterToPublicationDesc(&buf, "Except tables:",
> + true, &cont))
> + goto error_return;
> + }
> +
>
> I think this code is misplaced. Shouldn't it be if/else and be above
> the other 150000 check, otherwise when you change this to PG16 it may
> not work as expected?

I moved this to else. I felt this is applicable only for all tables
publication. Just keeping in else is fine.

> ~~~
>
> 34. src/bin/psql/describe.c - describePublications
>
> + if (!addFooterToPublicationDesc(&buf, "Except tables:",
> + true, &cont))
> + goto error_return;
> + }
>
> Should this be using the _T() macros same as the other prompts for translation?

Modified

> ~~~
>
> 35. src/include/catalog/pg_publication.h
>
> I thought the param "bexpect" should be "except_flag".
>
> (same comment as #18a)

Modified

> ~~~
>
> 36. src/include/catalog/pg_publication_rel.h
>
> @@ -31,6 +31,7 @@ CATALOG(pg_publication_rel,6106,PublicationRelRelationId)
> Oid oid; /* oid */
> Oid prpubid BKI_LOOKUP(pg_publication); /* Oid of the publication */
> Oid prrelid BKI_LOOKUP(pg_class); /* Oid of the relation */
> + bool prexcept BKI_DEFAULT(f); /* except the relation */
>
> SUGGEST (comment)
> /* skip the relation */

Changed it to exclude the relation

> ~~~
>
> 37. src/include/commands/publicationcmds.h
>
> @@ -32,8 +32,8 @@ extern ObjectAddress AlterPublicationOwner(const
> char *name, Oid newOwnerId);
> extern void AlterPublicationOwner_oid(Oid pubid, Oid newOwnerId);
> extern void InvalidatePublicationRels(List *relids);
> extern bool pub_rf_contains_invalid_column(Oid pubid, Relation relation,
> - List *ancestors, bool pubviaroot);
> + List *ancestors, bool pubviaroot, bool alltables);
> extern bool pub_collist_contains_invalid_column(Oid pubid, Relation relation,
> - List *ancestors, bool pubviaroot);
> + List *ancestors, bool pubviaroot, bool alltables);
>
> Elsewhere in this patch, a similarly added param is called
> "puballtables" (not "alltables"). Please check all places and use a
> consistent param name for all of them.

Modified

> ~~~
>
> 38. src/test/regress/sql/publication.sql
>
> There don't seem to be any tests for more than one EXCEPT TABLE (e.g.
> no list tests?)

Modified

> ~~~
>
> 38. src/test/regress/sql/publication.sql
>
> Maybe adjust all the below comments (a-d) to say "EXCEPT TABLES"
> intead of "except tables"
>
> 38a.
> +-- can't add except table to 'FOR ALL TABLES' publication
>
> 38b.
> +-- can't add except table to 'FOR TABLE' publication
>
> 38c.
> +-- can't add except table to 'FOR ALL TABLES IN SCHEMA' publication
>
> 38d.
> +-- can't add except table when publish_via_partition_root option does not
> +-- have default value
>
> 38e.
> +-- can't add except table when the publication options does not have default
> +-- values
>
> SUGGESTION
> can't add EXCEPT TABLE when the publication options are not the default values

Modified
> ~~~
>
> 39. .../t/032_rep_changes_except_table.pl
>
> 39a.
> +# Check the table data does not sync for excluded table
> +my $result = $node_subscriber->safe_psql('postgres',
> + "SELECT count(*), min(a), max(a) FROM sch1.tab1");
> +is($result, qq(0||), 'check tablesync is excluded for excluded tables');
>
> Maybe the "is" message should say "check there is no initial data
> copied for the excluded table"

Modified

> ~~~
>
>
> 40 .../t/032_rep_changes_except_table.pl
>
> +# Insert some data into few tables and verify that inserted data is not
> +# replicated
> +$node_publisher->safe_psql('postgres',
> + "INSERT INTO sch1.tab1 VALUES(generate_series(11,20))");
>
> The comment is not quite correct. You are inserting into only one
> table here - not "few tables".

Modified

> ~~~
>
> 41. .../t/032_rep_changes_except_table.pl
>
> +# Alter publication to exclude data changes in public.tab1 and verify that
> +# subscriber does not get the new table data.
>
> "new table data" -> "changed data for this table"

Modified

Thanks for the comments, the v6 patch attached at [2] has the changes
for the same.
[1] - https://www.postgresql.org/message-id/a2004f08-eb2f-b124-115c-f8f18667e585%40enterprisedb.com
[2] - https://www.postgresql.org/message-id/CALDaNm0iZZDB300Dez_97S8G6_RW5QpQ8ef6X3wq8tyK-8wnXQ%40mail.gmail.com

Regards,
Vignesh


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-19 08:19:19
Message-ID: CAHut+PsmfzDM-GCZL7DoTxYDcEnAaOY+KDEvH1bpzgNV_Suw9A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Below are my review comments for v6-0001.

======

1. General.

The patch failed 'publication' tests in the make check phase.

Please add this work to the commit-fest so that the 'cfbot' can report
such errors sooner.

~~~

2. src/backend/commands/publicationcmds.c - AlterPublicationReset

+/*
+ * Reset the publication.
+ *
+ * Reset the publication options, publication relations and
publication schemas.
+ */
+static void
+AlterPublicationReset(ParseState *pstate, AlterPublicationStmt *stmt,
+ Relation rel, HeapTuple tup)

SUGGESTION (Make the comment similar to the sgml text instead of
repeating "publication" 4x !)
/*
* Reset the publication options, set the ALL TABLES flag to false, and
* drop all relations and schemas that are associated with the publication.
*/

~~~

3. src/test/regress/expected/publication.out

make check failed. The diff is below:

@@ -1716,7 +1716,7 @@
-- Verify that only superuser can reset a publication
ALTER PUBLICATION testpub_reset OWNER TO regress_publication_user2;
SET ROLE regress_publication_user2;
-ALTER PUBLICATION testpub_reset RESET; -- fail
+ALTER PUBLICATION testpub_reset RESET; -- fail - must be superuser
ERROR: must be superuser to RESET publication
SET ROLE regress_publication_user;
DROP PUBLICATION testpub_reset;

------
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-20 00:19:13
Message-ID: CAHut+Psnng6z_D_jZtJumT+Qga-Y1evfUjAeQp_PoARbz8NT3w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

FYI, although the v6-0002 patch applied cleanly, I found that the SGML
was malformed and so the pg docs build fails.

~~~
e.g.

[postgres(at)CentOS7-x64 sgml]$ make STYLE=website html
{ \
echo "<!ENTITY version \"15beta1\">"; \
echo "<!ENTITY majorversion \"15\">"; \
} > version.sgml
'/usr/bin/perl' ./mk_feature_tables.pl YES
../../../src/backend/catalog/sql_feature_packages.txt
../../../src/backend/catalog/sql_features.txt >
features-supported.sgml
'/usr/bin/perl' ./mk_feature_tables.pl NO
../../../src/backend/catalog/sql_feature_packages.txt
../../../src/backend/catalog/sql_features.txt >
features-unsupported.sgml
'/usr/bin/perl' ./generate-errcodes-table.pl
../../../src/backend/utils/errcodes.txt > errcodes-table.sgml
'/usr/bin/perl' ./generate-keywords-table.pl . > keywords-table.sgml
/usr/bin/xmllint --path . --noout --valid postgres.sgml
ref/create_publication.sgml:171: parser error : Opening and ending tag
mismatch: varlistentry line 166 and listitem
</listitem>
^
ref/create_publication.sgml:172: parser error : Opening and ending tag
mismatch: variablelist line 60 and varlistentry
</varlistentry>
^
ref/create_publication.sgml:226: parser error : Opening and ending tag
mismatch: refsect1 line 57 and variablelist
</variablelist>
^
...

I will work around it locally, but for future patches please check the
SGML builds ok before posting.

------
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-20 01:20:47
Message-ID: CAHut+PtZDfBJ1d=3kSexgM5m+P_ok8sdsJXKimsXycaMyqXsNA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, May 20, 2022 at 10:19 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> FYI, although the v6-0002 patch applied cleanly, I found that the SGML
> was malformed and so the pg docs build fails.
>
> ~~~
> e.g.
>
> [postgres(at)CentOS7-x64 sgml]$ make STYLE=website html
> { \
> echo "<!ENTITY version \"15beta1\">"; \
> echo "<!ENTITY majorversion \"15\">"; \
> } > version.sgml
> '/usr/bin/perl' ./mk_feature_tables.pl YES
> ../../../src/backend/catalog/sql_feature_packages.txt
> ../../../src/backend/catalog/sql_features.txt >
> features-supported.sgml
> '/usr/bin/perl' ./mk_feature_tables.pl NO
> ../../../src/backend/catalog/sql_feature_packages.txt
> ../../../src/backend/catalog/sql_features.txt >
> features-unsupported.sgml
> '/usr/bin/perl' ./generate-errcodes-table.pl
> ../../../src/backend/utils/errcodes.txt > errcodes-table.sgml
> '/usr/bin/perl' ./generate-keywords-table.pl . > keywords-table.sgml
> /usr/bin/xmllint --path . --noout --valid postgres.sgml
> ref/create_publication.sgml:171: parser error : Opening and ending tag
> mismatch: varlistentry line 166 and listitem
> </listitem>
> ^
> ref/create_publication.sgml:172: parser error : Opening and ending tag
> mismatch: variablelist line 60 and varlistentry
> </varlistentry>
> ^
> ref/create_publication.sgml:226: parser error : Opening and ending tag
> mismatch: refsect1 line 57 and variablelist
> </variablelist>
> ^
> ...
>
> I will work around it locally, but for future patches please check the
> SGML builds ok before posting.

FYI, I rewrote the bad SGML fragment like this:

<varlistentry>
<term><literal>EXCEPT TABLE</literal></term>
<listitem>
<para>
This clause specifies a list of tables to exclude from the publication. It
can only be used with <literal>FOR ALL TABLES</literal>.
</para>
</listitem>
</varlistentry>

------
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-20 05:53:12
Message-ID: CAHut+PtiomM+iyAZHvb2dzfsPvRru266KuBe49hKy2n2h+m_zA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Below are my review comments for v6-0002.

======

1. Commit message.
The psql \d family of commands to display excluded tables.

SUGGESTION
The psql \d family of commands can now display excluded tables.

~~~

2. doc/src/sgml/ref/alter_publication.sgml

@@ -22,6 +22,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
ADD <replaceable class="parameter">publication_object</replaceable> [,
...]
+ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
ADD ALL TABLES [ EXCEPT [ TABLE ] exception_object [, ... ] ]

The "exception_object" font is wrong. Should look the same as
"publication_object"

~~~

3. doc/src/sgml/ref/alter_publication.sgml - Examples

@@ -214,6 +220,14 @@ ALTER PUBLICATION sales_publication ADD ALL
TABLES IN SCHEMA marketing, sales;
</programlisting>
</para>

+ <para>
+ Alter publication <structname>production_publication</structname> to publish
+ all tables except <structname>users</structname> and
+ <structname>departments</structname> tables:
+<programlisting>
+ALTER PUBLICATION production_publication ADD ALL TABLES EXCEPT TABLE
users, departments;
+</programlisting></para>

Consider using "EXCEPT" instead of "EXCEPT TABLE" because that will
show TABLE keyword is optional.

~~~

4. doc/src/sgml/ref/create_publication.sgml

An SGML tag error caused building the docs to fail. My fix was
previously reported [1].

~~~

5. doc/src/sgml/ref/create_publication.sgml

@@ -22,7 +22,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
- [ FOR ALL TABLES
+ [ FOR ALL TABLES [ EXCEPT [ TABLE ] exception_object [, ... ] ]

The "exception_object" font is wrong. Should look the same as
"publication_object"

~~~

6. doc/src/sgml/ref/create_publication.sgml - Examples

@@ -351,6 +366,15 @@ CREATE PUBLICATION production_publication FOR
TABLE users, departments, ALL TABL
CREATE PUBLICATION sales_publication FOR ALL TABLES IN SCHEMA marketing, sales;
</programlisting></para>

+ <para>
+ Create a publication that publishes all changes in all the tables except for
+ the changes of <structname>users</structname> and
+ <structname>departments</structname> table:
+<programlisting>
+CREATE PUBLICATION mypublication FOR ALL TABLE EXCEPT TABLE users, departments;
+</programlisting>
+ </para>
+

6a.
Typo: "FOR ALL TABLE" -> "FOR ALL TABLES"

6b.
Consider using "EXCEPT" instead of "EXCEPT TABLE" because that will
show TABLE keyword is optional.

~~~

7. src/backend/catalog/pg_publication.c - GetTopMostAncestorInPublication

@@ -316,18 +316,25 @@ GetTopMostAncestorInPublication(Oid puboid, List
*ancestors, int *ancestor_level
}
else
{
- aschemaPubids = GetSchemaPublications(get_rel_namespace(ancestor));
- if (list_member_oid(aschemaPubids, puboid))
+ List *aschemapubids = NIL;
+ List *aexceptpubids = NIL;
+
+ aschemapubids = GetSchemaPublications(get_rel_namespace(ancestor));
+ aexceptpubids = GetRelationPublications(ancestor, true);
+ if (list_member_oid(aschemapubids, puboid) ||
+ (puballtables && !list_member_oid(aexceptpubids, puboid)))
{

You could re-write this as multiple conditions instead of one. That
could avoid always assigning the 'aexceptpubids', so it might be a
more efficient way to write this logic.

~~~

8. src/backend/catalog/pg_publication.c - CheckPublicationDefValues

+/*
+ * Check if the publication has default values
+ *
+ * Check the following:
+ * Publication is having default options
+ * Publication is not associated with relations
+ * Publication is not associated with schemas
+ * Publication is not set with "FOR ALL TABLES"
+ */
+static bool
+CheckPublicationDefValues(HeapTuple tup)

8a.
Remove the tab. Replace with spaces.

8b.
It might be better if this comment order is the same as the logic order.
e.g.

* Check the following:
* Publication is not set with "FOR ALL TABLES"
* Publication is having default options
* Publication is not associated with schemas
* Publication is not associated with relations

~~~

9. src/backend/catalog/pg_publication.c - AlterPublicationSetAllTables

+/*
+ * Reset the publication.
+ *
+ * Reset the publication options, publication relations and
publication schemas.
+ */
+static void
+AlterPublicationSetAllTables(Relation rel, HeapTuple tup)

The function comment and the function name do not seem to match here;
something looks like a cut/paste error ??

~~~

10. src/backend/catalog/pg_publication.c - AlterPublicationSetAllTables

+ /* set all tables option */
+ values[Anum_pg_publication_puballtables - 1] = BoolGetDatum(true);
+ replaces[Anum_pg_publication_puballtables - 1] = true;

SUGGEST (comment)
/* set all ALL TABLES flag */

~~~

11. src/backend/catalog/pg_publication.c - AlterPublication

@@ -1501,6 +1579,20 @@ AlterPublication(ParseState *pstate,
AlterPublicationStmt *stmt)
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION,
stmt->pubname);

+ if (stmt->for_all_tables)
+ {
+ bool isdefault = CheckPublicationDefValues(tup);
+
+ if (!isdefault)
+ ereport(ERROR,
+ errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("Setting ALL TABLES requires publication \"%s\" to have
default values",
+ stmt->pubname),
+ errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));

The errmsg should start with a lowercase letter.

~~~

12. src/backend/catalog/pg_publication.c - AlterPublication

@@ -1501,6 +1579,20 @@ AlterPublication(ParseState *pstate,
AlterPublicationStmt *stmt)
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION,
stmt->pubname);

+ if (stmt->for_all_tables)
+ {
+ bool isdefault = CheckPublicationDefValues(tup);
+
+ if (!isdefault)
+ ereport(ERROR,
+ errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("Setting ALL TABLES requires publication \"%s\" to have
default values",
+ stmt->pubname),
+ errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));

Example test:

postgres=# create table t1(a int);
CREATE TABLE
postgres=# create publication p1 for table t1;
CREATE PUBLICATION
postgres=# alter publication p1 add all tables except t1;
2022-05-20 14:34:49.301 AEST [21802] ERROR: Setting ALL TABLES
requires publication "p1" to have default values
2022-05-20 14:34:49.301 AEST [21802] HINT: Use ALTER PUBLICATION ...
RESET to reset the publication
2022-05-20 14:34:49.301 AEST [21802] STATEMENT: alter publication p1
add all tables except t1;
ERROR: Setting ALL TABLES requires publication "p1" to have default values
HINT: Use ALTER PUBLICATION ... RESET to reset the publication
postgres=# alter publication p1 set all tables except t1;

That error message does not quite match what the user was doing.
Firstly, they were adding the ALL TABLES, not setting it. Secondly,
all the values of the publication were already defaults (only there
was an existing table t1 in the publication). Maybe some minor changes
to the message wording can be a better reflect what the user is doing
here.

~~~

13. src/backend/parser/gram.y

@@ -10410,7 +10411,7 @@ AlterOwnerStmt: ALTER AGGREGATE
aggregate_with_argtypes OWNER TO RoleSpec
*
* CREATE PUBLICATION name [WITH options]
*
- * CREATE PUBLICATION FOR ALL TABLES [WITH options]
+ * CREATE PUBLICATION FOR ALL TABLES [EXCEPT TABLE table [, ...]]
[WITH options]

Comment should show the "TABLE" keyword is optional

~~~

14. src/bin/pg_dump/pg_dump.c - dumpPublicationTable

@@ -4332,6 +4380,7 @@ dumpPublicationTable(Archive *fout, const
PublicationRelInfo *pubrinfo)

appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD TABLE ONLY",
fmtId(pubinfo->dobj.name));
+
appendPQExpBuffer(query, " %s",
fmtQualifiedDumpable(tbinfo));

This additional whitespace seems unrelated to this patch

~~~

15. src/include/nodes/parsenodes.h

15a.
@@ -3999,6 +3999,7 @@ typedef struct PublicationTable
RangeVar *relation; /* relation to be published */
Node *whereClause; /* qualifications */
List *columns; /* List of columns in a publication table */
+ bool except; /* except relation */
} PublicationTable;

Maybe the comment should be more like similar ones:
/* exclude the relation */

15b.
@@ -4007,6 +4008,7 @@ typedef struct PublicationTable
typedef enum PublicationObjSpecType
{
PUBLICATIONOBJ_TABLE, /* A table */
+ PUBLICATIONOBJ_EXCEPT_TABLE, /* An Except table */
PUBLICATIONOBJ_TABLES_IN_SCHEMA, /* All tables in schema */
PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA, /* All tables in first element of

Maybe the comment should be more like:
/* A table to be excluded */

~~~

16. src/test/regress/sql/publication.sql

I did not see any test cases using EXCEPT when the optional TABLE
keyword is omitted.

------
[1] https://www.postgresql.org/message-id/CAHut%2BPtZDfBJ1d%3D3kSexgM5m%2BP_ok8sdsJXKimsXycaMyqXsNA%40mail.gmail.com

Kind Regards,
Peter Smith.
Fujitsu Australia


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-21 05:30:52
Message-ID: CALDaNm3EpX3+Ru=SNaYi=UW5ZLE6nNhGRHZ7a8-fXPZ_-gLdxQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, May 19, 2022 at 1:49 PM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Below are my review comments for v6-0001.
>
> ======
>
> 1. General.
>
> The patch failed 'publication' tests in the make check phase.
>
> Please add this work to the commit-fest so that the 'cfbot' can report
> such errors sooner.

Added commitfest entry

> ~~~
>
> 2. src/backend/commands/publicationcmds.c - AlterPublicationReset
>
> +/*
> + * Reset the publication.
> + *
> + * Reset the publication options, publication relations and
> publication schemas.
> + */
> +static void
> +AlterPublicationReset(ParseState *pstate, AlterPublicationStmt *stmt,
> + Relation rel, HeapTuple tup)
>
> SUGGESTION (Make the comment similar to the sgml text instead of
> repeating "publication" 4x !)
> /*
> * Reset the publication options, set the ALL TABLES flag to false, and
> * drop all relations and schemas that are associated with the publication.
> */

Modified

> ~~~
>
> 3. src/test/regress/expected/publication.out
>
> make check failed. The diff is below:
>
> @@ -1716,7 +1716,7 @@
> -- Verify that only superuser can reset a publication
> ALTER PUBLICATION testpub_reset OWNER TO regress_publication_user2;
> SET ROLE regress_publication_user2;
> -ALTER PUBLICATION testpub_reset RESET; -- fail
> +ALTER PUBLICATION testpub_reset RESET; -- fail - must be superuser
> ERROR: must be superuser to RESET publication
> SET ROLE regress_publication_user;
> DROP PUBLICATION testpub_reset;

It passed for me locally because the change was present in the 002
patch. I have moved the change to 001.

The attached v7 patch has the changes for the same.
[1] - https://commitfest.postgresql.org/38/3646/

Regards,
Vignesh

Attachment Content-Type Size
v7-0001-Add-RESET-clause-to-Alter-Publication-which-will-.patch text/x-patch 16.4 KB
v7-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch text/x-patch 66.9 KB

From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-21 05:32:45
Message-ID: CALDaNm21XwM-n_VAuY1iS_BuaEAwaASxWZ4B3N1mRxs2YEeRVA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, May 20, 2022 at 5:49 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> FYI, although the v6-0002 patch applied cleanly, I found that the SGML
> was malformed and so the pg docs build fails.
>
> ~~~
> e.g.
>
> [postgres(at)CentOS7-x64 sgml]$ make STYLE=website html
> { \
> echo "<!ENTITY version \"15beta1\">"; \
> echo "<!ENTITY majorversion \"15\">"; \
> } > version.sgml
> '/usr/bin/perl' ./mk_feature_tables.pl YES
> ../../../src/backend/catalog/sql_feature_packages.txt
> ../../../src/backend/catalog/sql_features.txt >
> features-supported.sgml
> '/usr/bin/perl' ./mk_feature_tables.pl NO
> ../../../src/backend/catalog/sql_feature_packages.txt
> ../../../src/backend/catalog/sql_features.txt >
> features-unsupported.sgml
> '/usr/bin/perl' ./generate-errcodes-table.pl
> ../../../src/backend/utils/errcodes.txt > errcodes-table.sgml
> '/usr/bin/perl' ./generate-keywords-table.pl . > keywords-table.sgml
> /usr/bin/xmllint --path . --noout --valid postgres.sgml
> ref/create_publication.sgml:171: parser error : Opening and ending tag
> mismatch: varlistentry line 166 and listitem
> </listitem>
> ^
> ref/create_publication.sgml:172: parser error : Opening and ending tag
> mismatch: variablelist line 60 and varlistentry
> </varlistentry>
> ^
> ref/create_publication.sgml:226: parser error : Opening and ending tag
> mismatch: refsect1 line 57 and variablelist
> </variablelist>
> ^
> ...
>
> I will work around it locally, but for future patches please check the
> SGML builds ok before posting.

Thanks for reporting this, I have made the changes for this.
The v7 patch attached at [1] has the changes for the same.

[1] - https://www.postgresql.org/message-id/CALDaNm3EpX3%2BRu%3DSNaYi%3DUW5ZLE6nNhGRHZ7a8-fXPZ_-gLdxQ%40mail.gmail.com

Regards,
Vignesh


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-21 05:36:16
Message-ID: CALDaNm30KDnwX4Czi29fqLb8JBkuwqjbpj9ixwNXXox574NZqQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, May 20, 2022 at 11:23 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Below are my review comments for v6-0002.
>
> ======
>
> 1. Commit message.
> The psql \d family of commands to display excluded tables.
>
> SUGGESTION
> The psql \d family of commands can now display excluded tables.

Modified

> ~~~
>
> 2. doc/src/sgml/ref/alter_publication.sgml
>
> @@ -22,6 +22,7 @@ PostgreSQL documentation
> <refsynopsisdiv>
> <synopsis>
> ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
> ADD <replaceable class="parameter">publication_object</replaceable> [,
> ...]
> +ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
> ADD ALL TABLES [ EXCEPT [ TABLE ] exception_object [, ... ] ]
>
> The "exception_object" font is wrong. Should look the same as
> "publication_object"

Modified

> ~~~
>
> 3. doc/src/sgml/ref/alter_publication.sgml - Examples
>
> @@ -214,6 +220,14 @@ ALTER PUBLICATION sales_publication ADD ALL
> TABLES IN SCHEMA marketing, sales;
> </programlisting>
> </para>
>
> + <para>
> + Alter publication <structname>production_publication</structname> to publish
> + all tables except <structname>users</structname> and
> + <structname>departments</structname> tables:
> +<programlisting>
> +ALTER PUBLICATION production_publication ADD ALL TABLES EXCEPT TABLE
> users, departments;
> +</programlisting></para>
>
> Consider using "EXCEPT" instead of "EXCEPT TABLE" because that will
> show TABLE keyword is optional.

Modified

> ~~~
>
> 4. doc/src/sgml/ref/create_publication.sgml
>
> An SGML tag error caused building the docs to fail. My fix was
> previously reported [1].

Modified

> ~~~
>
> 5. doc/src/sgml/ref/create_publication.sgml
>
> @@ -22,7 +22,7 @@ PostgreSQL documentation
> <refsynopsisdiv>
> <synopsis>
> CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
> - [ FOR ALL TABLES
> + [ FOR ALL TABLES [ EXCEPT [ TABLE ] exception_object [, ... ] ]
>
> The "exception_object" font is wrong. Should look the same as
> "publication_object"

Modified

> ~~~
>
> 6. doc/src/sgml/ref/create_publication.sgml - Examples
>
> @@ -351,6 +366,15 @@ CREATE PUBLICATION production_publication FOR
> TABLE users, departments, ALL TABL
> CREATE PUBLICATION sales_publication FOR ALL TABLES IN SCHEMA marketing, sales;
> </programlisting></para>
>
> + <para>
> + Create a publication that publishes all changes in all the tables except for
> + the changes of <structname>users</structname> and
> + <structname>departments</structname> table:
> +<programlisting>
> +CREATE PUBLICATION mypublication FOR ALL TABLE EXCEPT TABLE users, departments;
> +</programlisting>
> + </para>
> +
>
> 6a.
> Typo: "FOR ALL TABLE" -> "FOR ALL TABLES"

Modified

> 6b.
> Consider using "EXCEPT" instead of "EXCEPT TABLE" because that will
> show TABLE keyword is optional.

Modified

> ~~~
>
> 7. src/backend/catalog/pg_publication.c - GetTopMostAncestorInPublication
>
> @@ -316,18 +316,25 @@ GetTopMostAncestorInPublication(Oid puboid, List
> *ancestors, int *ancestor_level
> }
> else
> {
> - aschemaPubids = GetSchemaPublications(get_rel_namespace(ancestor));
> - if (list_member_oid(aschemaPubids, puboid))
> + List *aschemapubids = NIL;
> + List *aexceptpubids = NIL;
> +
> + aschemapubids = GetSchemaPublications(get_rel_namespace(ancestor));
> + aexceptpubids = GetRelationPublications(ancestor, true);
> + if (list_member_oid(aschemapubids, puboid) ||
> + (puballtables && !list_member_oid(aexceptpubids, puboid)))
> {
>
> You could re-write this as multiple conditions instead of one. That
> could avoid always assigning the 'aexceptpubids', so it might be a
> more efficient way to write this logic.

Modified

> ~~~
>
> 8. src/backend/catalog/pg_publication.c - CheckPublicationDefValues
>
> +/*
> + * Check if the publication has default values
> + *
> + * Check the following:
> + * Publication is having default options
> + * Publication is not associated with relations
> + * Publication is not associated with schemas
> + * Publication is not set with "FOR ALL TABLES"
> + */
> +static bool
> +CheckPublicationDefValues(HeapTuple tup)
>
> 8a.
> Remove the tab. Replace with spaces.

Modified

> 8b.
> It might be better if this comment order is the same as the logic order.
> e.g.
>
> * Check the following:
> * Publication is not set with "FOR ALL TABLES"
> * Publication is having default options
> * Publication is not associated with schemas
> * Publication is not associated with relations

Modified

> ~~~
>
> 9. src/backend/catalog/pg_publication.c - AlterPublicationSetAllTables
>
> +/*
> + * Reset the publication.
> + *
> + * Reset the publication options, publication relations and
> publication schemas.
> + */
> +static void
> +AlterPublicationSetAllTables(Relation rel, HeapTuple tup)
>
> The function comment and the function name do not seem to match here;
> something looks like a cut/paste error ??

Modified

> ~~~
>
> 10. src/backend/catalog/pg_publication.c - AlterPublicationSetAllTables
>
> + /* set all tables option */
> + values[Anum_pg_publication_puballtables - 1] = BoolGetDatum(true);
> + replaces[Anum_pg_publication_puballtables - 1] = true;
>
> SUGGEST (comment)
> /* set all ALL TABLES flag */

Modified

> ~~~
>
> 11. src/backend/catalog/pg_publication.c - AlterPublication
>
> @@ -1501,6 +1579,20 @@ AlterPublication(ParseState *pstate,
> AlterPublicationStmt *stmt)
> aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION,
> stmt->pubname);
>
> + if (stmt->for_all_tables)
> + {
> + bool isdefault = CheckPublicationDefValues(tup);
> +
> + if (!isdefault)
> + ereport(ERROR,
> + errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
> + errmsg("Setting ALL TABLES requires publication \"%s\" to have
> default values",
> + stmt->pubname),
> + errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));
>
> The errmsg should start with a lowercase letter.

Modified

> ~~~
>
> 12. src/backend/catalog/pg_publication.c - AlterPublication
>
> @@ -1501,6 +1579,20 @@ AlterPublication(ParseState *pstate,
> AlterPublicationStmt *stmt)
> aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION,
> stmt->pubname);
>
> + if (stmt->for_all_tables)
> + {
> + bool isdefault = CheckPublicationDefValues(tup);
> +
> + if (!isdefault)
> + ereport(ERROR,
> + errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
> + errmsg("Setting ALL TABLES requires publication \"%s\" to have
> default values",
> + stmt->pubname),
> + errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));
>
> Example test:
>
> postgres=# create table t1(a int);
> CREATE TABLE
> postgres=# create publication p1 for table t1;
> CREATE PUBLICATION
> postgres=# alter publication p1 add all tables except t1;
> 2022-05-20 14:34:49.301 AEST [21802] ERROR: Setting ALL TABLES
> requires publication "p1" to have default values
> 2022-05-20 14:34:49.301 AEST [21802] HINT: Use ALTER PUBLICATION ...
> RESET to reset the publication
> 2022-05-20 14:34:49.301 AEST [21802] STATEMENT: alter publication p1
> add all tables except t1;
> ERROR: Setting ALL TABLES requires publication "p1" to have default values
> HINT: Use ALTER PUBLICATION ... RESET to reset the publication
> postgres=# alter publication p1 set all tables except t1;
>
> That error message does not quite match what the user was doing.
> Firstly, they were adding the ALL TABLES, not setting it. Secondly,
> all the values of the publication were already defaults (only there
> was an existing table t1 in the publication). Maybe some minor changes
> to the message wording can be a better reflect what the user is doing
> here.

Modified

> ~~~
>
> 13. src/backend/parser/gram.y
>
> @@ -10410,7 +10411,7 @@ AlterOwnerStmt: ALTER AGGREGATE
> aggregate_with_argtypes OWNER TO RoleSpec
> *
> * CREATE PUBLICATION name [WITH options]
> *
> - * CREATE PUBLICATION FOR ALL TABLES [WITH options]
> + * CREATE PUBLICATION FOR ALL TABLES [EXCEPT TABLE table [, ...]]
> [WITH options]
>
> Comment should show the "TABLE" keyword is optional

Modified

> ~~~
>
> 14. src/bin/pg_dump/pg_dump.c - dumpPublicationTable
>
> @@ -4332,6 +4380,7 @@ dumpPublicationTable(Archive *fout, const
> PublicationRelInfo *pubrinfo)
>
> appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD TABLE ONLY",
> fmtId(pubinfo->dobj.name));
> +
> appendPQExpBuffer(query, " %s",
> fmtQualifiedDumpable(tbinfo));
>
> This additional whitespace seems unrelated to this patch

Modified

> ~~~
>
> 15. src/include/nodes/parsenodes.h
>
> 15a.
> @@ -3999,6 +3999,7 @@ typedef struct PublicationTable
> RangeVar *relation; /* relation to be published */
> Node *whereClause; /* qualifications */
> List *columns; /* List of columns in a publication table */
> + bool except; /* except relation */
> } PublicationTable;
>
> Maybe the comment should be more like similar ones:
> /* exclude the relation */

Modified

> 15b.
> @@ -4007,6 +4008,7 @@ typedef struct PublicationTable
> typedef enum PublicationObjSpecType
> {
> PUBLICATIONOBJ_TABLE, /* A table */
> + PUBLICATIONOBJ_EXCEPT_TABLE, /* An Except table */
> PUBLICATIONOBJ_TABLES_IN_SCHEMA, /* All tables in schema */
> PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA, /* All tables in first element of
>
> Maybe the comment should be more like:
> /* A table to be excluded */

Modified

> ~~~
>
> 16. src/test/regress/sql/publication.sql
>
> I did not see any test cases using EXCEPT when the optional TABLE
> keyword is omitted.

Added a test

Thanks for the comments, the v7 patch attached at [1] has the changes
for the same.
[1] - https://www.postgresql.org/message-id/CALDaNm3EpX3%2BRu%3DSNaYi%3DUW5ZLE6nNhGRHZ7a8-fXPZ_-gLdxQ%40mail.gmail.com

Regards,
Vignesh


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-23 05:13:03
Message-ID: CALDaNm1PfKRJsEzbKpyt=v4p3bw+_SzE+LFPsMhR5X+qs+0pPw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, May 21, 2022 at 11:06 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Fri, May 20, 2022 at 11:23 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >
> > Below are my review comments for v6-0002.
> >
> > ======
> >
> > 1. Commit message.
> > The psql \d family of commands to display excluded tables.
> >
> > SUGGESTION
> > The psql \d family of commands can now display excluded tables.
>
> Modified
>
> > ~~~
> >
> > 2. doc/src/sgml/ref/alter_publication.sgml
> >
> > @@ -22,6 +22,7 @@ PostgreSQL documentation
> > <refsynopsisdiv>
> > <synopsis>
> > ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
> > ADD <replaceable class="parameter">publication_object</replaceable> [,
> > ...]
> > +ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
> > ADD ALL TABLES [ EXCEPT [ TABLE ] exception_object [, ... ] ]
> >
> > The "exception_object" font is wrong. Should look the same as
> > "publication_object"
>
> Modified
>
> > ~~~
> >
> > 3. doc/src/sgml/ref/alter_publication.sgml - Examples
> >
> > @@ -214,6 +220,14 @@ ALTER PUBLICATION sales_publication ADD ALL
> > TABLES IN SCHEMA marketing, sales;
> > </programlisting>
> > </para>
> >
> > + <para>
> > + Alter publication <structname>production_publication</structname> to publish
> > + all tables except <structname>users</structname> and
> > + <structname>departments</structname> tables:
> > +<programlisting>
> > +ALTER PUBLICATION production_publication ADD ALL TABLES EXCEPT TABLE
> > users, departments;
> > +</programlisting></para>
> >
> > Consider using "EXCEPT" instead of "EXCEPT TABLE" because that will
> > show TABLE keyword is optional.
>
> Modified
>
> > ~~~
> >
> > 4. doc/src/sgml/ref/create_publication.sgml
> >
> > An SGML tag error caused building the docs to fail. My fix was
> > previously reported [1].
>
> Modified
>
> > ~~~
> >
> > 5. doc/src/sgml/ref/create_publication.sgml
> >
> > @@ -22,7 +22,7 @@ PostgreSQL documentation
> > <refsynopsisdiv>
> > <synopsis>
> > CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
> > - [ FOR ALL TABLES
> > + [ FOR ALL TABLES [ EXCEPT [ TABLE ] exception_object [, ... ] ]
> >
> > The "exception_object" font is wrong. Should look the same as
> > "publication_object"
>
> Modified
>
> > ~~~
> >
> > 6. doc/src/sgml/ref/create_publication.sgml - Examples
> >
> > @@ -351,6 +366,15 @@ CREATE PUBLICATION production_publication FOR
> > TABLE users, departments, ALL TABL
> > CREATE PUBLICATION sales_publication FOR ALL TABLES IN SCHEMA marketing, sales;
> > </programlisting></para>
> >
> > + <para>
> > + Create a publication that publishes all changes in all the tables except for
> > + the changes of <structname>users</structname> and
> > + <structname>departments</structname> table:
> > +<programlisting>
> > +CREATE PUBLICATION mypublication FOR ALL TABLE EXCEPT TABLE users, departments;
> > +</programlisting>
> > + </para>
> > +
> >
> > 6a.
> > Typo: "FOR ALL TABLE" -> "FOR ALL TABLES"
>
> Modified
>
> > 6b.
> > Consider using "EXCEPT" instead of "EXCEPT TABLE" because that will
> > show TABLE keyword is optional.
>
> Modified
>
> > ~~~
> >
> > 7. src/backend/catalog/pg_publication.c - GetTopMostAncestorInPublication
> >
> > @@ -316,18 +316,25 @@ GetTopMostAncestorInPublication(Oid puboid, List
> > *ancestors, int *ancestor_level
> > }
> > else
> > {
> > - aschemaPubids = GetSchemaPublications(get_rel_namespace(ancestor));
> > - if (list_member_oid(aschemaPubids, puboid))
> > + List *aschemapubids = NIL;
> > + List *aexceptpubids = NIL;
> > +
> > + aschemapubids = GetSchemaPublications(get_rel_namespace(ancestor));
> > + aexceptpubids = GetRelationPublications(ancestor, true);
> > + if (list_member_oid(aschemapubids, puboid) ||
> > + (puballtables && !list_member_oid(aexceptpubids, puboid)))
> > {
> >
> > You could re-write this as multiple conditions instead of one. That
> > could avoid always assigning the 'aexceptpubids', so it might be a
> > more efficient way to write this logic.
>
> Modified
>
> > ~~~
> >
> > 8. src/backend/catalog/pg_publication.c - CheckPublicationDefValues
> >
> > +/*
> > + * Check if the publication has default values
> > + *
> > + * Check the following:
> > + * Publication is having default options
> > + * Publication is not associated with relations
> > + * Publication is not associated with schemas
> > + * Publication is not set with "FOR ALL TABLES"
> > + */
> > +static bool
> > +CheckPublicationDefValues(HeapTuple tup)
> >
> > 8a.
> > Remove the tab. Replace with spaces.
>
> Modified
>
> > 8b.
> > It might be better if this comment order is the same as the logic order.
> > e.g.
> >
> > * Check the following:
> > * Publication is not set with "FOR ALL TABLES"
> > * Publication is having default options
> > * Publication is not associated with schemas
> > * Publication is not associated with relations
>
> Modified
>
> > ~~~
> >
> > 9. src/backend/catalog/pg_publication.c - AlterPublicationSetAllTables
> >
> > +/*
> > + * Reset the publication.
> > + *
> > + * Reset the publication options, publication relations and
> > publication schemas.
> > + */
> > +static void
> > +AlterPublicationSetAllTables(Relation rel, HeapTuple tup)
> >
> > The function comment and the function name do not seem to match here;
> > something looks like a cut/paste error ??
>
> Modified
>
> > ~~~
> >
> > 10. src/backend/catalog/pg_publication.c - AlterPublicationSetAllTables
> >
> > + /* set all tables option */
> > + values[Anum_pg_publication_puballtables - 1] = BoolGetDatum(true);
> > + replaces[Anum_pg_publication_puballtables - 1] = true;
> >
> > SUGGEST (comment)
> > /* set all ALL TABLES flag */
>
> Modified
>
> > ~~~
> >
> > 11. src/backend/catalog/pg_publication.c - AlterPublication
> >
> > @@ -1501,6 +1579,20 @@ AlterPublication(ParseState *pstate,
> > AlterPublicationStmt *stmt)
> > aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION,
> > stmt->pubname);
> >
> > + if (stmt->for_all_tables)
> > + {
> > + bool isdefault = CheckPublicationDefValues(tup);
> > +
> > + if (!isdefault)
> > + ereport(ERROR,
> > + errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
> > + errmsg("Setting ALL TABLES requires publication \"%s\" to have
> > default values",
> > + stmt->pubname),
> > + errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));
> >
> > The errmsg should start with a lowercase letter.
>
> Modified
>
> > ~~~
> >
> > 12. src/backend/catalog/pg_publication.c - AlterPublication
> >
> > @@ -1501,6 +1579,20 @@ AlterPublication(ParseState *pstate,
> > AlterPublicationStmt *stmt)
> > aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION,
> > stmt->pubname);
> >
> > + if (stmt->for_all_tables)
> > + {
> > + bool isdefault = CheckPublicationDefValues(tup);
> > +
> > + if (!isdefault)
> > + ereport(ERROR,
> > + errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
> > + errmsg("Setting ALL TABLES requires publication \"%s\" to have
> > default values",
> > + stmt->pubname),
> > + errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));
> >
> > Example test:
> >
> > postgres=# create table t1(a int);
> > CREATE TABLE
> > postgres=# create publication p1 for table t1;
> > CREATE PUBLICATION
> > postgres=# alter publication p1 add all tables except t1;
> > 2022-05-20 14:34:49.301 AEST [21802] ERROR: Setting ALL TABLES
> > requires publication "p1" to have default values
> > 2022-05-20 14:34:49.301 AEST [21802] HINT: Use ALTER PUBLICATION ...
> > RESET to reset the publication
> > 2022-05-20 14:34:49.301 AEST [21802] STATEMENT: alter publication p1
> > add all tables except t1;
> > ERROR: Setting ALL TABLES requires publication "p1" to have default values
> > HINT: Use ALTER PUBLICATION ... RESET to reset the publication
> > postgres=# alter publication p1 set all tables except t1;
> >
> > That error message does not quite match what the user was doing.
> > Firstly, they were adding the ALL TABLES, not setting it. Secondly,
> > all the values of the publication were already defaults (only there
> > was an existing table t1 in the publication). Maybe some minor changes
> > to the message wording can be a better reflect what the user is doing
> > here.
>
> Modified
>
> > ~~~
> >
> > 13. src/backend/parser/gram.y
> >
> > @@ -10410,7 +10411,7 @@ AlterOwnerStmt: ALTER AGGREGATE
> > aggregate_with_argtypes OWNER TO RoleSpec
> > *
> > * CREATE PUBLICATION name [WITH options]
> > *
> > - * CREATE PUBLICATION FOR ALL TABLES [WITH options]
> > + * CREATE PUBLICATION FOR ALL TABLES [EXCEPT TABLE table [, ...]]
> > [WITH options]
> >
> > Comment should show the "TABLE" keyword is optional
>
> Modified
>
> > ~~~
> >
> > 14. src/bin/pg_dump/pg_dump.c - dumpPublicationTable
> >
> > @@ -4332,6 +4380,7 @@ dumpPublicationTable(Archive *fout, const
> > PublicationRelInfo *pubrinfo)
> >
> > appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD TABLE ONLY",
> > fmtId(pubinfo->dobj.name));
> > +
> > appendPQExpBuffer(query, " %s",
> > fmtQualifiedDumpable(tbinfo));
> >
> > This additional whitespace seems unrelated to this patch
>
> Modified
>
> > ~~~
> >
> > 15. src/include/nodes/parsenodes.h
> >
> > 15a.
> > @@ -3999,6 +3999,7 @@ typedef struct PublicationTable
> > RangeVar *relation; /* relation to be published */
> > Node *whereClause; /* qualifications */
> > List *columns; /* List of columns in a publication table */
> > + bool except; /* except relation */
> > } PublicationTable;
> >
> > Maybe the comment should be more like similar ones:
> > /* exclude the relation */
>
> Modified
>
> > 15b.
> > @@ -4007,6 +4008,7 @@ typedef struct PublicationTable
> > typedef enum PublicationObjSpecType
> > {
> > PUBLICATIONOBJ_TABLE, /* A table */
> > + PUBLICATIONOBJ_EXCEPT_TABLE, /* An Except table */
> > PUBLICATIONOBJ_TABLES_IN_SCHEMA, /* All tables in schema */
> > PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA, /* All tables in first element of
> >
> > Maybe the comment should be more like:
> > /* A table to be excluded */
>
> Modified
>
> > ~~~
> >
> > 16. src/test/regress/sql/publication.sql
> >
> > I did not see any test cases using EXCEPT when the optional TABLE
> > keyword is omitted.
>
> Added a test
>
> Thanks for the comments, the v7 patch attached at [1] has the changes
> for the same.
> [1] - https://www.postgresql.org/message-id/CALDaNm3EpX3%2BRu%3DSNaYi%3DUW5ZLE6nNhGRHZ7a8-fXPZ_-gLdxQ%40mail.gmail.com

Attached v7 patch which fixes the buildfarm warning for an unused
warning in release mode as in [1].
[1] - https://cirrus-ci.com/task/6220288017825792

Regards,
Vignesh

Attachment Content-Type Size
v7-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch text/x-patch 67.0 KB
v7-0001-Add-RESET-clause-to-Alter-Publication-which-will-.patch text/x-patch 16.4 KB

From: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>
To: 'vignesh C' <vignesh21(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Skipping schema changes in publication
Date: 2022-05-26 13:34:33
Message-ID: TYCPR01MB83730A2F1D6A5303E9C1416AEDD99@TYCPR01MB8373.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Monday, May 23, 2022 2:13 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> Attached v7 patch which fixes the buildfarm warning for an unused warning in
> release mode as in [1].
Hi, thank you for the patches.

I'll share several review comments.

For v7-0001.

(1) I'll suggest some minor rewording.

+ <para>
+ The <literal>RESET</literal> clause will reset the publication to the
+ default state which includes resetting the publication options, setting
+ <literal>ALL TABLES</literal> flag to <literal>false</literal> and
+ dropping all relations and schemas that are associated with the publication.

My suggestion is
"The RESET clause will reset the publication to the
default state. It resets the publication operations,
sets ALL TABLES flag to false and drops all relations
and schemas associated with the publication."

(2) typo and rewording

+/*
+ * Reset the publication.
+ *
+ * Reset the publication options, setting ALL TABLES flag to false and drop
+ * all relations and schemas that are associated with the publication.
+ */

The "setting" in this sentence should be "set".

How about changing like below ?
FROM:
"Reset the publication options, setting ALL TABLES flag to false and drop
all relations and schemas that are associated with the publication."
TO:
"Reset the publication operations, set ALL TABLES flag to false and drop
all relations and schemas associated with the publication."

(3) AlterPublicationReset

Do we need to call CacheInvalidateRelcacheAll() or
InvalidatePublicationRels() at the end of
AlterPublicationReset() like AlterPublicationOptions() ?

For v7-0002.

(4)

+ if (stmt->for_all_tables)
+ {
+ bool isdefault = CheckPublicationDefValues(tup);
+
+ if (!isdefault)
+ ereport(ERROR,
+ errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("adding ALL TABLES requires the publication to have default publication options, no tables/....
+ errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));

The errmsg string has three messages for user and is a bit long
(we have two sentences there connected by 'and').
Can't we make it concise and split it into a couple of lines for code readability ?

I'll suggest a change below.
FROM:
"adding ALL TABLES requires the publication to have default publication options, no tables/schemas associated and ALL TABLES flag should not be set"
TO:
"adding ALL TABLES requires the publication defined not for ALL TABLES"
"to have default publish actions without any associated tables/schemas"

(5) typo

<varlistentry>
+ <term><literal>EXCEPT TABLE</literal></term>
+ <listitem>
+ <para>
+ This clause specifies a list of tables to exclude from the publication.
+ It can only be used with <literal>FOR ALL TABLES</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+

Kindly change
FROM:
This clause specifies a list of tables to exclude from the publication.
TO:
This clause specifies a list of tables to be excluded from the publication.
or
This clause specifies a list of tables excluded from the publication.

(6) Minor suggestion for an expression change

Marks the publication as one that replicates changes for all tables in
- the database, including tables created in the future.
+ the database, including tables created in the future. If
+ <literal>EXCEPT TABLE</literal> is specified, then exclude replicating
+ the changes for the specified tables.

I'll suggest a minor rewording.
FROM:
...exclude replicating the changes for the specified tables
TO:
...exclude replication changes for the specified tables

(7)
(7-1)

+/*
+ * Check if the publication has default values
+ *
+ * Check the following:
+ * a) Publication is not set with "FOR ALL TABLES"
+ * b) Publication is having default options
+ * c) Publication is not associated with schemas
+ * d) Publication is not associated with relations
+ */
+static bool
+CheckPublicationDefValues(HeapTuple tup)

I think this header comment can be improved.
FROM:
Check the following:
TO:
Returns true if the publication satisfies all the following conditions:

(7-2)

b) should be changed as well
FROM:
Publication is having default options
TO:
Publication has the default publish operations

Best Regards,
Takamichi Osumi


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-30 08:21:36
Message-ID: CAHut+PuHvZQL6aksQ2wJ5hE6Xw=MfJCaBU_=UMEZB-qAgSn9UA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Here are some minor review comments for v7-0001.

======

1. General

Probably the commit message and all the PG docs and code comments
should be changed to refer to "publication parameters" instead of
(currently) "publication options". This is because these things are
really called "publication_parameters" in the PG docs [1].

All the following review comments are just examples of this suggestion.

~~~

2. Commit message

"includes resetting the publication options," -> "includes resetting
the publication parameters,"

~~~

3. doc/src/sgml/ref/alter_publication.sgml

+ <para>
+ The <literal>RESET</literal> clause will reset the publication to the
+ default state which includes resetting the publication options, setting
+ <literal>ALL TABLES</literal> flag to <literal>false</literal> and
+ dropping all relations and schemas that are associated with the publication.
</para>

"resetting the publication options," -> "resetting the publication parameters,"

~~~

4. src/backend/commands/publicationcmds.c

@@ -53,6 +53,14 @@
#include "utils/syscache.h"
#include "utils/varlena.h"

+/* CREATE PUBLICATION default values for flags and options */
+#define PUB_DEFAULT_ACTION_INSERT true
+#define PUB_DEFAULT_ACTION_UPDATE true
+#define PUB_DEFAULT_ACTION_DELETE true
+#define PUB_DEFAULT_ACTION_TRUNCATE true
+#define PUB_DEFAULT_VIA_ROOT false
+#define PUB_DEFAULT_ALL_TABLES false

"flags and options" -> "flags and publication parameters"

~~~

5. src/backend/commands/publicationcmds.c

+/*
+ * Reset the publication.
+ *
+ * Reset the publication options, setting ALL TABLES flag to false and drop
+ * all relations and schemas that are associated with the publication.
+ */
+static void
+AlterPublicationReset(ParseState *pstate, AlterPublicationStmt *stmt,
+ Relation rel, HeapTuple tup)

"Reset the publication options," -> "Reset the publication parameters,"

~~~

6. src/test/regress/sql/publication.sql

+-- Verify that publish options and publish_via_partition_root option are reset
+\dRp+ testpub_reset
+ALTER PUBLICATION testpub_reset RESET;
+\dRp+ testpub_reset

SUGGESTION
-- Verify that 'publish' and 'publish_via_partition_root' publication
parameters are reset

------
[1] https://www.postgresql.org/docs/current/sql-createpublication.html

Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-05-31 06:20:48
Message-ID: CAHut+PtsyfwL3opi2u4gwak7nip66agq7rQynRBL97oXBjKkcg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Here are my review comments for patch v7-0002.

======

1. doc/src/sgml/logical-replication.sgml

@@ -1167,8 +1167,9 @@ CONTEXT: processing remote data for replication
origin "pg_16395" during "INSER
<para>
To add tables to a publication, the user must have ownership rights on the
table. To add all tables in schema to a publication, the user must be a
- superuser. To create a publication that publishes all tables or
all tables in
- schema automatically, the user must be a superuser.
+ superuser. To add all tables to a publication, the user must be a superuser.
+ To create a publication that publishes all tables or all tables in schema
+ automatically, the user must be a superuser.
</para>

I felt that maybe this whole paragraph should be rearranged. Put the
"create publication" parts before the "alter publication" parts;
Re-word the sentences more similarly. I also felt the ALL TABLES and
ALL TABLES IN SCHEMA etc should be written uppercase/literal since
that is what was meant.

SUGGESTION
To create a publication using FOR ALL TABLES or FOR ALL TABLES IN
SCHEMA, the user must be a superuser. To add ALL TABLES or ALL TABLES
IN SCHEMA to a publication, the user must be a superuser. To add
tables to a publication, the user must have ownership rights on the
table.

~~~

2. doc/src/sgml/ref/alter_publication.sgml

@@ -82,8 +88,8 @@ ALTER PUBLICATION <replaceable
class="parameter">name</replaceable> RESET

<para>
You must own the publication to use <command>ALTER PUBLICATION</command>.
- Adding a table to a publication additionally requires owning that table.
- The <literal>ADD ALL TABLES IN SCHEMA</literal>,
+ Adding a table to or excluding a table from a publication additionally
+ requires owning that table. The <literal>ADD ALL TABLES IN SCHEMA</literal>,
<literal>SET ALL TABLES IN SCHEMA</literal> to a publication and

Isn't this missing some information that says ADD ALL TABLES requires
the invoking user to be a superuser?

~~~

3. doc/src/sgml/ref/alter_publication.sgml - examples

+ <para>
+ Alter publication <structname>production_publication</structname> to publish
+ all tables except <structname>users</structname> and
+ <structname>departments</structname> tables:
+<programlisting>
+ALTER PUBLICATION production_publication ADD ALL TABLES EXCEPT users,
departments;
+</programlisting></para>
+

I didn't think it needs to say "tables" 2x (e.g. remove the last "tables")

~~~

4. doc/src/sgml/ref/create_publication.sgml - examples

+ <para>
+ Create a publication that publishes all changes in all the tables except for
+ the changes of <structname>users</structname> and
+ <structname>departments</structname> tables:
+<programlisting>
+CREATE PUBLICATION mypublication FOR ALL TABLES EXCEPT users, departments;
+</programlisting>
+ </para>

I didn't think it needs to say "tables" 2x (e.g. remove the last "tables")

~~~

5. src/backend/catalog/pg_publication.c

foreach(lc, ancestors)
{
Oid ancestor = lfirst_oid(lc);
- List *apubids = GetRelationPublications(ancestor);
- List *aschemaPubids = NIL;
+ List *apubids = GetRelationPublications(ancestor, false);
+ List *aschemapubids = NIL;
+ List *aexceptpubids = NIL;

level++;

- if (list_member_oid(apubids, puboid))
+ /* check if member of table publications */
+ if (!list_member_oid(apubids, puboid))
{
- topmost_relid = ancestor;
-
- if (ancestor_level)
- *ancestor_level = level;
- }
- else
- {
- aschemaPubids = GetSchemaPublications(get_rel_namespace(ancestor));
- if (list_member_oid(aschemaPubids, puboid))
+ /* check if member of schema publications */
+ aschemapubids = GetSchemaPublications(get_rel_namespace(ancestor));
+ if (!list_member_oid(aschemapubids, puboid))
{
- topmost_relid = ancestor;
-
- if (ancestor_level)
- *ancestor_level = level;
+ /*
+ * If the publication is all tables publication and the table
+ * is not part of exception tables.
+ */
+ if (puballtables)
+ {
+ aexceptpubids = GetRelationPublications(ancestor, true);
+ if (list_member_oid(aexceptpubids, puboid))
+ goto next;
+ }
+ else
+ goto next;
}
}

+ topmost_relid = ancestor;
+
+ if (ancestor_level)
+ *ancestor_level = level;
+
+next:
list_free(apubids);
- list_free(aschemaPubids);
+ list_free(aschemapubids);
+ list_free(aexceptpubids);
}

I felt those negative (!) conditions and those goto are making this
logic hard to understand. Can’t it be simplified more than this? Even
just having another bool flag might help make it easier.

e.g. Perhaps something a bit like this (but add some comments)

foreach(lc, ancestors)
{
Oid ancestor = lfirst_oid(lc);
List *apubids = GetRelationPublications(ancestor);
List *aschemaPubids = NIL;
List *aexceptpubids = NIL;
bool set_top = false;
level++;

set_top = list_member_oid(apubids, puboid);
if (!set_top)
{
aschemaPubids = GetSchemaPublications(get_rel_namespace(ancestor));
set_top = list_member_oid(aschemaPubids, puboid);

if (!set_top && puballtables)
{
aexceptpubids = GetRelationPublications(ancestor, true);
set_top = !list_member_oid(aexceptpubids, puboid);
}
}
if (set_top)
{
topmost_relid = ancestor;

if (ancestor_level)
*ancestor_level = level;
}

list_free(apubids);
list_free(aschemapubids);
list_free(aexceptpubids);
}

------

6. src/backend/commands/publicationcmds.c - CheckPublicationDefValues

+/*
+ * Check if the publication has default values
+ *
+ * Check the following:
+ * a) Publication is not set with "FOR ALL TABLES"
+ * b) Publication is having default options
+ * c) Publication is not associated with schemas
+ * d) Publication is not associated with relations
+ */
+static bool
+CheckPublicationDefValues(HeapTuple tup)

I think Osumi-san already gave a review [1] about this same comment.

So I only wanted to add that it should not say "options" here:
"default options" -> "default publication parameter values"

~~~

7. src/backend/commands/publicationcmds.c - AlterPublicationSetAllTables

+#ifdef USE_ASSERT_CHECKING
+ Assert(!pubform->puballtables);
+#endif

Why is this #ifdef needed? Isn't that logic built into the Assert macro already?

~~~

8. src/backend/commands/publicationcmds.c - AlterPublicationSetAllTables

+ /* set ALL TABLES flag */

Use uppercase 'S' to match other comments.

~~~

9. src/backend/commands/publicationcmds.c - AlterPublication

+ if (!isdefault)
+ ereport(ERROR,
+ errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("adding ALL TABLES requires the publication to have default
publication options, no tables/schemas associated and ALL TABLES flag
should not be set"),
+ errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));

IMO this errmsg text is not very good but I think Osumi-san [1] has
also given a review comment about the same errmsg.

So I only wanted to add that should not say "options" here:
"default publication options" -> "default publication parameter values"

~~~

10. src/backend/parser/gram.y

/*****************************************************************************
*
* ALTER PUBLICATION name SET ( options )
*
* ALTER PUBLICATION name ADD pub_obj [, ...]
*
* ALTER PUBLICATION name DROP pub_obj [, ...]
*
* ALTER PUBLICATION name SET pub_obj [, ...]
*
* ALTER PUBLICATION name RESET
*
* pub_obj is one of:
*
* TABLE table_name [, ...]
* ALL TABLES IN SCHEMA schema_name [, ...]
*
*****************************************************************************/

-

Should the above comment be updated to mention also ADD ALL TABLES
... EXCEPT [TABLE] ...

~~~

11. src/bin/pg_dump/pg_dump.c - dumpPublication

+ /* Include exception tables if the publication has except tables */
+ for (cell = exceptinfo.head; cell; cell = cell->next)
+ {
+ PublicationRelInfo *pubrinfo = (PublicationRelInfo *) cell->ptr;
+ PublicationInfo *relpubinfo = pubrinfo->publication;
+ TableInfo *tbinfo;
+
+ if (pubinfo == relpubinfo)

I am unsure if that variable 'relpubinfo' is of much use; it is only
used one time.

~~~

12. src/bin/pg_dump/t/002_pg_dump.pl

I think there should be more test cases here:

E.g.1. EXCEPT TABLE should also test a list of tables

E.g.2. EXCEPT with optional TABLE keyword ommitted

~~~

13. src/bin/psql/describe.c - question about the SQL

Since the new 'except' is a boolean column, wouldn't it be more
natural if all the SQL was treating it as one?

e.g. should the SQL be saying "IS preexpect", "IS NOT prexcept";
instead of comparing preexpect to 't' and 'f' character.

~~~

14. .../t/032_rep_changes_except_table.pl

+# Test replication with publications created using FOR ALL TABLES EXCEPT TABLE
+# option.
+# Create schemas and tables on publisher

"option" -> "clause"

------
[1] https://www.postgresql.org/message-id/TYCPR01MB83730A2F1D6A5303E9C1416AEDD99%40TYCPR01MB8373.jpnprd01.prod.outlook.com

Kind Regards,
Peter Smith.
Fujitsu Australia


From: vignesh C <vignesh21(at)gmail(dot)com>
To: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-06-03 10:06:51
Message-ID: CALDaNm0sAU4s1KTLOEWv=rYo5dQK6uFTJn_0FKj3XG1Nv4D-qw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, May 26, 2022 at 7:04 PM osumi(dot)takamichi(at)fujitsu(dot)com
<osumi(dot)takamichi(at)fujitsu(dot)com> wrote:
>
> On Monday, May 23, 2022 2:13 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > Attached v7 patch which fixes the buildfarm warning for an unused warning in
> > release mode as in [1].
> Hi, thank you for the patches.
>
>
> I'll share several review comments.
>
> For v7-0001.
>
> (1) I'll suggest some minor rewording.
>
> + <para>
> + The <literal>RESET</literal> clause will reset the publication to the
> + default state which includes resetting the publication options, setting
> + <literal>ALL TABLES</literal> flag to <literal>false</literal> and
> + dropping all relations and schemas that are associated with the publication.
>
> My suggestion is
> "The RESET clause will reset the publication to the
> default state. It resets the publication operations,
> sets ALL TABLES flag to false and drops all relations
> and schemas associated with the publication."

I felt the existing looks better. I would prefer to keep it that way.

> (2) typo and rewording
>
> +/*
> + * Reset the publication.
> + *
> + * Reset the publication options, setting ALL TABLES flag to false and drop
> + * all relations and schemas that are associated with the publication.
> + */
>
> The "setting" in this sentence should be "set".
>
> How about changing like below ?
> FROM:
> "Reset the publication options, setting ALL TABLES flag to false and drop
> all relations and schemas that are associated with the publication."
> TO:
> "Reset the publication operations, set ALL TABLES flag to false and drop
> all relations and schemas associated with the publication."

I felt the existing looks better. I would prefer to keep it that way.

> (3) AlterPublicationReset
>
> Do we need to call CacheInvalidateRelcacheAll() or
> InvalidatePublicationRels() at the end of
> AlterPublicationReset() like AlterPublicationOptions() ?

CacheInvalidateRelcacheAll should be called if we change all tables
from true to false, else the cache will not be invalidated. Modified

>
> For v7-0002.
>
> (4)
>
> + if (stmt->for_all_tables)
> + {
> + bool isdefault = CheckPublicationDefValues(tup);
> +
> + if (!isdefault)
> + ereport(ERROR,
> + errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
> + errmsg("adding ALL TABLES requires the publication to have default publication options, no tables/....
> + errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));
>
>
> The errmsg string has three messages for user and is a bit long
> (we have two sentences there connected by 'and').
> Can't we make it concise and split it into a couple of lines for code readability ?
>
> I'll suggest a change below.
> FROM:
> "adding ALL TABLES requires the publication to have default publication options, no tables/schemas associated and ALL TABLES flag should not be set"
> TO:
> "adding ALL TABLES requires the publication defined not for ALL TABLES"
> "to have default publish actions without any associated tables/schemas"

Added errdetail and split it

> (5) typo
>
> <varlistentry>
> + <term><literal>EXCEPT TABLE</literal></term>
> + <listitem>
> + <para>
> + This clause specifies a list of tables to exclude from the publication.
> + It can only be used with <literal>FOR ALL TABLES</literal>.
> + </para>
> + </listitem>
> + </varlistentry>
> +
>
> Kindly change
> FROM:
> This clause specifies a list of tables to exclude from the publication.
> TO:
> This clause specifies a list of tables to be excluded from the publication.
> or
> This clause specifies a list of tables excluded from the publication.

Modified

> (6) Minor suggestion for an expression change
>
> Marks the publication as one that replicates changes for all tables in
> - the database, including tables created in the future.
> + the database, including tables created in the future. If
> + <literal>EXCEPT TABLE</literal> is specified, then exclude replicating
> + the changes for the specified tables.
>
>
> I'll suggest a minor rewording.
> FROM:
> ...exclude replicating the changes for the specified tables
> TO:
> ...exclude replication changes for the specified tables

I felt the existing is better.

> (7)
> (7-1)
>
> +/*
> + * Check if the publication has default values
> + *
> + * Check the following:
> + * a) Publication is not set with "FOR ALL TABLES"
> + * b) Publication is having default options
> + * c) Publication is not associated with schemas
> + * d) Publication is not associated with relations
> + */
> +static bool
> +CheckPublicationDefValues(HeapTuple tup)
>
>
> I think this header comment can be improved.
> FROM:
> Check the following:
> TO:
> Returns true if the publication satisfies all the following conditions:

Modified

> (7-2)
>
> b) should be changed as well
> FROM:
> Publication is having default options
> TO:
> Publication has the default publish operations

Changed it to "Publication is having default publication parameter values"

Thanks for the comments, the attached v8 patch has the changes for the same.

Regards,
Vignesh

Attachment Content-Type Size
v8-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch text/x-patch 67.3 KB
v8-0001-Add-RESET-clause-to-Alter-Publication-which-will-.patch text/x-patch 18.5 KB

From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-06-03 10:10:55
Message-ID: CALDaNm1VnoPFpUneukoaKmvVdyuUSSi=_pPGYTGbrSZrR2acBQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

'On Mon, May 30, 2022 at 1:51 PM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Here are some minor review comments for v7-0001.
>
> ======
>
> 1. General
>
> Probably the commit message and all the PG docs and code comments
> should be changed to refer to "publication parameters" instead of
> (currently) "publication options". This is because these things are
> really called "publication_parameters" in the PG docs [1].
>
> All the following review comments are just examples of this suggestion.

Modified

> ~~~
>
> 2. Commit message
>
> "includes resetting the publication options," -> "includes resetting
> the publication parameters,"

Modified

> ~~~
>
> 3. doc/src/sgml/ref/alter_publication.sgml
>
> + <para>
> + The <literal>RESET</literal> clause will reset the publication to the
> + default state which includes resetting the publication options, setting
> + <literal>ALL TABLES</literal> flag to <literal>false</literal> and
> + dropping all relations and schemas that are associated with the publication.
> </para>
>
>
> "resetting the publication options," -> "resetting the publication parameters,"

Modified

> ~~~
>
> 4. src/backend/commands/publicationcmds.c
>
> @@ -53,6 +53,14 @@
> #include "utils/syscache.h"
> #include "utils/varlena.h"
>
> +/* CREATE PUBLICATION default values for flags and options */
> +#define PUB_DEFAULT_ACTION_INSERT true
> +#define PUB_DEFAULT_ACTION_UPDATE true
> +#define PUB_DEFAULT_ACTION_DELETE true
> +#define PUB_DEFAULT_ACTION_TRUNCATE true
> +#define PUB_DEFAULT_VIA_ROOT false
> +#define PUB_DEFAULT_ALL_TABLES false
>
> "flags and options" -> "flags and publication parameters"

Modified

> ~~~
>
> 5. src/backend/commands/publicationcmds.c
>
> +/*
> + * Reset the publication.
> + *
> + * Reset the publication options, setting ALL TABLES flag to false and drop
> + * all relations and schemas that are associated with the publication.
> + */
> +static void
> +AlterPublicationReset(ParseState *pstate, AlterPublicationStmt *stmt,
> + Relation rel, HeapTuple tup)
>
> "Reset the publication options," -> "Reset the publication parameters,"

Modified

> ~~~
>
> 6. src/test/regress/sql/publication.sql
>
> +-- Verify that publish options and publish_via_partition_root option are reset
> +\dRp+ testpub_reset
> +ALTER PUBLICATION testpub_reset RESET;
> +\dRp+ testpub_reset
>
> SUGGESTION
> -- Verify that 'publish' and 'publish_via_partition_root' publication
> parameters are reset

Modified, I have split this into two tests as it will help the 0002
patch to add few tests with the existing steps for 'publish' and
'publish_via_partition_root' publication parameter.

Thanks for the comments. the v8 patch attached at [1] has the fixes
for the same.
[1] - https://www.postgresql.org/message-id/CALDaNm0sAU4s1KTLOEWv%3DrYo5dQK6uFTJn_0FKj3XG1Nv4D-qw%40mail.gmail.com

Regards,
Vignesh


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-06-03 10:20:08
Message-ID: CALDaNm1T1pj6aDG-U_4Zxzykv-uxzYVAP7W_QAaYNcDKW+3xRA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, May 31, 2022 at 11:51 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Here are my review comments for patch v7-0002.
>
> ======
>
> 1. doc/src/sgml/logical-replication.sgml
>
> @@ -1167,8 +1167,9 @@ CONTEXT: processing remote data for replication
> origin "pg_16395" during "INSER
> <para>
> To add tables to a publication, the user must have ownership rights on the
> table. To add all tables in schema to a publication, the user must be a
> - superuser. To create a publication that publishes all tables or
> all tables in
> - schema automatically, the user must be a superuser.
> + superuser. To add all tables to a publication, the user must be a superuser.
> + To create a publication that publishes all tables or all tables in schema
> + automatically, the user must be a superuser.
> </para>
>
> I felt that maybe this whole paragraph should be rearranged. Put the
> "create publication" parts before the "alter publication" parts;
> Re-word the sentences more similarly. I also felt the ALL TABLES and
> ALL TABLES IN SCHEMA etc should be written uppercase/literal since
> that is what was meant.
>
> SUGGESTION
> To create a publication using FOR ALL TABLES or FOR ALL TABLES IN
> SCHEMA, the user must be a superuser. To add ALL TABLES or ALL TABLES
> IN SCHEMA to a publication, the user must be a superuser. To add
> tables to a publication, the user must have ownership rights on the
> table.

Modified

> ~~~
>
> 2. doc/src/sgml/ref/alter_publication.sgml
>
> @@ -82,8 +88,8 @@ ALTER PUBLICATION <replaceable
> class="parameter">name</replaceable> RESET
>
> <para>
> You must own the publication to use <command>ALTER PUBLICATION</command>.
> - Adding a table to a publication additionally requires owning that table.
> - The <literal>ADD ALL TABLES IN SCHEMA</literal>,
> + Adding a table to or excluding a table from a publication additionally
> + requires owning that table. The <literal>ADD ALL TABLES IN SCHEMA</literal>,
> <literal>SET ALL TABLES IN SCHEMA</literal> to a publication and
>
> Isn't this missing some information that says ADD ALL TABLES requires
> the invoking user to be a superuser?

Modified

> ~~~
>
> 3. doc/src/sgml/ref/alter_publication.sgml - examples
>
> + <para>
> + Alter publication <structname>production_publication</structname> to publish
> + all tables except <structname>users</structname> and
> + <structname>departments</structname> tables:
> +<programlisting>
> +ALTER PUBLICATION production_publication ADD ALL TABLES EXCEPT users,
> departments;
> +</programlisting></para>
> +
>
> I didn't think it needs to say "tables" 2x (e.g. remove the last "tables")

Modified

> ~~~
>
> 4. doc/src/sgml/ref/create_publication.sgml - examples
>
> + <para>
> + Create a publication that publishes all changes in all the tables except for
> + the changes of <structname>users</structname> and
> + <structname>departments</structname> tables:
> +<programlisting>
> +CREATE PUBLICATION mypublication FOR ALL TABLES EXCEPT users, departments;
> +</programlisting>
> + </para>
>
> I didn't think it needs to say "tables" 2x (e.g. remove the last "tables")

Modified

> ~~~
>
> 5. src/backend/catalog/pg_publication.c
>
> foreach(lc, ancestors)
> {
> Oid ancestor = lfirst_oid(lc);
> - List *apubids = GetRelationPublications(ancestor);
> - List *aschemaPubids = NIL;
> + List *apubids = GetRelationPublications(ancestor, false);
> + List *aschemapubids = NIL;
> + List *aexceptpubids = NIL;
>
> level++;
>
> - if (list_member_oid(apubids, puboid))
> + /* check if member of table publications */
> + if (!list_member_oid(apubids, puboid))
> {
> - topmost_relid = ancestor;
> -
> - if (ancestor_level)
> - *ancestor_level = level;
> - }
> - else
> - {
> - aschemaPubids = GetSchemaPublications(get_rel_namespace(ancestor));
> - if (list_member_oid(aschemaPubids, puboid))
> + /* check if member of schema publications */
> + aschemapubids = GetSchemaPublications(get_rel_namespace(ancestor));
> + if (!list_member_oid(aschemapubids, puboid))
> {
> - topmost_relid = ancestor;
> -
> - if (ancestor_level)
> - *ancestor_level = level;
> + /*
> + * If the publication is all tables publication and the table
> + * is not part of exception tables.
> + */
> + if (puballtables)
> + {
> + aexceptpubids = GetRelationPublications(ancestor, true);
> + if (list_member_oid(aexceptpubids, puboid))
> + goto next;
> + }
> + else
> + goto next;
> }
> }
>
> + topmost_relid = ancestor;
> +
> + if (ancestor_level)
> + *ancestor_level = level;
> +
> +next:
> list_free(apubids);
> - list_free(aschemaPubids);
> + list_free(aschemapubids);
> + list_free(aexceptpubids);
> }
>
>
> I felt those negative (!) conditions and those goto are making this
> logic hard to understand. Can’t it be simplified more than this? Even
> just having another bool flag might help make it easier.
>
> e.g. Perhaps something a bit like this (but add some comments)
>
> foreach(lc, ancestors)
> {
> Oid ancestor = lfirst_oid(lc);
> List *apubids = GetRelationPublications(ancestor);
> List *aschemaPubids = NIL;
> List *aexceptpubids = NIL;
> bool set_top = false;
> level++;
>
> set_top = list_member_oid(apubids, puboid);
> if (!set_top)
> {
> aschemaPubids = GetSchemaPublications(get_rel_namespace(ancestor));
> set_top = list_member_oid(aschemaPubids, puboid);
>
> if (!set_top && puballtables)
> {
> aexceptpubids = GetRelationPublications(ancestor, true);
> set_top = !list_member_oid(aexceptpubids, puboid);
> }
> }
> if (set_top)
> {
> topmost_relid = ancestor;
>
> if (ancestor_level)
> *ancestor_level = level;
> }
>
> list_free(apubids);
> list_free(aschemapubids);
> list_free(aexceptpubids);
> }

Modified

> ------
>
> 6. src/backend/commands/publicationcmds.c - CheckPublicationDefValues
>
> +/*
> + * Check if the publication has default values
> + *
> + * Check the following:
> + * a) Publication is not set with "FOR ALL TABLES"
> + * b) Publication is having default options
> + * c) Publication is not associated with schemas
> + * d) Publication is not associated with relations
> + */
> +static bool
> +CheckPublicationDefValues(HeapTuple tup)
>
> I think Osumi-san already gave a review [1] about this same comment.
>
> So I only wanted to add that it should not say "options" here:
> "default options" -> "default publication parameter values"

Modified

> ~~~
>
> 7. src/backend/commands/publicationcmds.c - AlterPublicationSetAllTables
>
> +#ifdef USE_ASSERT_CHECKING
> + Assert(!pubform->puballtables);
> +#endif
>
> Why is this #ifdef needed? Isn't that logic built into the Assert macro already?

pubform is used only for assert case. If we don't use it within #ifdef
or PG_USED_FOR_ASSERTS_ONLY, it will throw a unused variable error
without --enable-cassert like:

publicationcmds.c: In function ‘AlterPublicationSetAllTables’:
publicationcmds.c:1250:29: error: unused variable ‘pubform’
[-Werror=unused-variable]
1250 | Form_pg_publication pubform = (Form_pg_publication)
GETSTRUCT(tup);
| ^~~~~~~
cc1: all warnings being treated as errors

> ~~~
>
> 8. src/backend/commands/publicationcmds.c - AlterPublicationSetAllTables
>
> + /* set ALL TABLES flag */
>
> Use uppercase 'S' to match other comments.

Modified

> ~~~
>
> 9. src/backend/commands/publicationcmds.c - AlterPublication
>
> + if (!isdefault)
> + ereport(ERROR,
> + errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
> + errmsg("adding ALL TABLES requires the publication to have default
> publication options, no tables/schemas associated and ALL TABLES flag
> should not be set"),
> + errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));
>
> IMO this errmsg text is not very good but I think Osumi-san [1] has
> also given a review comment about the same errmsg.
>
> So I only wanted to add that should not say "options" here:
> "default publication options" -> "default publication parameter values"

Modified

> ~~~
>
> 10. src/backend/parser/gram.y
>
> /*****************************************************************************
> *
> * ALTER PUBLICATION name SET ( options )
> *
> * ALTER PUBLICATION name ADD pub_obj [, ...]
> *
> * ALTER PUBLICATION name DROP pub_obj [, ...]
> *
> * ALTER PUBLICATION name SET pub_obj [, ...]
> *
> * ALTER PUBLICATION name RESET
> *
> * pub_obj is one of:
> *
> * TABLE table_name [, ...]
> * ALL TABLES IN SCHEMA schema_name [, ...]
> *
> *****************************************************************************/
>
> -
>
> Should the above comment be updated to mention also ADD ALL TABLES
> ... EXCEPT [TABLE] ...

Modified

> ~~~
>
> 11. src/bin/pg_dump/pg_dump.c - dumpPublication
>
> + /* Include exception tables if the publication has except tables */
> + for (cell = exceptinfo.head; cell; cell = cell->next)
> + {
> + PublicationRelInfo *pubrinfo = (PublicationRelInfo *) cell->ptr;
> + PublicationInfo *relpubinfo = pubrinfo->publication;
> + TableInfo *tbinfo;
> +
> + if (pubinfo == relpubinfo)
>
> I am unsure if that variable 'relpubinfo' is of much use; it is only
> used one time.

Removed relpubinfo

> ~~~
>
> 12. src/bin/pg_dump/t/002_pg_dump.pl
>
> I think there should be more test cases here:
>
> E.g.1. EXCEPT TABLE should also test a list of tables
>
> E.g.2. EXCEPT with optional TABLE keyword ommitted

Added a test for list of tables and modified one of the test to remove TABLE.

> ~~~
>
> 13. src/bin/psql/describe.c - question about the SQL
>
> Since the new 'except' is a boolean column, wouldn't it be more
> natural if all the SQL was treating it as one?
>
> e.g. should the SQL be saying "IS preexpect", "IS NOT prexcept";
> instead of comparing preexpect to 't' and 'f' character.

modified

> ~~~
>
> 14. .../t/032_rep_changes_except_table.pl
>
> +# Test replication with publications created using FOR ALL TABLES EXCEPT TABLE
> +# option.
> +# Create schemas and tables on publisher
>
> "option" -> "clause"

Modified.

Thanks for the comments. The v8 patch attached at [1] has the fixes
for the same.
[1] - https://www.postgresql.org/message-id/CALDaNm0sAU4s1KTLOEWv%3DrYo5dQK6uFTJn_0FKj3XG1Nv4D-qw%40mail.gmail.com

Regards,
Vignesh


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-06-08 11:04:05
Message-ID: CAA4eK1KaYmEPD0W6KPHB+ci-4PZB4k9v1TygsC+_1Mn5dPUYWg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Jun 3, 2022 at 3:37 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> Thanks for the comments, the attached v8 patch has the changes for the same.
>

AFAICS, the summary of this proposal is that we want to support
exclude of certain objects from publication with two kinds of
variants. The first variant is to add support to exclude specific
tables from ALL TABLES PUBLICATION. Without this feature, users need
to manually add all tables for a database even when she wants to avoid
only a handful of tables from the database say because they contain
sensitive information or are not required. We have seen that other
database like MySQL also provides similar feature [1] (See
REPLICATE_WILD_IGNORE_TABLE). The proposed syntax for this is as
follows:

CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE t1,t2;
or
ALTER PUBLICATION pub1 ADD ALL TABLES EXCEPT TABLE t1,t2;

This will allow us to publish all the tables in the current database
except t1 and t2. Now, I see that pg_dump has a similar option
provided by switch --exclude-table but that allows tables matching
patterns which is not the case here. I am not sure if we need a
similar variant here.

Then users will be allowed to reset the publication by:
ALTER PUBLICATION pub1 RESET;

This will reset the publication to the default state which includes
resetting the publication parameters, setting the ALL TABLES flag to
false, and dropping the relations and schemas that are associated with
the publication. I don't know if we want to go further with allowing
to RESET specific parameters and if so which parameters and what would
its syntax be?

The second variant is to add support to exclude certain columns of a
table while publishing a particular table. Currently, users need to
list all required columns' names even if they don't want to hide most
of the columns in the table (for example Create Publication pub For
Table t1 (c1, c2)). Consider user doesn't want to publish the 'salary'
or other sensitive information of executives/employees but would like
to publish all other columns. I feel in such cases it will be a lot of
work for the user especially when the table has many columns. I see
that Oracle has a similar feature [2]. I think without this it will be
difficult for users to use this feature in some cases. The patch for
this is not proposed but I would imagine syntax for it to be something
like "Create Publication pub For Table t1 Except (c3)" and similar
variants for Alter Publication.

Have I missed anything?

Thoughts on the proposal/syntax would be appreciated?

[1] - https://dev.mysql.com/doc/refman/5.7/en/change-replication-filter.html
[2] - https://docs.oracle.com/en/cloud/paas/goldengate-cloud/gwuad/selecting-columns.html#GUID-9A851C8B-48F7-43DF-8D98-D086BE069E20

--
With Regards,
Amit Kapila.


From: "houzj(dot)fnst(at)fujitsu(dot)com" <houzj(dot)fnst(at)fujitsu(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, "hametan(at)gmail(dot)com" <hametan(at)gmail(dot)com>
Subject: RE: Skipping schema changes in publication
Date: 2022-06-14 03:40:42
Message-ID: OS0PR01MB5716FB119DE3A5CB34A981F794AA9@OS0PR01MB5716.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wednesday, June 8, 2022 7:04 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Fri, Jun 3, 2022 at 3:37 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > Thanks for the comments, the attached v8 patch has the changes for the
> same.
> >
>
> AFAICS, the summary of this proposal is that we want to support
> exclude of certain objects from publication with two kinds of
> variants. The first variant is to add support to exclude specific
> tables from ALL TABLES PUBLICATION. Without this feature, users need
> to manually add all tables for a database even when she wants to avoid
> only a handful of tables from the database say because they contain
> sensitive information or are not required. We have seen that other
> database like MySQL also provides similar feature [1] (See
> REPLICATE_WILD_IGNORE_TABLE). The proposed syntax for this is as
> follows:
>
> CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE t1,t2;
> or
> ALTER PUBLICATION pub1 ADD ALL TABLES EXCEPT TABLE t1,t2;
>
> This will allow us to publish all the tables in the current database
> except t1 and t2. Now, I see that pg_dump has a similar option
> provided by switch --exclude-table but that allows tables matching
> patterns which is not the case here. I am not sure if we need a
> similar variant here.
>
> Then users will be allowed to reset the publication by:
> ALTER PUBLICATION pub1 RESET;
>
> This will reset the publication to the default state which includes
> resetting the publication parameters, setting the ALL TABLES flag to
> false, and dropping the relations and schemas that are associated with
> the publication. I don't know if we want to go further with allowing
> to RESET specific parameters and if so which parameters and what would
> its syntax be?
>
> The second variant is to add support to exclude certain columns of a
> table while publishing a particular table. Currently, users need to
> list all required columns' names even if they don't want to hide most
> of the columns in the table (for example Create Publication pub For
> Table t1 (c1, c2)). Consider user doesn't want to publish the 'salary'
> or other sensitive information of executives/employees but would like
> to publish all other columns. I feel in such cases it will be a lot of
> work for the user especially when the table has many columns. I see
> that Oracle has a similar feature [2]. I think without this it will be
> difficult for users to use this feature in some cases. The patch for
> this is not proposed but I would imagine syntax for it to be something
> like "Create Publication pub For Table t1 Except (c3)" and similar
> variants for Alter Publication.

I think the feature to exclude certain columns of a table would be useful.

In some production scenarios, we usually do not want to replicate
sensitive fields(column) in the table. Although we already can achieve
this by specify all replicated columns in the list[1], but that seems a
hard work when the table has hundreds of columns.

[1]
CREATE TABLE test(a int, b int, c int,..., sensitive text);
CRAETE PUBLICATION pub FOR TABLE test(a,b,c,...);

In addition, it's not easy to maintain the column list like above. Because
we sometimes need to add new fields or delete fields due to business
needs. Every time we add a column(or delete a column in column list), we
need to update the column list.

If we support Except:
CRAETE PUBLICATION pub FOR TABLE test EXCEPT (sensitive);

We don't need to update the column list in most cases.

Thanks for "hametan" for providing the use case off-list.

Best regards,
Hou zj


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: "houzj(dot)fnst(at)fujitsu(dot)com" <houzj(dot)fnst(at)fujitsu(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, "hametan(at)gmail(dot)com" <hametan(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2022-06-16 04:04:54
Message-ID: CAA4eK1JHpQ11=Hu3x2mP0wKu_gmoDmd95FgcoOmc9c5OpY2DAg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Jun 14, 2022 at 9:10 AM houzj(dot)fnst(at)fujitsu(dot)com
<houzj(dot)fnst(at)fujitsu(dot)com> wrote:
>
> On Wednesday, June 8, 2022 7:04 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> > On Fri, Jun 3, 2022 at 3:37 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > >
> > > Thanks for the comments, the attached v8 patch has the changes for the
> > same.
> > >
> >
> > AFAICS, the summary of this proposal is that we want to support
> > exclude of certain objects from publication with two kinds of
> > variants. The first variant is to add support to exclude specific
> > tables from ALL TABLES PUBLICATION. Without this feature, users need
> > to manually add all tables for a database even when she wants to avoid
> > only a handful of tables from the database say because they contain
> > sensitive information or are not required. We have seen that other
> > database like MySQL also provides similar feature [1] (See
> > REPLICATE_WILD_IGNORE_TABLE). The proposed syntax for this is as
> > follows:
> >
> > CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE t1,t2;
> > or
> > ALTER PUBLICATION pub1 ADD ALL TABLES EXCEPT TABLE t1,t2;
> >
> > This will allow us to publish all the tables in the current database
> > except t1 and t2. Now, I see that pg_dump has a similar option
> > provided by switch --exclude-table but that allows tables matching
> > patterns which is not the case here. I am not sure if we need a
> > similar variant here.
> >
> > Then users will be allowed to reset the publication by:
> > ALTER PUBLICATION pub1 RESET;
> >
> > This will reset the publication to the default state which includes
> > resetting the publication parameters, setting the ALL TABLES flag to
> > false, and dropping the relations and schemas that are associated with
> > the publication. I don't know if we want to go further with allowing
> > to RESET specific parameters and if so which parameters and what would
> > its syntax be?
> >
> > The second variant is to add support to exclude certain columns of a
> > table while publishing a particular table. Currently, users need to
> > list all required columns' names even if they don't want to hide most
> > of the columns in the table (for example Create Publication pub For
> > Table t1 (c1, c2)). Consider user doesn't want to publish the 'salary'
> > or other sensitive information of executives/employees but would like
> > to publish all other columns. I feel in such cases it will be a lot of
> > work for the user especially when the table has many columns. I see
> > that Oracle has a similar feature [2]. I think without this it will be
> > difficult for users to use this feature in some cases. The patch for
> > this is not proposed but I would imagine syntax for it to be something
> > like "Create Publication pub For Table t1 Except (c3)" and similar
> > variants for Alter Publication.
>
> I think the feature to exclude certain columns of a table would be useful.
>
> In some production scenarios, we usually do not want to replicate
> sensitive fields(column) in the table. Although we already can achieve
> this by specify all replicated columns in the list[1], but that seems a
> hard work when the table has hundreds of columns.
>
> [1]
> CREATE TABLE test(a int, b int, c int,..., sensitive text);
> CRAETE PUBLICATION pub FOR TABLE test(a,b,c,...);
>
> In addition, it's not easy to maintain the column list like above. Because
> we sometimes need to add new fields or delete fields due to business
> needs. Every time we add a column(or delete a column in column list), we
> need to update the column list.
>
> If we support Except:
> CRAETE PUBLICATION pub FOR TABLE test EXCEPT (sensitive);
>
> We don't need to update the column list in most cases.
>

Right, this is a valid point and I think it makes sense for me to
support such a feature for column list and also to exclude a
particular table(s) from the ALL TABLES publication.

Peter E., Euler, and others, do you have any objections to supporting
the above-mentioned two cases?

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-08-08 07:16:39
Message-ID: CALDaNm3CLRa95tpas6tEj8x58MUNDShxBNoYS+P8Uq5cryoAOw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Jun 3, 2022 at 3:36 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Thu, May 26, 2022 at 7:04 PM osumi(dot)takamichi(at)fujitsu(dot)com
> <osumi(dot)takamichi(at)fujitsu(dot)com> wrote:
> >
> > On Monday, May 23, 2022 2:13 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > > Attached v7 patch which fixes the buildfarm warning for an unused warning in
> > > release mode as in [1].
> > Hi, thank you for the patches.
> >
> >
> > I'll share several review comments.
> >
> > For v7-0001.
> >
> > (1) I'll suggest some minor rewording.
> >
> > + <para>
> > + The <literal>RESET</literal> clause will reset the publication to the
> > + default state which includes resetting the publication options, setting
> > + <literal>ALL TABLES</literal> flag to <literal>false</literal> and
> > + dropping all relations and schemas that are associated with the publication.
> >
> > My suggestion is
> > "The RESET clause will reset the publication to the
> > default state. It resets the publication operations,
> > sets ALL TABLES flag to false and drops all relations
> > and schemas associated with the publication."
>
> I felt the existing looks better. I would prefer to keep it that way.
>
> > (2) typo and rewording
> >
> > +/*
> > + * Reset the publication.
> > + *
> > + * Reset the publication options, setting ALL TABLES flag to false and drop
> > + * all relations and schemas that are associated with the publication.
> > + */
> >
> > The "setting" in this sentence should be "set".
> >
> > How about changing like below ?
> > FROM:
> > "Reset the publication options, setting ALL TABLES flag to false and drop
> > all relations and schemas that are associated with the publication."
> > TO:
> > "Reset the publication operations, set ALL TABLES flag to false and drop
> > all relations and schemas associated with the publication."
>
> I felt the existing looks better. I would prefer to keep it that way.
>
> > (3) AlterPublicationReset
> >
> > Do we need to call CacheInvalidateRelcacheAll() or
> > InvalidatePublicationRels() at the end of
> > AlterPublicationReset() like AlterPublicationOptions() ?
>
> CacheInvalidateRelcacheAll should be called if we change all tables
> from true to false, else the cache will not be invalidated. Modified
>
> >
> > For v7-0002.
> >
> > (4)
> >
> > + if (stmt->for_all_tables)
> > + {
> > + bool isdefault = CheckPublicationDefValues(tup);
> > +
> > + if (!isdefault)
> > + ereport(ERROR,
> > + errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
> > + errmsg("adding ALL TABLES requires the publication to have default publication options, no tables/....
> > + errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));
> >
> >
> > The errmsg string has three messages for user and is a bit long
> > (we have two sentences there connected by 'and').
> > Can't we make it concise and split it into a couple of lines for code readability ?
> >
> > I'll suggest a change below.
> > FROM:
> > "adding ALL TABLES requires the publication to have default publication options, no tables/schemas associated and ALL TABLES flag should not be set"
> > TO:
> > "adding ALL TABLES requires the publication defined not for ALL TABLES"
> > "to have default publish actions without any associated tables/schemas"
>
> Added errdetail and split it
>
> > (5) typo
> >
> > <varlistentry>
> > + <term><literal>EXCEPT TABLE</literal></term>
> > + <listitem>
> > + <para>
> > + This clause specifies a list of tables to exclude from the publication.
> > + It can only be used with <literal>FOR ALL TABLES</literal>.
> > + </para>
> > + </listitem>
> > + </varlistentry>
> > +
> >
> > Kindly change
> > FROM:
> > This clause specifies a list of tables to exclude from the publication.
> > TO:
> > This clause specifies a list of tables to be excluded from the publication.
> > or
> > This clause specifies a list of tables excluded from the publication.
>
> Modified
>
> > (6) Minor suggestion for an expression change
> >
> > Marks the publication as one that replicates changes for all tables in
> > - the database, including tables created in the future.
> > + the database, including tables created in the future. If
> > + <literal>EXCEPT TABLE</literal> is specified, then exclude replicating
> > + the changes for the specified tables.
> >
> >
> > I'll suggest a minor rewording.
> > FROM:
> > ...exclude replicating the changes for the specified tables
> > TO:
> > ...exclude replication changes for the specified tables
>
> I felt the existing is better.
>
> > (7)
> > (7-1)
> >
> > +/*
> > + * Check if the publication has default values
> > + *
> > + * Check the following:
> > + * a) Publication is not set with "FOR ALL TABLES"
> > + * b) Publication is having default options
> > + * c) Publication is not associated with schemas
> > + * d) Publication is not associated with relations
> > + */
> > +static bool
> > +CheckPublicationDefValues(HeapTuple tup)
> >
> >
> > I think this header comment can be improved.
> > FROM:
> > Check the following:
> > TO:
> > Returns true if the publication satisfies all the following conditions:
>
> Modified
>
> > (7-2)
> >
> > b) should be changed as well
> > FROM:
> > Publication is having default options
> > TO:
> > Publication has the default publish operations
>
> Changed it to "Publication is having default publication parameter values"
>
> Thanks for the comments, the attached v8 patch has the changes for the same.

The patch needed to be rebased on top of HEAD because of commit
"0c20dd33db1607d6a85ffce24238c1e55e384b49", attached a rebased v8
version for the changes of the same.

Regards,
Vignesh

Attachment Content-Type Size
v8-0001-Add-RESET-clause-to-Alter-Publication-which-will-.patch application/x-patch 18.5 KB
v8-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch application/x-patch 67.1 KB

From: vignesh C <vignesh21(at)gmail(dot)com>
To: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-08-08 09:23:28
Message-ID: CALDaNm0EKC3o=v+F7GneGibuCULGKkBWXmNaVB4GR9HoqD066A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Aug 8, 2022 at 12:46 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Fri, Jun 3, 2022 at 3:36 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > On Thu, May 26, 2022 at 7:04 PM osumi(dot)takamichi(at)fujitsu(dot)com
> > <osumi(dot)takamichi(at)fujitsu(dot)com> wrote:
> > >
> > > On Monday, May 23, 2022 2:13 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > > > Attached v7 patch which fixes the buildfarm warning for an unused warning in
> > > > release mode as in [1].
> > > Hi, thank you for the patches.
> > >
> > >
> > > I'll share several review comments.
> > >
> > > For v7-0001.
> > >
> > > (1) I'll suggest some minor rewording.
> > >
> > > + <para>
> > > + The <literal>RESET</literal> clause will reset the publication to the
> > > + default state which includes resetting the publication options, setting
> > > + <literal>ALL TABLES</literal> flag to <literal>false</literal> and
> > > + dropping all relations and schemas that are associated with the publication.
> > >
> > > My suggestion is
> > > "The RESET clause will reset the publication to the
> > > default state. It resets the publication operations,
> > > sets ALL TABLES flag to false and drops all relations
> > > and schemas associated with the publication."
> >
> > I felt the existing looks better. I would prefer to keep it that way.
> >
> > > (2) typo and rewording
> > >
> > > +/*
> > > + * Reset the publication.
> > > + *
> > > + * Reset the publication options, setting ALL TABLES flag to false and drop
> > > + * all relations and schemas that are associated with the publication.
> > > + */
> > >
> > > The "setting" in this sentence should be "set".
> > >
> > > How about changing like below ?
> > > FROM:
> > > "Reset the publication options, setting ALL TABLES flag to false and drop
> > > all relations and schemas that are associated with the publication."
> > > TO:
> > > "Reset the publication operations, set ALL TABLES flag to false and drop
> > > all relations and schemas associated with the publication."
> >
> > I felt the existing looks better. I would prefer to keep it that way.
> >
> > > (3) AlterPublicationReset
> > >
> > > Do we need to call CacheInvalidateRelcacheAll() or
> > > InvalidatePublicationRels() at the end of
> > > AlterPublicationReset() like AlterPublicationOptions() ?
> >
> > CacheInvalidateRelcacheAll should be called if we change all tables
> > from true to false, else the cache will not be invalidated. Modified
> >
> > >
> > > For v7-0002.
> > >
> > > (4)
> > >
> > > + if (stmt->for_all_tables)
> > > + {
> > > + bool isdefault = CheckPublicationDefValues(tup);
> > > +
> > > + if (!isdefault)
> > > + ereport(ERROR,
> > > + errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
> > > + errmsg("adding ALL TABLES requires the publication to have default publication options, no tables/....
> > > + errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));
> > >
> > >
> > > The errmsg string has three messages for user and is a bit long
> > > (we have two sentences there connected by 'and').
> > > Can't we make it concise and split it into a couple of lines for code readability ?
> > >
> > > I'll suggest a change below.
> > > FROM:
> > > "adding ALL TABLES requires the publication to have default publication options, no tables/schemas associated and ALL TABLES flag should not be set"
> > > TO:
> > > "adding ALL TABLES requires the publication defined not for ALL TABLES"
> > > "to have default publish actions without any associated tables/schemas"
> >
> > Added errdetail and split it
> >
> > > (5) typo
> > >
> > > <varlistentry>
> > > + <term><literal>EXCEPT TABLE</literal></term>
> > > + <listitem>
> > > + <para>
> > > + This clause specifies a list of tables to exclude from the publication.
> > > + It can only be used with <literal>FOR ALL TABLES</literal>.
> > > + </para>
> > > + </listitem>
> > > + </varlistentry>
> > > +
> > >
> > > Kindly change
> > > FROM:
> > > This clause specifies a list of tables to exclude from the publication.
> > > TO:
> > > This clause specifies a list of tables to be excluded from the publication.
> > > or
> > > This clause specifies a list of tables excluded from the publication.
> >
> > Modified
> >
> > > (6) Minor suggestion for an expression change
> > >
> > > Marks the publication as one that replicates changes for all tables in
> > > - the database, including tables created in the future.
> > > + the database, including tables created in the future. If
> > > + <literal>EXCEPT TABLE</literal> is specified, then exclude replicating
> > > + the changes for the specified tables.
> > >
> > >
> > > I'll suggest a minor rewording.
> > > FROM:
> > > ...exclude replicating the changes for the specified tables
> > > TO:
> > > ...exclude replication changes for the specified tables
> >
> > I felt the existing is better.
> >
> > > (7)
> > > (7-1)
> > >
> > > +/*
> > > + * Check if the publication has default values
> > > + *
> > > + * Check the following:
> > > + * a) Publication is not set with "FOR ALL TABLES"
> > > + * b) Publication is having default options
> > > + * c) Publication is not associated with schemas
> > > + * d) Publication is not associated with relations
> > > + */
> > > +static bool
> > > +CheckPublicationDefValues(HeapTuple tup)
> > >
> > >
> > > I think this header comment can be improved.
> > > FROM:
> > > Check the following:
> > > TO:
> > > Returns true if the publication satisfies all the following conditions:
> >
> > Modified
> >
> > > (7-2)
> > >
> > > b) should be changed as well
> > > FROM:
> > > Publication is having default options
> > > TO:
> > > Publication has the default publish operations
> >
> > Changed it to "Publication is having default publication parameter values"
> >
> > Thanks for the comments, the attached v8 patch has the changes for the same.
>
> The patch needed to be rebased on top of HEAD because of commit
> "0c20dd33db1607d6a85ffce24238c1e55e384b49", attached a rebased v8
> version for the changes of the same.

I had missed attaching one of the changes that was present locally.
The updated patch has the changes for the same.

Regards,
Vignesh

Attachment Content-Type Size
v8-0001-Add-RESET-clause-to-Alter-Publication-which-will-.patch text/x-patch 18.5 KB
v8-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch text/x-patch 67.1 KB

From: Nitin Jadhav <nitinjadhavpostgres(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-08-18 07:02:31
Message-ID: CAMm1aWbMsWLKX2m7Cynux_3T8+J-zHx2gm37S=Ly9iL8OBEfsA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

I spent some time on understanding the proposal and the patch. Here
are a few comments wrt the test cases.

> +ALTER PUBLICATION testpub_reset ADD TABLE pub_sch1.tbl1;
> +
> +-- Verify that tables associated with the publication are dropped after RESET
> +\dRp+ testpub_reset
> +ALTER PUBLICATION testpub_reset RESET;
> +\dRp+ testpub_reset
>
> +ALTER PUBLICATION testpub_reset ADD ALL TABLES IN SCHEMA public;
> +
> +-- Verify that schemas associated with the publication are dropped after RESET
> +\dRp+ testpub_reset
> +ALTER PUBLICATION testpub_reset RESET;
> +\dRp+ testpub_reset

The results for the above two cases are the same before and after the
reset. Is there any way to verify that?
---

> +-- Can't add EXCEPT TABLE to 'FOR ALL TABLES' publication
> +ALTER PUBLICATION testpub_reset ADD ALL TABLES EXCEPT TABLE pub_sch1.tbl1;
> +
>
> +-- Can't add EXCEPT TABLE to 'FOR TABLE' publication
> +ALTER PUBLICATION testpub_reset ADD ALL TABLES EXCEPT TABLE pub_sch1.tbl1;
> +
>
> +-- Can't add EXCEPT TABLE to 'FOR ALL TABLES IN SCHEMA' publication
> +ALTER PUBLICATION testpub_reset ADD ALL TABLES EXCEPT TABLE pub_sch1.tbl1;
> +

I did not understand the objective of these tests. I think we need to
improve the comments.

Thanks & Regards,

On Mon, Aug 8, 2022 at 2:53 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Mon, Aug 8, 2022 at 12:46 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > On Fri, Jun 3, 2022 at 3:36 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > >
> > > On Thu, May 26, 2022 at 7:04 PM osumi(dot)takamichi(at)fujitsu(dot)com
> > > <osumi(dot)takamichi(at)fujitsu(dot)com> wrote:
> > > >
> > > > On Monday, May 23, 2022 2:13 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > > > > Attached v7 patch which fixes the buildfarm warning for an unused warning in
> > > > > release mode as in [1].
> > > > Hi, thank you for the patches.
> > > >
> > > >
> > > > I'll share several review comments.
> > > >
> > > > For v7-0001.
> > > >
> > > > (1) I'll suggest some minor rewording.
> > > >
> > > > + <para>
> > > > + The <literal>RESET</literal> clause will reset the publication to the
> > > > + default state which includes resetting the publication options, setting
> > > > + <literal>ALL TABLES</literal> flag to <literal>false</literal> and
> > > > + dropping all relations and schemas that are associated with the publication.
> > > >
> > > > My suggestion is
> > > > "The RESET clause will reset the publication to the
> > > > default state. It resets the publication operations,
> > > > sets ALL TABLES flag to false and drops all relations
> > > > and schemas associated with the publication."
> > >
> > > I felt the existing looks better. I would prefer to keep it that way.
> > >
> > > > (2) typo and rewording
> > > >
> > > > +/*
> > > > + * Reset the publication.
> > > > + *
> > > > + * Reset the publication options, setting ALL TABLES flag to false and drop
> > > > + * all relations and schemas that are associated with the publication.
> > > > + */
> > > >
> > > > The "setting" in this sentence should be "set".
> > > >
> > > > How about changing like below ?
> > > > FROM:
> > > > "Reset the publication options, setting ALL TABLES flag to false and drop
> > > > all relations and schemas that are associated with the publication."
> > > > TO:
> > > > "Reset the publication operations, set ALL TABLES flag to false and drop
> > > > all relations and schemas associated with the publication."
> > >
> > > I felt the existing looks better. I would prefer to keep it that way.
> > >
> > > > (3) AlterPublicationReset
> > > >
> > > > Do we need to call CacheInvalidateRelcacheAll() or
> > > > InvalidatePublicationRels() at the end of
> > > > AlterPublicationReset() like AlterPublicationOptions() ?
> > >
> > > CacheInvalidateRelcacheAll should be called if we change all tables
> > > from true to false, else the cache will not be invalidated. Modified
> > >
> > > >
> > > > For v7-0002.
> > > >
> > > > (4)
> > > >
> > > > + if (stmt->for_all_tables)
> > > > + {
> > > > + bool isdefault = CheckPublicationDefValues(tup);
> > > > +
> > > > + if (!isdefault)
> > > > + ereport(ERROR,
> > > > + errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
> > > > + errmsg("adding ALL TABLES requires the publication to have default publication options, no tables/....
> > > > + errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));
> > > >
> > > >
> > > > The errmsg string has three messages for user and is a bit long
> > > > (we have two sentences there connected by 'and').
> > > > Can't we make it concise and split it into a couple of lines for code readability ?
> > > >
> > > > I'll suggest a change below.
> > > > FROM:
> > > > "adding ALL TABLES requires the publication to have default publication options, no tables/schemas associated and ALL TABLES flag should not be set"
> > > > TO:
> > > > "adding ALL TABLES requires the publication defined not for ALL TABLES"
> > > > "to have default publish actions without any associated tables/schemas"
> > >
> > > Added errdetail and split it
> > >
> > > > (5) typo
> > > >
> > > > <varlistentry>
> > > > + <term><literal>EXCEPT TABLE</literal></term>
> > > > + <listitem>
> > > > + <para>
> > > > + This clause specifies a list of tables to exclude from the publication.
> > > > + It can only be used with <literal>FOR ALL TABLES</literal>.
> > > > + </para>
> > > > + </listitem>
> > > > + </varlistentry>
> > > > +
> > > >
> > > > Kindly change
> > > > FROM:
> > > > This clause specifies a list of tables to exclude from the publication.
> > > > TO:
> > > > This clause specifies a list of tables to be excluded from the publication.
> > > > or
> > > > This clause specifies a list of tables excluded from the publication.
> > >
> > > Modified
> > >
> > > > (6) Minor suggestion for an expression change
> > > >
> > > > Marks the publication as one that replicates changes for all tables in
> > > > - the database, including tables created in the future.
> > > > + the database, including tables created in the future. If
> > > > + <literal>EXCEPT TABLE</literal> is specified, then exclude replicating
> > > > + the changes for the specified tables.
> > > >
> > > >
> > > > I'll suggest a minor rewording.
> > > > FROM:
> > > > ...exclude replicating the changes for the specified tables
> > > > TO:
> > > > ...exclude replication changes for the specified tables
> > >
> > > I felt the existing is better.
> > >
> > > > (7)
> > > > (7-1)
> > > >
> > > > +/*
> > > > + * Check if the publication has default values
> > > > + *
> > > > + * Check the following:
> > > > + * a) Publication is not set with "FOR ALL TABLES"
> > > > + * b) Publication is having default options
> > > > + * c) Publication is not associated with schemas
> > > > + * d) Publication is not associated with relations
> > > > + */
> > > > +static bool
> > > > +CheckPublicationDefValues(HeapTuple tup)
> > > >
> > > >
> > > > I think this header comment can be improved.
> > > > FROM:
> > > > Check the following:
> > > > TO:
> > > > Returns true if the publication satisfies all the following conditions:
> > >
> > > Modified
> > >
> > > > (7-2)
> > > >
> > > > b) should be changed as well
> > > > FROM:
> > > > Publication is having default options
> > > > TO:
> > > > Publication has the default publish operations
> > >
> > > Changed it to "Publication is having default publication parameter values"
> > >
> > > Thanks for the comments, the attached v8 patch has the changes for the same.
> >
> > The patch needed to be rebased on top of HEAD because of commit
> > "0c20dd33db1607d6a85ffce24238c1e55e384b49", attached a rebased v8
> > version for the changes of the same.
>
> I had missed attaching one of the changes that was present locally.
> The updated patch has the changes for the same.
>
> Regards,
> Vignesh


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Nitin Jadhav <nitinjadhavpostgres(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-08-18 14:26:54
Message-ID: CALDaNm00SgB0kJUD=JD7OH+eP9MA8C4gxHjwY=0oBd23+LdqXw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Aug 18, 2022 at 12:33 PM Nitin Jadhav
<nitinjadhavpostgres(at)gmail(dot)com> wrote:
>
> I spent some time on understanding the proposal and the patch. Here
> are a few comments wrt the test cases.
>
> > +ALTER PUBLICATION testpub_reset ADD TABLE pub_sch1.tbl1;
> > +
> > +-- Verify that tables associated with the publication are dropped after RESET
> > +\dRp+ testpub_reset
> > +ALTER PUBLICATION testpub_reset RESET;
> > +\dRp+ testpub_reset
> >
> > +ALTER PUBLICATION testpub_reset ADD ALL TABLES IN SCHEMA public;
> > +
> > +-- Verify that schemas associated with the publication are dropped after RESET
> > +\dRp+ testpub_reset
> > +ALTER PUBLICATION testpub_reset RESET;
> > +\dRp+ testpub_reset
>
> The results for the above two cases are the same before and after the
> reset. Is there any way to verify that?

If you see the expected, first \dRp+ command includes:
+Tables:
+ "pub_sch1.tbl1"
The second \dRp+ does not include the Tables.
We are trying to verify that after reset, the tables will be removed
from the publication.
The second test is similar to the first, the only difference here is
that we test schema instead of tables. i.e we verify that the schemas
will be removed from the publication.

> ---
>
> > +-- Can't add EXCEPT TABLE to 'FOR ALL TABLES' publication
> > +ALTER PUBLICATION testpub_reset ADD ALL TABLES EXCEPT TABLE pub_sch1.tbl1;
> > +
> >
> > +-- Can't add EXCEPT TABLE to 'FOR TABLE' publication
> > +ALTER PUBLICATION testpub_reset ADD ALL TABLES EXCEPT TABLE pub_sch1.tbl1;
> > +
> >
> > +-- Can't add EXCEPT TABLE to 'FOR ALL TABLES IN SCHEMA' publication
> > +ALTER PUBLICATION testpub_reset ADD ALL TABLES EXCEPT TABLE pub_sch1.tbl1;
> > +
>
> I did not understand the objective of these tests. I think we need to
> improve the comments.

There are different publications like "ALL TABLES", "TABLE", "ALL
TABLES IN SCHEMA" publications. Here we are trying to verify that
except tables cannot be added to "ALL TABLES", "TABLE", "ALL TABLES IN
SCHEMA" publications.
If you see the expected file, you will see the following error:
+-- Can't add EXCEPT TABLE to 'FOR ALL TABLES' publication
+ALTER PUBLICATION testpub_reset ADD ALL TABLES EXCEPT TABLE pub_sch1.tbl1;
+ERROR: adding ALL TABLES requires the publication to have default
publication parameter values
+DETAIL: ALL TABLES flag should not be set and no tables/schemas
should be associated.
+HINT: Use ALTER PUBLICATION ... RESET to reset the publication

I felt the existing comment is ok. Let me know if you still feel any
change is required.

Regards,
Vignesh


From: vignesh C <vignesh21(at)gmail(dot)com>
To: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-08-18 17:41:30
Message-ID: CALDaNm1Z1Rmqj9s6P9ZzmrVA9F_vZ_DwwhYAJmsjqmY6dS3-hA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Aug 8, 2022 at 2:53 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Mon, Aug 8, 2022 at 12:46 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > On Fri, Jun 3, 2022 at 3:36 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > >
> > > On Thu, May 26, 2022 at 7:04 PM osumi(dot)takamichi(at)fujitsu(dot)com
> > > <osumi(dot)takamichi(at)fujitsu(dot)com> wrote:
> > > >
> > > > On Monday, May 23, 2022 2:13 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > > > > Attached v7 patch which fixes the buildfarm warning for an unused warning in
> > > > > release mode as in [1].
> > > > Hi, thank you for the patches.
> > > >
> > > >
> > > > I'll share several review comments.
> > > >
> > > > For v7-0001.
> > > >
> > > > (1) I'll suggest some minor rewording.
> > > >
> > > > + <para>
> > > > + The <literal>RESET</literal> clause will reset the publication to the
> > > > + default state which includes resetting the publication options, setting
> > > > + <literal>ALL TABLES</literal> flag to <literal>false</literal> and
> > > > + dropping all relations and schemas that are associated with the publication.
> > > >
> > > > My suggestion is
> > > > "The RESET clause will reset the publication to the
> > > > default state. It resets the publication operations,
> > > > sets ALL TABLES flag to false and drops all relations
> > > > and schemas associated with the publication."
> > >
> > > I felt the existing looks better. I would prefer to keep it that way.
> > >
> > > > (2) typo and rewording
> > > >
> > > > +/*
> > > > + * Reset the publication.
> > > > + *
> > > > + * Reset the publication options, setting ALL TABLES flag to false and drop
> > > > + * all relations and schemas that are associated with the publication.
> > > > + */
> > > >
> > > > The "setting" in this sentence should be "set".
> > > >
> > > > How about changing like below ?
> > > > FROM:
> > > > "Reset the publication options, setting ALL TABLES flag to false and drop
> > > > all relations and schemas that are associated with the publication."
> > > > TO:
> > > > "Reset the publication operations, set ALL TABLES flag to false and drop
> > > > all relations and schemas associated with the publication."
> > >
> > > I felt the existing looks better. I would prefer to keep it that way.
> > >
> > > > (3) AlterPublicationReset
> > > >
> > > > Do we need to call CacheInvalidateRelcacheAll() or
> > > > InvalidatePublicationRels() at the end of
> > > > AlterPublicationReset() like AlterPublicationOptions() ?
> > >
> > > CacheInvalidateRelcacheAll should be called if we change all tables
> > > from true to false, else the cache will not be invalidated. Modified
> > >
> > > >
> > > > For v7-0002.
> > > >
> > > > (4)
> > > >
> > > > + if (stmt->for_all_tables)
> > > > + {
> > > > + bool isdefault = CheckPublicationDefValues(tup);
> > > > +
> > > > + if (!isdefault)
> > > > + ereport(ERROR,
> > > > + errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
> > > > + errmsg("adding ALL TABLES requires the publication to have default publication options, no tables/....
> > > > + errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));
> > > >
> > > >
> > > > The errmsg string has three messages for user and is a bit long
> > > > (we have two sentences there connected by 'and').
> > > > Can't we make it concise and split it into a couple of lines for code readability ?
> > > >
> > > > I'll suggest a change below.
> > > > FROM:
> > > > "adding ALL TABLES requires the publication to have default publication options, no tables/schemas associated and ALL TABLES flag should not be set"
> > > > TO:
> > > > "adding ALL TABLES requires the publication defined not for ALL TABLES"
> > > > "to have default publish actions without any associated tables/schemas"
> > >
> > > Added errdetail and split it
> > >
> > > > (5) typo
> > > >
> > > > <varlistentry>
> > > > + <term><literal>EXCEPT TABLE</literal></term>
> > > > + <listitem>
> > > > + <para>
> > > > + This clause specifies a list of tables to exclude from the publication.
> > > > + It can only be used with <literal>FOR ALL TABLES</literal>.
> > > > + </para>
> > > > + </listitem>
> > > > + </varlistentry>
> > > > +
> > > >
> > > > Kindly change
> > > > FROM:
> > > > This clause specifies a list of tables to exclude from the publication.
> > > > TO:
> > > > This clause specifies a list of tables to be excluded from the publication.
> > > > or
> > > > This clause specifies a list of tables excluded from the publication.
> > >
> > > Modified
> > >
> > > > (6) Minor suggestion for an expression change
> > > >
> > > > Marks the publication as one that replicates changes for all tables in
> > > > - the database, including tables created in the future.
> > > > + the database, including tables created in the future. If
> > > > + <literal>EXCEPT TABLE</literal> is specified, then exclude replicating
> > > > + the changes for the specified tables.
> > > >
> > > >
> > > > I'll suggest a minor rewording.
> > > > FROM:
> > > > ...exclude replicating the changes for the specified tables
> > > > TO:
> > > > ...exclude replication changes for the specified tables
> > >
> > > I felt the existing is better.
> > >
> > > > (7)
> > > > (7-1)
> > > >
> > > > +/*
> > > > + * Check if the publication has default values
> > > > + *
> > > > + * Check the following:
> > > > + * a) Publication is not set with "FOR ALL TABLES"
> > > > + * b) Publication is having default options
> > > > + * c) Publication is not associated with schemas
> > > > + * d) Publication is not associated with relations
> > > > + */
> > > > +static bool
> > > > +CheckPublicationDefValues(HeapTuple tup)
> > > >
> > > >
> > > > I think this header comment can be improved.
> > > > FROM:
> > > > Check the following:
> > > > TO:
> > > > Returns true if the publication satisfies all the following conditions:
> > >
> > > Modified
> > >
> > > > (7-2)
> > > >
> > > > b) should be changed as well
> > > > FROM:
> > > > Publication is having default options
> > > > TO:
> > > > Publication has the default publish operations
> > >
> > > Changed it to "Publication is having default publication parameter values"
> > >
> > > Thanks for the comments, the attached v8 patch has the changes for the same.
> >
> > The patch needed to be rebased on top of HEAD because of commit
> > "0c20dd33db1607d6a85ffce24238c1e55e384b49", attached a rebased v8
> > version for the changes of the same.
>
> I had missed attaching one of the changes that was present locally.
> The updated patch has the changes for the same.

The patch needed to be rebased on top of HEAD because of a recent
commit. The updated v8 patch has the changes for the same.

Regards,
Vignesh

Attachment Content-Type Size
v8-0001-Add-RESET-clause-to-Alter-Publication-which-will-.patch text/x-patch 18.5 KB
v8-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch text/x-patch 67.0 KB

From: Ian Lawrence Barwick <barwick(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-11-04 02:49:46
Message-ID: CAB8KJ=jJGuW=ozKmXZzKDUHZ_-J2ZYGOtJo=i2cnNbSu6=KuYg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

2022年8月19日(金) 2:41 vignesh C <vignesh21(at)gmail(dot)com>:
>
> On Mon, Aug 8, 2022 at 2:53 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > On Mon, Aug 8, 2022 at 12:46 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > >
> > > On Fri, Jun 3, 2022 at 3:36 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > > >
> > > > On Thu, May 26, 2022 at 7:04 PM osumi(dot)takamichi(at)fujitsu(dot)com
> > > > <osumi(dot)takamichi(at)fujitsu(dot)com> wrote:
> > > > >
> > > > > On Monday, May 23, 2022 2:13 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > > > > > Attached v7 patch which fixes the buildfarm warning for an unused warning in
> > > > > > release mode as in [1].
> > > > > Hi, thank you for the patches.
> > > > >
> > > > >
> > > > > I'll share several review comments.
> > > > >
> > > > > For v7-0001.
> > > > >
> > > > > (1) I'll suggest some minor rewording.
> > > > >
> > > > > + <para>
> > > > > + The <literal>RESET</literal> clause will reset the publication to the
> > > > > + default state which includes resetting the publication options, setting
> > > > > + <literal>ALL TABLES</literal> flag to <literal>false</literal> and
> > > > > + dropping all relations and schemas that are associated with the publication.
> > > > >
> > > > > My suggestion is
> > > > > "The RESET clause will reset the publication to the
> > > > > default state. It resets the publication operations,
> > > > > sets ALL TABLES flag to false and drops all relations
> > > > > and schemas associated with the publication."
> > > >
> > > > I felt the existing looks better. I would prefer to keep it that way.
> > > >
> > > > > (2) typo and rewording
> > > > >
> > > > > +/*
> > > > > + * Reset the publication.
> > > > > + *
> > > > > + * Reset the publication options, setting ALL TABLES flag to false and drop
> > > > > + * all relations and schemas that are associated with the publication.
> > > > > + */
> > > > >
> > > > > The "setting" in this sentence should be "set".
> > > > >
> > > > > How about changing like below ?
> > > > > FROM:
> > > > > "Reset the publication options, setting ALL TABLES flag to false and drop
> > > > > all relations and schemas that are associated with the publication."
> > > > > TO:
> > > > > "Reset the publication operations, set ALL TABLES flag to false and drop
> > > > > all relations and schemas associated with the publication."
> > > >
> > > > I felt the existing looks better. I would prefer to keep it that way.
> > > >
> > > > > (3) AlterPublicationReset
> > > > >
> > > > > Do we need to call CacheInvalidateRelcacheAll() or
> > > > > InvalidatePublicationRels() at the end of
> > > > > AlterPublicationReset() like AlterPublicationOptions() ?
> > > >
> > > > CacheInvalidateRelcacheAll should be called if we change all tables
> > > > from true to false, else the cache will not be invalidated. Modified
> > > >
> > > > >
> > > > > For v7-0002.
> > > > >
> > > > > (4)
> > > > >
> > > > > + if (stmt->for_all_tables)
> > > > > + {
> > > > > + bool isdefault = CheckPublicationDefValues(tup);
> > > > > +
> > > > > + if (!isdefault)
> > > > > + ereport(ERROR,
> > > > > + errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
> > > > > + errmsg("adding ALL TABLES requires the publication to have default publication options, no tables/....
> > > > > + errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));
> > > > >
> > > > >
> > > > > The errmsg string has three messages for user and is a bit long
> > > > > (we have two sentences there connected by 'and').
> > > > > Can't we make it concise and split it into a couple of lines for code readability ?
> > > > >
> > > > > I'll suggest a change below.
> > > > > FROM:
> > > > > "adding ALL TABLES requires the publication to have default publication options, no tables/schemas associated and ALL TABLES flag should not be set"
> > > > > TO:
> > > > > "adding ALL TABLES requires the publication defined not for ALL TABLES"
> > > > > "to have default publish actions without any associated tables/schemas"
> > > >
> > > > Added errdetail and split it
> > > >
> > > > > (5) typo
> > > > >
> > > > > <varlistentry>
> > > > > + <term><literal>EXCEPT TABLE</literal></term>
> > > > > + <listitem>
> > > > > + <para>
> > > > > + This clause specifies a list of tables to exclude from the publication.
> > > > > + It can only be used with <literal>FOR ALL TABLES</literal>.
> > > > > + </para>
> > > > > + </listitem>
> > > > > + </varlistentry>
> > > > > +
> > > > >
> > > > > Kindly change
> > > > > FROM:
> > > > > This clause specifies a list of tables to exclude from the publication.
> > > > > TO:
> > > > > This clause specifies a list of tables to be excluded from the publication.
> > > > > or
> > > > > This clause specifies a list of tables excluded from the publication.
> > > >
> > > > Modified
> > > >
> > > > > (6) Minor suggestion for an expression change
> > > > >
> > > > > Marks the publication as one that replicates changes for all tables in
> > > > > - the database, including tables created in the future.
> > > > > + the database, including tables created in the future. If
> > > > > + <literal>EXCEPT TABLE</literal> is specified, then exclude replicating
> > > > > + the changes for the specified tables.
> > > > >
> > > > >
> > > > > I'll suggest a minor rewording.
> > > > > FROM:
> > > > > ...exclude replicating the changes for the specified tables
> > > > > TO:
> > > > > ...exclude replication changes for the specified tables
> > > >
> > > > I felt the existing is better.
> > > >
> > > > > (7)
> > > > > (7-1)
> > > > >
> > > > > +/*
> > > > > + * Check if the publication has default values
> > > > > + *
> > > > > + * Check the following:
> > > > > + * a) Publication is not set with "FOR ALL TABLES"
> > > > > + * b) Publication is having default options
> > > > > + * c) Publication is not associated with schemas
> > > > > + * d) Publication is not associated with relations
> > > > > + */
> > > > > +static bool
> > > > > +CheckPublicationDefValues(HeapTuple tup)
> > > > >
> > > > >
> > > > > I think this header comment can be improved.
> > > > > FROM:
> > > > > Check the following:
> > > > > TO:
> > > > > Returns true if the publication satisfies all the following conditions:
> > > >
> > > > Modified
> > > >
> > > > > (7-2)
> > > > >
> > > > > b) should be changed as well
> > > > > FROM:
> > > > > Publication is having default options
> > > > > TO:
> > > > > Publication has the default publish operations
> > > >
> > > > Changed it to "Publication is having default publication parameter values"
> > > >
> > > > Thanks for the comments, the attached v8 patch has the changes for the same.
> > >
> > > The patch needed to be rebased on top of HEAD because of commit
> > > "0c20dd33db1607d6a85ffce24238c1e55e384b49", attached a rebased v8
> > > version for the changes of the same.
> >
> > I had missed attaching one of the changes that was present locally.
> > The updated patch has the changes for the same.
>
> The patch needed to be rebased on top of HEAD because of a recent
> commit. The updated v8 patch has the changes for the same.

Hi

cfbot reports the patch no longer applies [1]. As CommitFest 2022-11 is
currently underway, this would be an excellent time to update the patch.

[1] http://cfbot.cputube.org/patch_40_3646.log

Thanks

Ian Barwick


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Ian Lawrence Barwick <barwick(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-11-07 13:39:41
Message-ID: CALDaNm1mbFP8fxHU_H1Ex4cT2Aq3n8FE79tq0TO5ThvFnDUYMA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 4 Nov 2022 at 08:19, Ian Lawrence Barwick <barwick(at)gmail(dot)com> wrote:
>
> Hi
>
> cfbot reports the patch no longer applies [1]. As CommitFest 2022-11 is
> currently underway, this would be an excellent time to update the patch.
>
> [1] http://cfbot.cputube.org/patch_40_3646.log

Here is an updated patch which is rebased on top of HEAD.

Regards,
Vignesh

Attachment Content-Type Size
v9-0001-Add-RESET-clause-to-Alter-Publication-which-will-.patch text/x-patch 17.8 KB
v9-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch text/x-patch 66.6 KB

From: Ian Lawrence Barwick <barwick(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-11-16 04:04:18
Message-ID: CAB8KJ=jq4RwTs8K7pokmXQwQppP2ChVJLMSAdXaxAX+c1r+mdg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

2022年11月7日(月) 22:39 vignesh C <vignesh21(at)gmail(dot)com>:
>
> On Fri, 4 Nov 2022 at 08:19, Ian Lawrence Barwick <barwick(at)gmail(dot)com> wrote:
> >
> > Hi
> >
> > cfbot reports the patch no longer applies [1]. As CommitFest 2022-11 is
> > currently underway, this would be an excellent time to update the patch.
> >
> > [1] http://cfbot.cputube.org/patch_40_3646.log
>
> Here is an updated patch which is rebased on top of HEAD.

Thanks for the updated patch.

While reviewing the patch backlog, we have determined that this patch adds
one or more TAP tests but has not added the test to the "meson.build" file.

To do this, locate the relevant "meson.build" file for each test and add it
in the 'tests' dictionary, which will look something like this:

'tap': {
'tests': [
't/001_basic.pl',
],
},

For some additional details please see this Wiki article:

https://wiki.postgresql.org/wiki/Meson_for_patch_authors

For more information on the meson build system for PostgreSQL see:

https://wiki.postgresql.org/wiki/Meson

Regards

Ian Barwick


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Ian Lawrence Barwick <barwick(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2022-11-16 10:05:31
Message-ID: CALDaNm1mJvLni8GODebKBmyegXuZ18bLoG-Pz6H1MCX=vphCYA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 16 Nov 2022 at 09:34, Ian Lawrence Barwick <barwick(at)gmail(dot)com> wrote:
>
> 2022年11月7日(月) 22:39 vignesh C <vignesh21(at)gmail(dot)com>:
> >
> > On Fri, 4 Nov 2022 at 08:19, Ian Lawrence Barwick <barwick(at)gmail(dot)com> wrote:
> > >
> > > Hi
> > >
> > > cfbot reports the patch no longer applies [1]. As CommitFest 2022-11 is
> > > currently underway, this would be an excellent time to update the patch.
> > >
> > > [1] http://cfbot.cputube.org/patch_40_3646.log
> >
> > Here is an updated patch which is rebased on top of HEAD.
>
> Thanks for the updated patch.
>
> While reviewing the patch backlog, we have determined that this patch adds
> one or more TAP tests but has not added the test to the "meson.build" file.

Thanks, I have updated the meson.build to include the TAP test. The
attached patch has the changes for the same.

Regards,
Vignesh

Attachment Content-Type Size
v9-0001-Add-RESET-clause-to-Alter-Publication-which-will-.patch text/x-patch 17.8 KB
v9-0002-Skip-publishing-the-tables-specified-in-EXCEPT-TA.patch text/x-patch 67.1 KB

From: vignesh C <vignesh21(at)gmail(dot)com>
To: Ian Lawrence Barwick <barwick(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2023-01-20 10:00:54
Message-ID: CALDaNm3dWZCYDih55qTNAYsjCvYXMFv=46UsDWmfCnXMt3kPCg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 16 Nov 2022 at 15:35, vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Wed, 16 Nov 2022 at 09:34, Ian Lawrence Barwick <barwick(at)gmail(dot)com> wrote:
> >
> > 2022年11月7日(月) 22:39 vignesh C <vignesh21(at)gmail(dot)com>:
> > >
> > > On Fri, 4 Nov 2022 at 08:19, Ian Lawrence Barwick <barwick(at)gmail(dot)com> wrote:
> > > >
> > > > Hi
> > > >
> > > > cfbot reports the patch no longer applies [1]. As CommitFest 2022-11 is
> > > > currently underway, this would be an excellent time to update the patch.
> > > >
> > > > [1] http://cfbot.cputube.org/patch_40_3646.log
> > >
> > > Here is an updated patch which is rebased on top of HEAD.
> >
> > Thanks for the updated patch.
> >
> > While reviewing the patch backlog, we have determined that this patch adds
> > one or more TAP tests but has not added the test to the "meson.build" file.
>
> Thanks, I have updated the meson.build to include the TAP test. The
> attached patch has the changes for the same.

The patch was not applying on top of HEAD, attached a rebased version.

Regards,
Vignesh

Attachment Content-Type Size
v10-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch text/x-patch 18.2 KB
v10-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch text/x-patch 67.1 KB

From: vignesh C <vignesh21(at)gmail(dot)com>
To: Ian Lawrence Barwick <barwick(at)gmail(dot)com>
Cc: "osumi(dot)takamichi(at)fujitsu(dot)com" <osumi(dot)takamichi(at)fujitsu(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2024-01-09 06:32:04
Message-ID: CALDaNm1AQZYgT0tALRrkvpP1Q+8+e7vkGCUjQ-jim1C0q3e=zA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 20 Jan 2023 at 15:30, vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Wed, 16 Nov 2022 at 15:35, vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > On Wed, 16 Nov 2022 at 09:34, Ian Lawrence Barwick <barwick(at)gmail(dot)com> wrote:
> > >
> > > 2022年11月7日(月) 22:39 vignesh C <vignesh21(at)gmail(dot)com>:
> > > >
> > > > On Fri, 4 Nov 2022 at 08:19, Ian Lawrence Barwick <barwick(at)gmail(dot)com> wrote:
> > > > >
> > > > > Hi
> > > > >
> > > > > cfbot reports the patch no longer applies [1]. As CommitFest 2022-11 is
> > > > > currently underway, this would be an excellent time to update the patch.
> > > > >
> > > > > [1] http://cfbot.cputube.org/patch_40_3646.log
> > > >
> > > > Here is an updated patch which is rebased on top of HEAD.
> > >
> > > Thanks for the updated patch.
> > >
> > > While reviewing the patch backlog, we have determined that this patch adds
> > > one or more TAP tests but has not added the test to the "meson.build" file.
> >
> > Thanks, I have updated the meson.build to include the TAP test. The
> > attached patch has the changes for the same.
>
> The patch was not applying on top of HEAD, attached a rebased version.

As I did not see much interest from others, I'm withdrawing this patch
for now. But if there is any interest others in future, I would be
more than happy to work on this feature.

Regards,
Vignesh


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>
Cc: Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-04-10 11:24:57
Message-ID: CAA4eK1KRdAPC=5=7tQ1GW0cRwD=zaDMi+T4u_k4GxPhPY6e8BQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Jan 9, 2024 at 12:02 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> As I did not see much interest from others, I'm withdrawing this patch
> for now. But if there is any interest others in future, I would be
> more than happy to work on this feature.
>

Just FYI, I noticed a use case for this patch in email [1]. Users
would like to replicate all except a few columns having sensitive
information. The challenge with current column list features is that
adding new tables to columns would lead users to change the respective
publications as well.

[1] - https://www.postgresql.org/message-id/tencent_DCDF626FCD4A556C51BE270FDC3047540208%40qq.com

--
With Regards,
Amit Kapila.


From: "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>
Cc: Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Skipping schema changes in publication
Date: 2025-04-16 02:52:29
Message-ID: OS3PR01MB5718C8BE84B862E7E0CEC29B94BD2@OS3PR01MB5718.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Apr 10, 2025 at 7:25 PM Amit Kapila wrote:
>
> On Tue, Jan 9, 2024 at 12:02 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > As I did not see much interest from others, I'm withdrawing this patch
> > for now. But if there is any interest others in future, I would be
> > more than happy to work on this feature.
> >
>
> Just FYI, I noticed a use case for this patch in email [1]. Users would like to
> replicate all except a few columns having sensitive information. The challenge
> with current column list features is that adding new tables to columns would
> lead users to change the respective publications as well.
>
> [1] -
> https://www.postgresql.org/message-id/tencent_DCDF626FCD4A556C51BE
> 270FDC3047540208%40qq.com

BTW, I noticed that debezium, an open source distributed platform for change
data capture that replies on logical decoding, also support specifying the
column exclusion list[1]. So, this indicates that there could be some use cases
for this feature.

https://debezium.io/documentation/reference/stable/connectors/postgresql.html#postgresql-property-column-exclude-list

Best Regards,
Hou zj


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-04-17 03:42:22
Message-ID: CAA4eK1KYQz7cf46_D=6VkZ4J6Y8vJ88MMi=6zm2TJXDP+V1mLg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Apr 16, 2025 at 8:22 AM Zhijie Hou (Fujitsu)
<houzj(dot)fnst(at)fujitsu(dot)com> wrote:
>
> On Thu, Apr 10, 2025 at 7:25 PM Amit Kapila wrote:
> >
> > On Tue, Jan 9, 2024 at 12:02 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > >
> > > As I did not see much interest from others, I'm withdrawing this patch
> > > for now. But if there is any interest others in future, I would be
> > > more than happy to work on this feature.
> > >
> >
> > Just FYI, I noticed a use case for this patch in email [1]. Users would like to
> > replicate all except a few columns having sensitive information. The challenge
> > with current column list features is that adding new tables to columns would
> > lead users to change the respective publications as well.
> >
> > [1] -
> > https://www.postgresql.org/message-id/tencent_DCDF626FCD4A556C51BE
> > 270FDC3047540208%40qq.com
>
> BTW, I noticed that debezium, an open source distributed platform for change
> data capture that replies on logical decoding, also support specifying the
> column exclusion list[1]. So, this indicates that there could be some use cases
> for this feature.
>

Thanks for sharing the link. I see that they support both the include
and exclude lists for columns and tables.

--
With Regards,
Amit Kapila.


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-06-11 14:07:49
Message-ID: CANhcyEXZq4mP5dNgg7u=sMPwvxA4_ZN9U92uZEuzs=0xTu+8Yg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 17 Apr 2025 at 09:12, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Wed, Apr 16, 2025 at 8:22 AM Zhijie Hou (Fujitsu)
> <houzj(dot)fnst(at)fujitsu(dot)com> wrote:
> >
> > On Thu, Apr 10, 2025 at 7:25 PM Amit Kapila wrote:
> > >
> > > On Tue, Jan 9, 2024 at 12:02 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > > >
> > > > As I did not see much interest from others, I'm withdrawing this patch
> > > > for now. But if there is any interest others in future, I would be
> > > > more than happy to work on this feature.
> > > >
> > >
> > > Just FYI, I noticed a use case for this patch in email [1]. Users would like to
> > > replicate all except a few columns having sensitive information. The challenge
> > > with current column list features is that adding new tables to columns would
> > > lead users to change the respective publications as well.
> > >
> > > [1] -
> > > https://www.postgresql.org/message-id/tencent_DCDF626FCD4A556C51BE
> > > 270FDC3047540208%40qq.com
> >
> > BTW, I noticed that debezium, an open source distributed platform for change
> > data capture that replies on logical decoding, also support specifying the
> > column exclusion list[1]. So, this indicates that there could be some use cases
> > for this feature.
> >
>
> Thanks for sharing the link. I see that they support both the include
> and exclude lists for columns and tables.
>

Hi Hackers,

I see there is some interest in the functionality added by this patch.
I have rebased the patches in [1]. I saw a new column 'pubgencols' was
added in pg_publication in PG 18. So, I have modified v11-0001 to
RESET this as well.
I am also working on creating a patch to exclude columns in
publication as per suggestion in [2].

[1]: https://www.postgresql.org/message-id/CALDaNm3dWZCYDih55qTNAYsjCvYXMFv%3D46UsDWmfCnXMt3kPCg%40mail.gmail.com
[2]: https://www.postgresql.org/message-id/CAA4eK1KRdAPC%3D5%3D7tQ1GW0cRwD%3DzaDMi%2BT4u_k4GxPhPY6e8BQ%40mail.gmail.com

Thanks and Regards,
Shlok Kyal

Attachment Content-Type Size
v11-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 20.5 KB
v11-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 68.8 KB

From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-06-17 07:41:34
Message-ID: CANhcyEXspT3v5-Tdop9uqQV2HWBvZoN5P0BxXQ6Md6Mr7GXK9A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 11 Jun 2025 at 19:37, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> On Thu, 17 Apr 2025 at 09:12, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> > On Wed, Apr 16, 2025 at 8:22 AM Zhijie Hou (Fujitsu)
> > <houzj(dot)fnst(at)fujitsu(dot)com> wrote:
> > >
> > > On Thu, Apr 10, 2025 at 7:25 PM Amit Kapila wrote:
> > > >
> > > > On Tue, Jan 9, 2024 at 12:02 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > > > >
> > > > > As I did not see much interest from others, I'm withdrawing this patch
> > > > > for now. But if there is any interest others in future, I would be
> > > > > more than happy to work on this feature.
> > > > >
> > > >
> > > > Just FYI, I noticed a use case for this patch in email [1]. Users would like to
> > > > replicate all except a few columns having sensitive information. The challenge
> > > > with current column list features is that adding new tables to columns would
> > > > lead users to change the respective publications as well.
> > > >
> > > > [1] -
> > > > https://www.postgresql.org/message-id/tencent_DCDF626FCD4A556C51BE
> > > > 270FDC3047540208%40qq.com
> > >
> > > BTW, I noticed that debezium, an open source distributed platform for change
> > > data capture that replies on logical decoding, also support specifying the
> > > column exclusion list[1]. So, this indicates that there could be some use cases
> > > for this feature.
> > >
> >
> > Thanks for sharing the link. I see that they support both the include
> > and exclude lists for columns and tables.
> >
>
> Hi Hackers,
>
> I see there is some interest in the functionality added by this patch.
> I have rebased the patches in [1]. I saw a new column 'pubgencols' was
> added in pg_publication in PG 18. So, I have modified v11-0001 to
> RESET this as well.
> I am also working on creating a patch to exclude columns in
> publication as per suggestion in [2].
>
> [1]: https://www.postgresql.org/message-id/CALDaNm3dWZCYDih55qTNAYsjCvYXMFv%3D46UsDWmfCnXMt3kPCg%40mail.gmail.com
> [2]: https://www.postgresql.org/message-id/CAA4eK1KRdAPC%3D5%3D7tQ1GW0cRwD%3DzaDMi%2BT4u_k4GxPhPY6e8BQ%40mail.gmail.com
>

I have attached a patch support excluding columns for publication.

I have added a syntax: "FOR TABLE table_name EXCEPT (c1, c2, ..)"
It can be used with CREATE or ALTER PUBLICATION.

v12-0003 patch contains the changes for the same.

Thanks and Regards,
Shlok Kyal

Attachment Content-Type Size
v12-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 20.5 KB
v12-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 68.8 KB
v12-0003-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 45.5 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-06-18 01:04:31
Message-ID: CAHut+PuiaLOCkiAx9nPnjk6wTbPFvnm9T5svTuKbgwJwTdea8w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Jun 17, 2025 at 5:41 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
...
> I have attached a patch support excluding columns for publication.
>
> I have added a syntax: "FOR TABLE table_name EXCEPT (c1, c2, ..)"
> It can be used with CREATE or ALTER PUBLICATION.
>
> v12-0003 patch contains the changes for the same.
>

Hi Shlok,

I was interested in your new EXCEPT (col-list) so I had a quick look
at your patch v12-0003 (only looked at the documentation).

Below are some comments:

======

1. Chapter 29.5 "Column Lists".

I think new EXCEPT syntax needs a mention here as well.

======

doc/src/sgml/catalogs.sgml

2.
+ <para>
+ This is an array of values that indicates which table columns are
+ excluded from the publication. For example, a value of
+ <literal>1 3</literal> would mean that the columns except the first and
+ the third columns are published.
+ A null value indicates that no columns are excluded from being
published.
+ </para></entry>

The sentence "A null value indicates that no columns are excluded from
being published" seems kind of confusing, because if the user has a
"normal" column-list although nothing was being *explicitly* excluded
(using EXCEPT), any columns not named are *implicitly* excluded from
being published.

~

3.
TBH, I was wondering why a new catalog attribute was necessary...

Can't you simply re-use the existing attribute "prattrs" attribute.
e.g. let's just define negative means exclude.

e.g. a value of 1 3 means only the 1st and 3rd columns are published
e.g. a value of -1 -3 means all columns except 1st and 3rd columns are published
e.g. a value of null mean all columns are published

(mixes of negative and positive will not be possible)

======

doc/src/sgml/ref/alter_publication.sgml

4. ALTER PUBLICATION syntax

The syntax is currently written as:
TABLE [ ONLY ] table_name [ * ] { [ [ ( column_name [, ... ] ) ] | [
EXCEPT ( column_name [, ... ] ) ] ] } [ WHERE ( expression ) ] [, ...
]

Can't this be more simply written as:
TABLE [ ONLY ] table_name [ * ] [ [ EXCEPT ] ( column_name [, ... ] )
] [ WHERE ( expression ) ] [, ... ]

~~~

5.
+ <para>
+ Alter publication <structname>mypublication</structname> to add table
+ <structname>users</structname> except column
+ <structname>security_pin</structname>:
+<programlisting>
+ALTER PUBLICATION production_publication ADD TABLE users EXCEPT (security_pin);

Those tags don't seem correct. e.g. "users" and "security_pin" are not
<structname> (???).

Perhaps, every other example here is wrong too and you just copied
them? Anyway, something here looks wrong to me.

======
doc/src/sgml/ref/create_publication.sgml

6. CREATE PUBLICATION syntax

The syntax is currently written as:
TABLE [ ONLY ] table_name [ * ] { [ [ ( column_name [, ... ] ) ] | [
EXCEPT ( column_name [, ... ] ) ] ] } [ WHERE ( expression ) ] [, ...
]

Can't this be more simply written as:
TABLE [ ONLY ] table_name [ * ] [ [ EXCEPT ] ( column_name [, ... ] )
] [ WHERE ( expression ) ] [, ... ]

~~~

7.
+ <para>
+ When a column list is specified with EXCEPT, the named columns are not
+ replicated. The excluded column list cannot contain generated
columns. The
+ column list and excluded column list cannot be specified together.
+ Specifying a column list has no effect on <literal>TRUNCATE</literal>
+ commands.
+ </para>

IMO you don't need to say "The column list and excluded column list
cannot be specified together." because AFAIK the syntax makes that
impossible to do anyhow.

~~~

8.
+ <para>
+ Create a publication that publishes all changes for table
<structname>users</structname>
+ except changes for columns <structname>security_pin</structname>:
+<programlisting>
+CREATE PUBLICATION users_safe FOR TABLE users EXCEPT (security_pin);
+</programlisting>
+ </para>

8a.
Same review comment as previously -- Those tags don't seem correct.
e.g. "users" and "security_pin" are not <structname> (???).
Again, are all the other existing tags also wrong? Maybe a new thread
needed to address these?

~

8b.
Plural? /except changes for columns/except changes for column/

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-06-19 06:41:48
Message-ID: CANhcyEV_MePxgftHY65et1WdOAk70M0C7PZ1STPUO8PXHVB1YA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 18 Jun 2025 at 06:34, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> On Tue, Jun 17, 2025 at 5:41 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> ...
> > I have attached a patch support excluding columns for publication.
> >
> > I have added a syntax: "FOR TABLE table_name EXCEPT (c1, c2, ..)"
> > It can be used with CREATE or ALTER PUBLICATION.
> >
> > v12-0003 patch contains the changes for the same.
> >
>
> Hi Shlok,
>
> I was interested in your new EXCEPT (col-list) so I had a quick look
> at your patch v12-0003 (only looked at the documentation).
>
> Below are some comments:
>
> ======
>
> 1. Chapter 29.5 "Column Lists".
>
> I think new EXCEPT syntax needs a mention here as well.
>
Added

> ======
>
> doc/src/sgml/catalogs.sgml
>
> 2.
> + <para>
> + This is an array of values that indicates which table columns are
> + excluded from the publication. For example, a value of
> + <literal>1 3</literal> would mean that the columns except the first and
> + the third columns are published.
> + A null value indicates that no columns are excluded from being
> published.
> + </para></entry>
>
> The sentence "A null value indicates that no columns are excluded from
> being published" seems kind of confusing, because if the user has a
> "normal" column-list although nothing was being *explicitly* excluded
> (using EXCEPT), any columns not named are *implicitly* excluded from
> being published.
>
I have removed this line.

> ~
>
> 3.
> TBH, I was wondering why a new catalog attribute was necessary...
>
> Can't you simply re-use the existing attribute "prattrs" attribute.
> e.g. let's just define negative means exclude.
>
> e.g. a value of 1 3 means only the 1st and 3rd columns are published
> e.g. a value of -1 -3 means all columns except 1st and 3rd columns are published
> e.g. a value of null mean all columns are published
>
> (mixes of negative and positive will not be possible)
>

Currently I have added a new attribute 'prexcludeattrs' in
pg_publication_rel table. I used this approach because it will be
easier for user to get the exclude column list, in code no extra
processing is required to get the exclude column list.

For an approach to use negative numbers for exclude columns. I see an
advantage that we do not need to introduce a new column for
pg_publication_rel. But in code, each time we want to get a column
list or exclude column list we need an extra processing of 'prattrs'
columns. Also I don't see any existing catalog table using a negative
attribute for column list.

Based on above observations, I feel that the current is better.

Please correct me if I missed an advantage for the approach you suggested.

> ======
>
> doc/src/sgml/ref/alter_publication.sgml
>
> 4. ALTER PUBLICATION syntax
>
> The syntax is currently written as:
> TABLE [ ONLY ] table_name [ * ] { [ [ ( column_name [, ... ] ) ] | [
> EXCEPT ( column_name [, ... ] ) ] ] } [ WHERE ( expression ) ] [, ...
> ]
>
> Can't this be more simply written as:
> TABLE [ ONLY ] table_name [ * ] [ [ EXCEPT ] ( column_name [, ... ] )
> ] [ WHERE ( expression ) ] [, ... ]
>
> ~~~
Fixed

>
> 5.
> + <para>
> + Alter publication <structname>mypublication</structname> to add table
> + <structname>users</structname> except column
> + <structname>security_pin</structname>:
> +<programlisting>
> +ALTER PUBLICATION production_publication ADD TABLE users EXCEPT (security_pin);
>
> Those tags don't seem correct. e.g. "users" and "security_pin" are not
> <structname> (???).
>
> Perhaps, every other example here is wrong too and you just copied
> them? Anyway, something here looks wrong to me.
>
I saw different documents and usage of tags seems not well defined.
For example for table we are using tags in document
create_publication.sgml, update.sgml <structname> is used, in document
table.sgml, advanced.sgml <classname> is used, and in
logical-replication.sgml <literal> is used. Similarly for column
names <structname>, <structfield> or <literal> are used in different
parts of the document.

I kept the changed tag to <structfield> for the column for this patch.
Do you have any suggestions?

> ======
> doc/src/sgml/ref/create_publication.sgml
>
> 6. CREATE PUBLICATION syntax
>
> The syntax is currently written as:
> TABLE [ ONLY ] table_name [ * ] { [ [ ( column_name [, ... ] ) ] | [
> EXCEPT ( column_name [, ... ] ) ] ] } [ WHERE ( expression ) ] [, ...
> ]
>
> Can't this be more simply written as:
> TABLE [ ONLY ] table_name [ * ] [ [ EXCEPT ] ( column_name [, ... ] )
> ] [ WHERE ( expression ) ] [, ... ]
>
> ~~~
Fixed

>
> 7.
> + <para>
> + When a column list is specified with EXCEPT, the named columns are not
> + replicated. The excluded column list cannot contain generated
> columns. The
> + column list and excluded column list cannot be specified together.
> + Specifying a column list has no effect on <literal>TRUNCATE</literal>
> + commands.
> + </para>
>
> IMO you don't need to say "The column list and excluded column list
> cannot be specified together." because AFAIK the syntax makes that
> impossible to do anyhow.
>
Removed this line

> ~~~
>
> 8.
> + <para>
> + Create a publication that publishes all changes for table
> <structname>users</structname>
> + except changes for columns <structname>security_pin</structname>:
> +<programlisting>
> +CREATE PUBLICATION users_safe FOR TABLE users EXCEPT (security_pin);
> +</programlisting>
> + </para>
>
> 8a.
> Same review comment as previously -- Those tags don't seem correct.
> e.g. "users" and "security_pin" are not <structname> (???).
> Again, are all the other existing tags also wrong? Maybe a new thread
> needed to address these?
>
> ~
Same as point 5.
I also feel this should be addressed in a new thread.

> 8b.
> Plural? /except changes for columns/except changes for column/
Fixed

Also in this patch I added displaying "EXCEPT (column_list)" for \dRp+
and \d table_name psql commands.

Thanks and Regards,
Shlok Kyal

Attachment Content-Type Size
v13-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 20.5 KB
v13-0003-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 64.3 KB
v13-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 68.8 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-06-20 03:57:39
Message-ID: CAHut+Ps0hSNqrjv_jT1AuXxO-CrZue3ixE0jKsxVhtArMrkujQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Jun 19, 2025 at 4:42 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
...
> > 3.
> > TBH, I was wondering why a new catalog attribute was necessary...
> >
> > Can't you simply re-use the existing attribute "prattrs" attribute.
> > e.g. let's just define negative means exclude.
> >
> > e.g. a value of 1 3 means only the 1st and 3rd columns are published
> > e.g. a value of -1 -3 means all columns except 1st and 3rd columns are published
> > e.g. a value of null mean all columns are published
> >
> > (mixes of negative and positive will not be possible)
> >
>
> Currently I have added a new attribute 'prexcludeattrs' in
> pg_publication_rel table. I used this approach because it will be
> easier for user to get the exclude column list, in code no extra
> processing is required to get the exclude column list.
>
> For an approach to use negative numbers for exclude columns. I see an
> advantage that we do not need to introduce a new column for
> pg_publication_rel. But in code, each time we want to get a column
> list or exclude column list we need an extra processing of 'prattrs'
> columns. Also I don't see any existing catalog table using a negative
> attribute for column list.
>
> Based on above observations, I feel that the current is better.
>
> Please correct me if I missed an advantage for the approach you suggested.
>

OK. Maybe using negative numbers was a bridge too far...

But IMO it is not good to have 2 separate attributes for the lists.
Doing so implies they can coexist, but that is not true. I felt there
are not really 2 "kinds" of columns list anyway -- there is just a
"column list" which defines columns that are either included or
excluded from the publication determined by EXCEPT.

Having dual lists gets weird/confusing to describe them -- you end up
continually having to refer to the other one to clarify behaviour.

e.g. Does 'prattrs' value NULL mean publish everything? Well, no...
that depends if there is a non null 'prexcludeattrs'
e.g. Does 'prexcludeattrs' value NULL mean publish everything? Well,
no... that depends if there is a non null 'prattrs'

Furthermore, all the code is doubling up referring to "column list"
and "exclude column list" -- code / docs / comments / error messages.
There are quite a lot of places the patch touches that I thought were
not really needed if you don't have 2 different kinds of column-lists.

To summarise, I felt it would be better to just keep the existing
'prattrs' as the one-and-only column list, but add another BOOLEAN
attribute to flag whether 'prattrs' columns should be included or
excluded.

prattrs; prattrs_exclude; Means
--------------------------------------------
1 2 3 f only cols 1,2,3 will be published
4 5 6 t only cols 4,5,6 will NOT be published
null f all cols are published (flag is ignored)
null t all cols are published (flag is ignored)

> > 5.
> > + <para>
> > + Alter publication <structname>mypublication</structname> to add table
> > + <structname>users</structname> except column
> > + <structname>security_pin</structname>:
> > +<programlisting>
> > +ALTER PUBLICATION production_publication ADD TABLE users EXCEPT (security_pin);
> >
> > Those tags don't seem correct. e.g. "users" and "security_pin" are not
> > <structname> (???).
> >
> > Perhaps, every other example here is wrong too and you just copied
> > them? Anyway, something here looks wrong to me.
> >
> I saw different documents and usage of tags seems not well defined.
> For example for table we are using tags in document
> create_publication.sgml, update.sgml <structname> is used, in document
> table.sgml, advanced.sgml <classname> is used, and in
> logical-replication.sgml <literal> is used. Similarly for column
> names <structname>, <structfield> or <literal> are used in different
> parts of the document.
>
> I kept the changed tag to <structfield> for the column for this patch.
> Do you have any suggestions?

No, for this patch I think it is best that you just follow nearby code
(as you are already doing). I plan to raise another thread to ask what
are the guidelines for this sort of markup which is currently used
inconsistently in different places.

//////////

Below are a few more review comments for v13-0003

======
Commit message

1.
Typo /THe/The/

~~~

2.
The new syntax allows specifying excluded column list when creating or
altering a publication. For example:
CREATE PUBLICATION pubname FOR TABLE tabname EXCEPT (exclude_column_list)
or
ALTER PUBLICATION pubname ADD TABLE tabname EXCEPT (exclude_column_list)

~

I felt since you say these "For example:" it would be better to give
real examples.
e.g. say "(col1,col2,col3)" instead of "(exclude_column_list)".

~~~

3.
Typo /family of command/family of commands/

======
doc/src/sgml/logical-replication.sgml

4.
I am not sure that it was a good idea to be making a new term called
an "exclude column list"... because in introduces a new concept of
something that sounds like it is a different kind of list, and now you
have to keep referring everywhere to both to "column list" versus
"exclude column list". All the doubling up add more complication I
think.

IMO really there is just a "column list". Whether that list is for
exclusion or not just depends on the presence of EXCEPT. So I felt
maybe all places mentioning "exclude column list" could be rephrased.

======
src/backend/catalog/pg_publication.c

5.
+/*
+ * Returns true if the relation has exluded column list associated with the
+ * publication, false otherwise.
+ *
+ * If a exclude column list is found, the corresponding bitmap is returned
+ * through the cols parameter, if provided. The bitmap is constructed
within the
+ * given memory context (mcxt).
+ */
+

Typo /exluded column/an excluded column/
Typo /exclude column list/excluded column list/

~~~

6.
+/*
+ * pub_exclude_collist_validate
+ * Process and validate the 'excluded columns' list and ensure the columns
+ * are all valid to exclude from publication. Checks for and raises an
+ * ERROR for any unknown columns, system columns, duplicate columns, or
+ * generated columns.
+ *

Why can't you exclude generated columns?

e.g. Maybe PUBLICATION says publish_generated_columns=stored and there
are 100s of such columns, but the user just wants to exclude one of
them. Why say they cannot do that? Hmm. Perhaps this is being already
handled elsewhere, in which case this comment still seems misleading.

======
src/backend/commands/publicationcmds.c

7.
+ * With REPLICA IDENTITY FULL, no column list and no excluded column
+ * list is allowed.

Really, just "no column list is allowed." same as it said before.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-06-23 00:54:10
Message-ID: CAHut+Pvb-gNmqAi=mtai9riN+61P_KiC8PT3AFi+CLRxXH9HRg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

> > > 5.
> > > + <para>
> > > + Alter publication <structname>mypublication</structname> to add table
> > > + <structname>users</structname> except column
> > > + <structname>security_pin</structname>:
> > > +<programlisting>
> > > +ALTER PUBLICATION production_publication ADD TABLE users EXCEPT (security_pin);
> > >
> > > Those tags don't seem correct. e.g. "users" and "security_pin" are not
> > > <structname> (???).
> > >
> > > Perhaps, every other example here is wrong too and you just copied
> > > them? Anyway, something here looks wrong to me.
> > >
> > I saw different documents and usage of tags seems not well defined.
> > For example for table we are using tags in document
> > create_publication.sgml, update.sgml <structname> is used, in document
> > table.sgml, advanced.sgml <classname> is used, and in
> > logical-replication.sgml <literal> is used. Similarly for column
> > names <structname>, <structfield> or <literal> are used in different
> > parts of the document.
> >
> > I kept the changed tag to <structfield> for the column for this patch.
> > Do you have any suggestions?
>
> No, for this patch I think it is best that you just follow nearby code
> (as you are already doing). I plan to raise another thread to ask what
> are the guidelines for this sort of markup which is currently used
> inconsistently in different places.
>

FYI - I created a new thread asking this markup question [1].

======
[1] https://www.postgresql.org/message-id/CAHut%2BPvtf24r%2BbdPgBind84dBLPvgNL7aB%2B%3DHxAUupdPuo2gRg%40mail.gmail.com

Kind Regards,
Peter Smith.
Fujitsu Australia


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-06-24 04:17:53
Message-ID: CANhcyEXX3viVpYcGHD_fzhf_f6CDQWr2+VBywrJf5zm_XiB4tg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 20 Jun 2025 at 09:28, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> On Thu, Jun 19, 2025 at 4:42 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> ...
> > > 3.
> > > TBH, I was wondering why a new catalog attribute was necessary...
> > >
> > > Can't you simply re-use the existing attribute "prattrs" attribute.
> > > e.g. let's just define negative means exclude.
> > >
> > > e.g. a value of 1 3 means only the 1st and 3rd columns are published
> > > e.g. a value of -1 -3 means all columns except 1st and 3rd columns are published
> > > e.g. a value of null mean all columns are published
> > >
> > > (mixes of negative and positive will not be possible)
> > >
> >
> > Currently I have added a new attribute 'prexcludeattrs' in
> > pg_publication_rel table. I used this approach because it will be
> > easier for user to get the exclude column list, in code no extra
> > processing is required to get the exclude column list.
> >
> > For an approach to use negative numbers for exclude columns. I see an
> > advantage that we do not need to introduce a new column for
> > pg_publication_rel. But in code, each time we want to get a column
> > list or exclude column list we need an extra processing of 'prattrs'
> > columns. Also I don't see any existing catalog table using a negative
> > attribute for column list.
> >
> > Based on above observations, I feel that the current is better.
> >
> > Please correct me if I missed an advantage for the approach you suggested.
> >
>
> OK. Maybe using negative numbers was a bridge too far...
>
> But IMO it is not good to have 2 separate attributes for the lists.
> Doing so implies they can coexist, but that is not true. I felt there
> are not really 2 "kinds" of columns list anyway -- there is just a
> "column list" which defines columns that are either included or
> excluded from the publication determined by EXCEPT.
>
> Having dual lists gets weird/confusing to describe them -- you end up
> continually having to refer to the other one to clarify behaviour.
>
> e.g. Does 'prattrs' value NULL mean publish everything? Well, no...
> that depends if there is a non null 'prexcludeattrs'
> e.g. Does 'prexcludeattrs' value NULL mean publish everything? Well,
> no... that depends if there is a non null 'prattrs'
>
> Furthermore, all the code is doubling up referring to "column list"
> and "exclude column list" -- code / docs / comments / error messages.
> There are quite a lot of places the patch touches that I thought were
> not really needed if you don't have 2 different kinds of column-lists.
>
> To summarise, I felt it would be better to just keep the existing
> 'prattrs' as the one-and-only column list, but add another BOOLEAN
> attribute to flag whether 'prattrs' columns should be included or
> excluded.
>
> prattrs; prattrs_exclude; Means
> --------------------------------------------
> 1 2 3 f only cols 1,2,3 will be published
> 4 5 6 t only cols 4,5,6 will NOT be published
> null f all cols are published (flag is ignored)
> null t all cols are published (flag is ignored)
>

I agree with your point and also it would be a better approach. In
patch 0001 an column 'prexcept' was added in pg_publication_rel. We
use that only for publication with all tables. I have reused this
column for patch 0003. If publication is not for all tables and the
'prexcept' flag is true, it implies that the columns in 'prattrs' are
to be excluded from being published. I have included the changes for
it in v14-0003 patch.

> > > 5.
> > > + <para>
> > > + Alter publication <structname>mypublication</structname> to add table
> > > + <structname>users</structname> except column
> > > + <structname>security_pin</structname>:
> > > +<programlisting>
> > > +ALTER PUBLICATION production_publication ADD TABLE users EXCEPT (security_pin);
> > >
> > > Those tags don't seem correct. e.g. "users" and "security_pin" are not
> > > <structname> (???).
> > >
> > > Perhaps, every other example here is wrong too and you just copied
> > > them? Anyway, something here looks wrong to me.
> > >
> > I saw different documents and usage of tags seems not well defined.
> > For example for table we are using tags in document
> > create_publication.sgml, update.sgml <structname> is used, in document
> > table.sgml, advanced.sgml <classname> is used, and in
> > logical-replication.sgml <literal> is used. Similarly for column
> > names <structname>, <structfield> or <literal> are used in different
> > parts of the document.
> >
> > I kept the changed tag to <structfield> for the column for this patch.
> > Do you have any suggestions?
>
> No, for this patch I think it is best that you just follow nearby code
> (as you are already doing). I plan to raise another thread to ask what
> are the guidelines for this sort of markup which is currently used
> inconsistently in different places.
Thanks for starting a thread for it.

>
> //////////
>
> Below are a few more review comments for v13-0003
>
> ======
> Commit message
>
> 1.
> Typo /THe/The/
>
> ~~~
Fixed

> 2.
> The new syntax allows specifying excluded column list when creating or
> altering a publication. For example:
> CREATE PUBLICATION pubname FOR TABLE tabname EXCEPT (exclude_column_list)
> or
> ALTER PUBLICATION pubname ADD TABLE tabname EXCEPT (exclude_column_list)
>
> ~
>
> I felt since you say these "For example:" it would be better to give
> real examples.
> e.g. say "(col1,col2,col3)" instead of "(exclude_column_list)".
>
Fixed

> ~~~
>
> 3.
> Typo /family of command/family of commands/
>
> ======
> doc/src/sgml/logical-replication.sgml
>
> 4.
> I am not sure that it was a good idea to be making a new term called
> an "exclude column list"... because in introduces a new concept of
> something that sounds like it is a different kind of list, and now you
> have to keep referring everywhere to both to "column list" versus
> "exclude column list". All the doubling up add more complication I
> think.
>
> IMO really there is just a "column list". Whether that list is for
> exclusion or not just depends on the presence of EXCEPT. So I felt
> maybe all places mentioning "exclude column list" could be rephrased.
>
> ======
> src/backend/catalog/pg_publication.c
>
> 5.
> +/*
> + * Returns true if the relation has exluded column list associated with the
> + * publication, false otherwise.
> + *
> + * If a exclude column list is found, the corresponding bitmap is returned
> + * through the cols parameter, if provided. The bitmap is constructed
> within the
> + * given memory context (mcxt).
> + */
> +
>
> Typo /exluded column/an excluded column/
> Typo /exclude column list/excluded column list/
>
updated the comment according to latest implementation

> ~~~
>
> 6.
> +/*
> + * pub_exclude_collist_validate
> + * Process and validate the 'excluded columns' list and ensure the columns
> + * are all valid to exclude from publication. Checks for and raises an
> + * ERROR for any unknown columns, system columns, duplicate columns, or
> + * generated columns.
> + *
>
> Why can't you exclude generated columns?
>
> e.g. Maybe PUBLICATION says publish_generated_columns=stored and there
> are 100s of such columns, but the user just wants to exclude one of
> them. Why say they cannot do that? Hmm. Perhaps this is being already
> handled elsewhere, in which case this comment still seems misleading.
>
I have removed this restriction. Now we can specify stored generated
columns in EXCEPT (column_list) when we use the
'publish_generated_columns' flag.

> ======
> src/backend/commands/publicationcmds.c
>
> 7.
> + * With REPLICA IDENTITY FULL, no column list and no excluded column
> + * list is allowed.
>
> Really, just "no column list is allowed." same as it said before.
>
> ======
Fixed

Thanks and Regards,
Shlok Kyal

Attachment Content-Type Size
v14-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 20.5 KB
v14-0003-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 54.9 KB
v14-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 68.8 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-06-26 03:36:10
Message-ID: CAHut+PsXP_61ZXuVOx5u9FZGK3oH4taaA59oOzgqyygZx8ezWw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok.

Below are some review comments for v14-0003

======
1. GENERAL

Since the new syntax uses EXCEPT, then, in my opinion, you should try
to use that same term where possible when describing things. I
understand it is hard to do this in text and I agree often it makes
more sense to say "exclude" columns etc, but OTOH in the code there
are lots of places where you could have named vars/params differently:
e.g. 'except_collist' instead of 'exclude_collist' might have been
better.

======
Commit message

2.
Column list specifed with EXCEPT is stored in column "prattrs" in table
"pg_publication_rel" and also column "prexcept" is set to "true", to maintain
the column list that user wants to exclude from the publication.

~

That paragraph could do with some rewording. For example, AFAIK,
"prattrs" is for all column lists -- not just except col-lists, but
the way it is described here sounds different.

Also, /specifed/specified/

======
doc/src/sgml/catalogs.sgml

3. (52.42. pg_publication_rel)

<para>
- True if the relation must be excluded
+ True if the relation or column list must be excluded. If publication is
+ created <literal>FOR ALL TABLES</literal> and it is specified as true,
+ the relation should be excluded. Else if it is true the columns in
+ <literal>prattrs</literal> should be excluded from being published.
</para></entry>

I felt this could be expressed more simply without mentioning anything
about FOR ALL TABLES.

SUGGESTION
True if the column list or relation must be excluded from publication.
If a column list is specified in <literal>prattrs</literal>, then
exclude only those columns. If <literal>prattrs</literal> is NULL,
then exclude the entire relation.

======
doc/src/sgml/logical-replication.sgml

4. (29.5. Column Lists)

<para>
- Each publication can optionally specify which columns of each table are
- replicated to subscribers. The table on the subscriber side must have at
- least all the columns that are published. If no column list is specified,
- then all columns on the publisher are replicated.
+ Each publication can optionally specify which columns of each
table should be
+ replicated or excluded from replication. On the subscriber side, the table
+ must include at least all the columns that are published. If no column list
+ is provided, all columns from the publisher are replicated by default.
See <xref linkend="sql-createpublication"/> for details on the syntax.
</para>

I felt this patch may have changed too much text. IMO, you only needed
to say "... are replicated or excluded from replication.". The other
changes did not seem necessary.

~~~

5.
<para>
- If no column list is specified, any columns added to the table later are
- automatically replicated. This means that having a column list which names
- all columns is not the same as having no column list at all.
+ If no column list or a column list with EXCEPT is specified, any columns
+ added to the table later are automatically replicated. This means
that having
+ a column list which names all columns is not the same as having no
+ column list at all. If an column list is specified, any columns added to the
+ table later are automatically replicated.
</para>

5a.
"This means that having a column list which names all columns is not
the same as having no column list at all." -- That note does not make
sense when you say EXCEPT. I think some rewording is needed here.

~

5b.
"If an column list is specified, any columns added to the table later
are automatically replicated.".

This made no sense -- some words missing?

~~~

6.
Generated columns can also be specified in a column list. This allows
generated columns to be published, regardless of the publication parameter
<link linkend="sql-createpublication-params-with-publish-generated-columns">
- <literal>publish_generated_columns</literal></link>. See
- <xref linkend="logical-replication-gencols"/> for details.
+ <literal>publish_generated_columns</literal></link>. Generated columns can
+ be included in column list specified with EXCEPT clause if publication
+ parameter
+ <link linkend="sql-createpublication-params-with-publish-generated-columns">
+ <literal>publish_generated_columns</literal></link> is not set to
+ <literal>none</literal>. Specified generated columns will not be published.
+ See <xref linkend="logical-replication-gencols"/> for details.
</para>

I am not so sure about this. It seemed overly strict to me.

Why can't it simply say:
"Generated columns can also be specified in a column list. This allows
generated columns to be published or excluded, regardless of the
publication parameter..."

Specifically, I don't know why you need to say:
Generated columns can be included in column list specified with EXCEPT
clause if publication parameter publish_generated_columns is not set
to none. Specified generated columns will not be published.

IIUC, then EXCEPT (gencol1, gencol2) is saying to exclude the named
cols. So if param is "stored", then the named cols will be excluded.
OTOH, if param is "none" then all generated cols will be excluded
anyway, so why not just allow the EXCEPT (gencol,gencol2) here as
well, because the result will be the same.

~~~

7. (29.5.1. Examples)

<para>
- Create a table <literal>t1</literal> to be used in the following example.
+ Create tables <literal>t1</literal>, <literal>t2</literal> to be
used in the
+ following example.

/Create tables t1, t2/Create tables t1 and t2/

~~~

8.
<para>
Create a publication <literal>p1</literal>. A column list is defined for
- table <literal>t1</literal> to reduce the number of columns that will be
- replicated. Notice that the order of column names in the column list does
- not matter.
+ table <literal>t1</literal> and a column list is defined for table
+ <literal>t2</literal> with EXCEPT clause to reduce the number of
columns that will be
+ replicated. Notice that the order of column names in the column
lists does not matter.

BEFORE
A column list is defined for table t1 and a column list is defined for
table t2...

SUGGESTION (added comma, etc.)
A column list is defined for table t1, and another column list is
defined for table t2...

~~~

9.
The final example still says:
"Only data from the column list of publication p1 is replicated."

That doesn't seem quite appropriate now that you also have an EXCEPT
column list.

SUGGESTION:
Only data specified by the column lists of publication p1 is replicated.

======
doc/src/sgml/ref/create_publication.sgml

10.
+ <para>
+ When a column list is specified with EXCEPT, the named columns are not
+ replicated. Specifying a column list has no effect on
+ <literal>TRUNCATE</literal> commands.
+ </para>

I felt that to be clearer the preceding paragraph should be changed as follows:

/When a column list is specified, only the named columns are
replicated./When a column list without EXCEPT is specified, only the
named columns are replicated./

~~~

11. CREATE PUBLICATION (NOTES section)

11a.
The NOTES talk about replica identity columns -- should you mention EXCEPT here?

~

11b.
The NOTES talk about generated columns -- should you mention EXCEPT here?

======
src/backend/catalog/pg_publication.c

12. check_and_fetch_column_list

+ if (!isnull)
+ except = DatumGetBool(cfdatum);
+
+ *except_columns = except && !pub->alltables;

AFAICT, you can Assert(!pub->alltables) because you already checked
that earlier up front.
So you don't need 'except' var either. Just assign *except_cols up
front and then overwrite it later if true.

SUGGESTION:

*except_cols = false;

if (pub->alltables)
return false;
...
if (!isnull)
*except_cols = DatumGetBool(cfdatum);

~~~

13. publication_add_relation

/* Validate and translate column names into a Bitmapset of attnums. */
- attnums = pub_collist_validate(pri->relation, pri->columns);
+ attnums = pub_collist_validate(pri->relation, pri->columns,
+ pri->except && !pub->alltables,
+ pub->pubgencols_type);

I am wondering why we are even calling a function to validate column
lists if pub->alltables was true. AFAIK, that combination of
column-lists and FOR ALL TABLES is not even possible, so the code
seems strange.

~~~

14. pub_exclude_collist_validate
.
+ /*
+ * Check if column list specified with EXCEPT have any stored
+ * generated column and 'publish_generated_columns' is not set to
+ * 'stored'.
+ */
+ if (except_columns &&
+ TupleDescAttr(tupdesc, attnum - 1)->attgenerated ==
ATTRIBUTE_GENERATED_STORED &&
+ pubgencols_type != PUBLISH_GENCOLS_STORED)
+ ereport(ERROR,
+ errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
+ errmsg("cannot use stored generated column \"%s\" in publication
column list specified with EXCEPT when \"%s\" set to \"%s\"",
+ colname, "publish_generated_columns", "stored"));

As mentioned in the above DOCS comments, I was having doubts about why
we have this error.

If the parameter says "none", then generated columns will not be
replicated, so why should we care if the user also says
EXCEPT(gencol1,gencol2). Either way, the result will be the same; the
generated column will not be published.

~~~

15. GetRelationPublications

{
HeapTuple tup = &pubrellist->members[i]->tuple;
Oid pubid = ((Form_pg_publication_rel) GETSTRUCT(tup))->prpubid;
+ HeapTuple pubtup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pubid));
+ bool is_table_excluded = ((Form_pg_publication)
GETSTRUCT(pubtup))->puballtables &&
+ ((Form_pg_publication_rel) GETSTRUCT(tup))->prexcept;

- if (except_flag == ((Form_pg_publication_rel) GETSTRUCT(tup))->prexcept)
+ if (except_flag == is_table_excluded)
result = lappend_oid(result, pubid);
+
+ ReleaseS

I'm not 100% sure you need the additional 'pubtup'... Can't you just
look at the "prattrs" field to see if a column-list was specified? If
"prattrs" is null and "prexcept" is true, isn't that the same
combination as what you are looking for here?

~~~

16. pg_get_publication_tables

+ columnsDatum = SysCacheGetAttr(PUBLICATIONRELMAP, pubtuple,
+ Anum_pg_publication_rel_prattrs,
+ &(nulls[2]));
+
+ /* if column list is specified with EXCEPT */
+ if (!pub->alltables && except)
+ columns = pub_collist_to_bitmapset(NULL, columnsDatum, NULL);
+ else
+ values[2] = columnsDatum;

16a.
Something seems fishy here. Isn't there a pathway where you missed
assigning value[2] to anything?

~

16b.
Also, I feel there should be some other boolean variable used here
instead of checking bot (!pub->alltables && except) in multiple
places.

======
src/backend/replication/pgoutput/pgoutput.c

17. RelationSyncEntry
+
+ /* Indicate if no column is included in the publication */
+ bool no_cols_published;

Maybe this can have a more explanatory comment to explain why it is needed?

~~~

18. check_and_init_gencol

+ bool found = false;
+ bool except_columns = false;
+
+ found = check_and_fetch_column_list(pub, entry->publish_as_relid, NULL,
+ NULL, &except_columns);
+
/*
* The column list takes precedence over the
* 'publish_generated_columns' parameter. Those will be checked later,
- * see pgoutput_column_list_init.
+ * see pgoutput_column_list_init. But when a column list is specified
+ * with EXCEPT, it should be checked.
*/
- if (check_and_fetch_column_list(pub, entry->publish_as_relid, NULL, NULL))
+ if (found && !except_columns)
continue;

The variable 'found' seems a poor name; how about 'has_column_list' or similar?

~~~

19. pgoutput_change

+ /*
+ * If all columns of a table is present in column list specified with
+ * EXCEPT, skip publishing the changes.
+ */
+ if (relentry->no_cols_published)
+ return;

/is present/are present/

======
src/bin/pg_dump/pg_dump.c

20. getPublicationTables

+ if (strcmp(prexcept, "t") == 0 && PQgetisnull(res, i, i_prattrs))
pubrinfo[j].dobj.objType = DO_PUBLICATION_EXCEPT_REL;
+ else
+ pubrinfo[j].dobj.objType = DO_PUBLICATION_REL;

pubrinfo[j].dobj.catId.tableoid =
atooid(PQgetvalue(res, i, i_tableoid));
@@ -4797,6 +4797,7 @@ getPublicationTables(Archive *fout, TableInfo
tblinfo[], int numTables)
pubrinfo[j].pubrelqual = NULL;
else
pubrinfo[j].pubrelqual = pg_strdup(PQgetvalue(res, i, i_prrelqual));
+ pubrinfo[j].pubexcept = (strcmp(prexcept, "t") == 0);

Why not assign pubrinfo[j].pubexcept earlier so you don't have to
repeat the strcmp?

~~~

21.
- if (strcmp(prexcept, "t") == 0)
+ if (strcmp(prexcept, "t") == 0 && PQgetisnull(res, i, i_prattrs))
simple_ptr_list_append(&exceptinfo, &pubrinfo[j]);

Why not assign pubrinfo[j].pubexcept earlier so you don't have to
repeat the strcmp? Same also for the PQgetisnull(res, i,
i_prattrs))...

~~~

22. dumpPublicationTable

if (pubrinfo->pubrattrs)
- appendPQExpBuffer(query, " (%s)", pubrinfo->pubrattrs);
+ {
+ if (pubrinfo->pubexcept)
+ appendPQExpBuffer(query, " EXCEPT (%s)", pubrinfo->pubrattrs);
+ else
+ appendPQExpBuffer(query, " (%s)", pubrinfo->pubrattrs);
+ }

SUGGESTION
{
if (pubrinfo->pubexcept)
appendPQExpBuffer(query, " EXCEPT");

appendPQExpBuffer(query, " (%s)", pubrinfo->pubrattrs);
}

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2025-06-26 09:57:36
Message-ID: CAJpy0uAamUiZN5LkN9y7_-zT8=OZmW846T8dfgkojFwreV8XOw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Jun 24, 2025 at 9:48 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> I have included the changes for
> it in v14-0003 patch.
>
Thanks for the patches. I have reviewed patch001 alone, please find
few comments:

1)
+ <para>
+ The <literal>RESET</literal> clause will reset the publication to the
+ default state which includes resetting the publication parameters, setting
+ <literal>ALL TABLES</literal> flag to <literal>false</literal> and
+ dropping all relations and schemas that are associated with the
+ publication.
</para>

It is misleading, as far as I have understood, we do not drop the
tables or schemas associated with the pub; we just remove those from
the publication's object list. See previous doc:
"The ADD and DROP clauses will add and remove one or more
tables/schemas from the publication"

Perhaps we want to say the same thing when we speak about the 'drop'
aspect of RESET.

2)
AlterPublicationReset():

+ if (!OidIsValid(prid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("relation \"%s\" is not part of the publication",
+ get_rel_name(relid))));

Can you please help me understand which scenario will give this error?

Another question is do we really need this error? IIUC, we generally
give errors if a user has explicitly called out a name of an object
and that object is not found. Example:

postgres=# alter publication pubnew drop table t1,tab2;
ERROR: relation "t1" is not part of the publication

While in a few other cases, we pass missing_okay as true and do not
give errors. Please see other callers of performDeletion in
publicationcmds.c itself. There we have usage of missing_okay=true. I
have not researched myself, but please analyze the cases where
missing_okay is passed as true to figure out if those match our RESET
case. Try to reproduce if possible and then take a call.

3)
+ALTER PUBLICATION testpub_reset ADD ALL TABLES IN SCHEMA public;
+ERROR: syntax error at or near "ALL"
+LINE 1: ALTER PUBLICATION testpub_reset ADD ALL TABLES IN SCHEMA pub...

There is a problem in syntax, I think the intention of testcase was to
run this query successfully.

thanks
Shveta


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-06-27 10:11:17
Message-ID: CANhcyEU+aPu6iAH2cTA0cDtn3pd6c_njBONCt3FubYZoEEnm8Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 26 Jun 2025 at 09:06, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok.
>
> Below are some review comments for v14-0003
>
> ======
> 1. GENERAL
>
> Since the new syntax uses EXCEPT, then, in my opinion, you should try
> to use that same term where possible when describing things. I
> understand it is hard to do this in text and I agree often it makes
> more sense to say "exclude" columns etc, but OTOH in the code there
> are lots of places where you could have named vars/params differently:
> e.g. 'except_collist' instead of 'exclude_collist' might have been
> better.
>
Fixed the variable names.

> ======
> Commit message
>
> 2.
> Column list specifed with EXCEPT is stored in column "prattrs" in table
> "pg_publication_rel" and also column "prexcept" is set to "true", to maintain
> the column list that user wants to exclude from the publication.
>
> ~
>
> That paragraph could do with some rewording. For example, AFAIK,
> "prattrs" is for all column lists -- not just except col-lists, but
> the way it is described here sounds different.
>
> Also, /specifed/specified/
>
Reworded the paragraph

> ======
> doc/src/sgml/catalogs.sgml
>
> 3. (52.42. pg_publication_rel)
>
> <para>
> - True if the relation must be excluded
> + True if the relation or column list must be excluded. If publication is
> + created <literal>FOR ALL TABLES</literal> and it is specified as true,
> + the relation should be excluded. Else if it is true the columns in
> + <literal>prattrs</literal> should be excluded from being published.
> </para></entry>
>
> I felt this could be expressed more simply without mentioning anything
> about FOR ALL TABLES.
>
> SUGGESTION
> True if the column list or relation must be excluded from publication.
> If a column list is specified in <literal>prattrs</literal>, then
> exclude only those columns. If <literal>prattrs</literal> is NULL,
> then exclude the entire relation.
>
Fixed

> ======
> doc/src/sgml/logical-replication.sgml
>
> 4. (29.5. Column Lists)
>
> <para>
> - Each publication can optionally specify which columns of each table are
> - replicated to subscribers. The table on the subscriber side must have at
> - least all the columns that are published. If no column list is specified,
> - then all columns on the publisher are replicated.
> + Each publication can optionally specify which columns of each
> table should be
> + replicated or excluded from replication. On the subscriber side, the table
> + must include at least all the columns that are published. If no column list
> + is provided, all columns from the publisher are replicated by default.
> See <xref linkend="sql-createpublication"/> for details on the syntax.
> </para>
>
> I felt this patch may have changed too much text. IMO, you only needed
> to say "... are replicated or excluded from replication.". The other
> changes did not seem necessary.
>
> ~~~
Fixed

> 5.
> <para>
> - If no column list is specified, any columns added to the table later are
> - automatically replicated. This means that having a column list which names
> - all columns is not the same as having no column list at all.
> + If no column list or a column list with EXCEPT is specified, any columns
> + added to the table later are automatically replicated. This means
> that having
> + a column list which names all columns is not the same as having no
> + column list at all. If an column list is specified, any columns added to the
> + table later are automatically replicated.
> </para>
>
> 5a.
> "This means that having a column list which names all columns is not
> the same as having no column list at all." -- That note does not make
> sense when you say EXCEPT. I think some rewording is needed here.
>
Fixed

> ~
>
> 5b.
> "If an column list is specified, any columns added to the table later
> are automatically replicated.".
>
> This made no sense -- some words missing?
>
This change was done by mistake. Removed it.

> ~~~
>
> 6.
> Generated columns can also be specified in a column list. This allows
> generated columns to be published, regardless of the publication parameter
> <link linkend="sql-createpublication-params-with-publish-generated-columns">
> - <literal>publish_generated_columns</literal></link>. See
> - <xref linkend="logical-replication-gencols"/> for details.
> + <literal>publish_generated_columns</literal></link>. Generated columns can
> + be included in column list specified with EXCEPT clause if publication
> + parameter
> + <link linkend="sql-createpublication-params-with-publish-generated-columns">
> + <literal>publish_generated_columns</literal></link> is not set to
> + <literal>none</literal>. Specified generated columns will not be published.
> + See <xref linkend="logical-replication-gencols"/> for details.
> </para>
>
> I am not so sure about this. It seemed overly strict to me.
>
> Why can't it simply say:
> "Generated columns can also be specified in a column list. This allows
> generated columns to be published or excluded, regardless of the
> publication parameter..."
>
> Specifically, I don't know why you need to say:
> Generated columns can be included in column list specified with EXCEPT
> clause if publication parameter publish_generated_columns is not set
> to none. Specified generated columns will not be published.
>
> IIUC, then EXCEPT (gencol1, gencol2) is saying to exclude the named
> cols. So if param is "stored", then the named cols will be excluded.
> OTOH, if param is "none" then all generated cols will be excluded
> anyway, so why not just allow the EXCEPT (gencol,gencol2) here as
> well, because the result will be the same.
>
>
I have removed this change. And allowed specifying generated columns
in EXCEPT column list as well irrespective of value of
‘publish_generated_columns’.

> ~~~
>
> 7. (29.5.1. Examples)
>
> <para>
> - Create a table <literal>t1</literal> to be used in the following example.
> + Create tables <literal>t1</literal>, <literal>t2</literal> to be
> used in the
> + following example.
>
> /Create tables t1, t2/Create tables t1 and t2/
>
Fixed

> ~~~
>
> 8.
> <para>
> Create a publication <literal>p1</literal>. A column list is defined for
> - table <literal>t1</literal> to reduce the number of columns that will be
> - replicated. Notice that the order of column names in the column list does
> - not matter.
> + table <literal>t1</literal> and a column list is defined for table
> + <literal>t2</literal> with EXCEPT clause to reduce the number of
> columns that will be
> + replicated. Notice that the order of column names in the column
> lists does not matter.
>
> BEFORE
> A column list is defined for table t1 and a column list is defined for
> table t2...
>
> SUGGESTION (added comma, etc.)
> A column list is defined for table t1, and another column list is
> defined for table t2...
>
Fixed

> ~~~
>
> 9.
> The final example still says:
> "Only data from the column list of publication p1 is replicated."
>
> That doesn't seem quite appropriate now that you also have an EXCEPT
> column list.
>
> SUGGESTION:
> Only data specified by the column lists of publication p1 is replicated.
>
Fixed

> ======
> doc/src/sgml/ref/create_publication.sgml
>
> 10.
> + <para>
> + When a column list is specified with EXCEPT, the named columns are not
> + replicated. Specifying a column list has no effect on
> + <literal>TRUNCATE</literal> commands.
> + </para>
>
> I felt that to be clearer the preceding paragraph should be changed as follows:
>
> /When a column list is specified, only the named columns are
> replicated./When a column list without EXCEPT is specified, only the
> named columns are replicated./
>
Fixed

> ~~~
>
> 11. CREATE PUBLICATION (NOTES section)
>
> 11a.
> The NOTES talk about replica identity columns -- should you mention EXCEPT here?
>
Added notes for EXCEPT

> ~
>
> 11b.
> The NOTES talk about generated columns -- should you mention EXCEPT here?
>
I felt it is not needed.

> ======
> src/backend/catalog/pg_publication.c
>
> 12. check_and_fetch_column_list
>
> + if (!isnull)
> + except = DatumGetBool(cfdatum);
> +
> + *except_columns = except && !pub->alltables;
>
> AFAICT, you can Assert(!pub->alltables) because you already checked
> that earlier up front.
> So you don't need 'except' var either. Just assign *except_cols up
> front and then overwrite it later if true.
>
> SUGGESTION:
>
> *except_cols = false;
>
> if (pub->alltables)
> return false;
> ...
> if (!isnull)
> *except_cols = DatumGetBool(cfdatum);
>
Fixed

> ~~~
>
> 13. publication_add_relation
>
> /* Validate and translate column names into a Bitmapset of attnums. */
> - attnums = pub_collist_validate(pri->relation, pri->columns);
> + attnums = pub_collist_validate(pri->relation, pri->columns,
> + pri->except && !pub->alltables,
> + pub->pubgencols_type);
>
>
> I am wondering why we are even calling a function to validate column
> lists if pub->alltables was true. AFAIK, that combination of
> column-lists and FOR ALL TABLES is not even possible, so the code
> seems strange.
>
Fixed

> ~~~
>
> 14. pub_exclude_collist_validate
> .
> + /*
> + * Check if column list specified with EXCEPT have any stored
> + * generated column and 'publish_generated_columns' is not set to
> + * 'stored'.
> + */
> + if (except_columns &&
> + TupleDescAttr(tupdesc, attnum - 1)->attgenerated ==
> ATTRIBUTE_GENERATED_STORED &&
> + pubgencols_type != PUBLISH_GENCOLS_STORED)
> + ereport(ERROR,
> + errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
> + errmsg("cannot use stored generated column \"%s\" in publication
> column list specified with EXCEPT when \"%s\" set to \"%s\"",
> + colname, "publish_generated_columns", "stored"));
>
> As mentioned in the above DOCS comments, I was having doubts about why
> we have this error.
>
> If the parameter says "none", then generated columns will not be
> replicated, so why should we care if the user also says
> EXCEPT(gencol1,gencol2). Either way, the result will be the same; the
> generated column will not be published.
>
Removed this restriction.

> ~~~
>
> 15. GetRelationPublications
>
> {
> HeapTuple tup = &pubrellist->members[i]->tuple;
> Oid pubid = ((Form_pg_publication_rel) GETSTRUCT(tup))->prpubid;
> + HeapTuple pubtup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pubid));
> + bool is_table_excluded = ((Form_pg_publication)
> GETSTRUCT(pubtup))->puballtables &&
> + ((Form_pg_publication_rel) GETSTRUCT(tup))->prexcept;
>
> - if (except_flag == ((Form_pg_publication_rel) GETSTRUCT(tup))->prexcept)
> + if (except_flag == is_table_excluded)
> result = lappend_oid(result, pubid);
> +
> + ReleaseS
>
>
> I'm not 100% sure you need the additional 'pubtup'... Can't you just
> look at the "prattrs" field to see if a column-list was specified? If
> "prattrs" is null and "prexcept" is true, isn't that the same
> combination as what you are looking for here?
>
Yes, we can use this combination as well. Fixed it in latest patch.

> ~~~
>
> 16. pg_get_publication_tables
>
> + columnsDatum = SysCacheGetAttr(PUBLICATIONRELMAP, pubtuple,
> + Anum_pg_publication_rel_prattrs,
> + &(nulls[2]));
> +
> + /* if column list is specified with EXCEPT */
> + if (!pub->alltables && except)
> + columns = pub_collist_to_bitmapset(NULL, columnsDatum, NULL);
> + else
> + values[2] = columnsDatum;
>
> 16a.
> Something seems fishy here. Isn't there a pathway where you missed
> assigning value[2] to anything?
>
Modified this change.

> ~
>
> 16b.
> Also, I feel there should be some other boolean variable used here
> instead of checking bot (!pub->alltables && except) in multiple
> places.
>
Fixed
>
> ======
> src/backend/replication/pgoutput/pgoutput.c
>
> 17. RelationSyncEntry
> +
> + /* Indicate if no column is included in the publication */
> + bool no_cols_published;
>
> Maybe this can have a more explanatory comment to explain why it is needed?
>
Fixed

> ~~~
>
> 18. check_and_init_gencol
>
> + bool found = false;
> + bool except_columns = false;
> +
> + found = check_and_fetch_column_list(pub, entry->publish_as_relid, NULL,
> + NULL, &except_columns);
> +
> /*
> * The column list takes precedence over the
> * 'publish_generated_columns' parameter. Those will be checked later,
> - * see pgoutput_column_list_init.
> + * see pgoutput_column_list_init. But when a column list is specified
> + * with EXCEPT, it should be checked.
> */
> - if (check_and_fetch_column_list(pub, entry->publish_as_relid, NULL, NULL))
> + if (found && !except_columns)
> continue;
>
> The variable 'found' seems a poor name; how about 'has_column_list' or similar?
>
Fixed

> ~~~
>
> 19. pgoutput_change
>
> + /*
> + * If all columns of a table is present in column list specified with
> + * EXCEPT, skip publishing the changes.
> + */
> + if (relentry->no_cols_published)
> + return;
>
> /is present/are present/
>
fixed

> ======
> src/bin/pg_dump/pg_dump.c
>
> 20. getPublicationTables
>
> + if (strcmp(prexcept, "t") == 0 && PQgetisnull(res, i, i_prattrs))
> pubrinfo[j].dobj.objType = DO_PUBLICATION_EXCEPT_REL;
> + else
> + pubrinfo[j].dobj.objType = DO_PUBLICATION_REL;
>
> pubrinfo[j].dobj.catId.tableoid =
> atooid(PQgetvalue(res, i, i_tableoid));
> @@ -4797,6 +4797,7 @@ getPublicationTables(Archive *fout, TableInfo
> tblinfo[], int numTables)
> pubrinfo[j].pubrelqual = NULL;
> else
> pubrinfo[j].pubrelqual = pg_strdup(PQgetvalue(res, i, i_prrelqual));
> + pubrinfo[j].pubexcept = (strcmp(prexcept, "t") == 0);
>
>
> Why not assign pubrinfo[j].pubexcept earlier so you don't have to
> repeat the strcmp?
>
Fixed

> ~~~
>
> 21.
> - if (strcmp(prexcept, "t") == 0)
> + if (strcmp(prexcept, "t") == 0 && PQgetisnull(res, i, i_prattrs))
> simple_ptr_list_append(&exceptinfo, &pubrinfo[j]);
>
> Why not assign pubrinfo[j].pubexcept earlier so you don't have to
> repeat the strcmp? Same also for the PQgetisnull(res, i,
> i_prattrs))...
>
Fixed

> ~~~
>
> 22. dumpPublicationTable
>
> if (pubrinfo->pubrattrs)
> - appendPQExpBuffer(query, " (%s)", pubrinfo->pubrattrs);
> + {
> + if (pubrinfo->pubexcept)
> + appendPQExpBuffer(query, " EXCEPT (%s)", pubrinfo->pubrattrs);
> + else
> + appendPQExpBuffer(query, " (%s)", pubrinfo->pubrattrs);
> + }
>
> SUGGESTION
> {
> if (pubrinfo->pubexcept)
> appendPQExpBuffer(query, " EXCEPT");
>
> appendPQExpBuffer(query, " (%s)", pubrinfo->pubrattrs);
> }
Fixed

I have addressed the comments shared by you and shared the updated v15
patch set here.

Thanks and Regards,
Shlok Kyal

Attachment Content-Type Size
v15-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 20.2 KB
v15-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 79.1 KB
v15-0003-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 54.2 KB

From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-06-27 10:14:14
Message-ID: CANhcyEU9jX5wM0R3jHs5-=UFaFehcXC8KMkKow_rphHVben_Nw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 26 Jun 2025 at 15:27, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Tue, Jun 24, 2025 at 9:48 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > I have included the changes for
> > it in v14-0003 patch.
> >
> Thanks for the patches. I have reviewed patch001 alone, please find
> few comments:
>
> 1)
> + <para>
> + The <literal>RESET</literal> clause will reset the publication to the
> + default state which includes resetting the publication parameters, setting
> + <literal>ALL TABLES</literal> flag to <literal>false</literal> and
> + dropping all relations and schemas that are associated with the
> + publication.
> </para>
>
> It is misleading, as far as I have understood, we do not drop the
> tables or schemas associated with the pub; we just remove those from
> the publication's object list. See previous doc:
> "The ADD and DROP clauses will add and remove one or more
> tables/schemas from the publication"
>
> Perhaps we want to say the same thing when we speak about the 'drop'
> aspect of RESET.
I have updated the document.

> 2)
> AlterPublicationReset():
>
> + if (!OidIsValid(prid))
> + ereport(ERROR,
> + (errcode(ERRCODE_UNDEFINED_OBJECT),
> + errmsg("relation \"%s\" is not part of the publication",
> + get_rel_name(relid))));
>
> Can you please help me understand which scenario will give this error?
>
> Another question is do we really need this error? IIUC, we generally
> give errors if a user has explicitly called out a name of an object
> and that object is not found. Example:
>
> postgres=# alter publication pubnew drop table t1,tab2;
> ERROR: relation "t1" is not part of the publication
>
> While in a few other cases, we pass missing_okay as true and do not
> give errors. Please see other callers of performDeletion in
> publicationcmds.c itself. There we have usage of missing_okay=true. I
> have not researched myself, but please analyze the cases where
> missing_okay is passed as true to figure out if those match our RESET
> case. Try to reproduce if possible and then take a call.
I thought about the above point and I also think this check is not
required. Also, the function was calling PublicationDropSchemas with
missing_ok as false. I have changed it to be true.

> 3)
> +ALTER PUBLICATION testpub_reset ADD ALL TABLES IN SCHEMA public;
> +ERROR: syntax error at or near "ALL"
> +LINE 1: ALTER PUBLICATION testpub_reset ADD ALL TABLES IN SCHEMA pub...
>
> There is a problem in syntax, I think the intention of testcase was to
> run this query successfully.

I have fixed it.

Thanks Shveta for reviewing the patch. I have addressed the comments
and posted an updated version v15 in [1].

[1]: https://www.postgresql.org/message-id/CANhcyEU%2BaPu6iAH2cTA0cDtn3pd6c_njBONCt3FubYZoEEnm8Q%40mail.gmail.com

Thanks and Regards,
Shlok Kyal


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-06-30 06:07:15
Message-ID: CAHut+Pv2P6dJ7hZj_fmzN+=xzjvpOpgkAJvDZg3TD2xpvmY1NQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok.

Some review comments for v15-0003.

======
doc/src/sgml/catalogs.sgml

1.
<para>
- True if the relation must be excluded
+ True if the column list or relation must be excluded from publication.
+ If a column list is specified in <literal>prattrs</literal>, then
+ exclude only those columns. If <literal>prattrs</literal> is NULL,
+ then exclude the entire relation.
</para></entry>

I noticed other fields on this page say "null" instead of "NULL". It
seems like "null" is more conventional.

======
doc/src/sgml/logical-replication.sgml

2.
<para>
If no column list is specified, any columns added to the table later are
automatically replicated. This means that having a column list which names
- all columns is not the same as having no column list at all.
+ all columns is not the same as having no column list at all.
Similarly, if an
+ column list is specified with EXCEPT, any columns added to the table later
+ are also replicated automatically.
</para>

2a.
CURRENTLY
If no column list or a column list with EXCEPT is specified, any
columns added to the table later are automatically replicated. This
means that having a column list which names all columns is not the
same as having no column list at all. If an column list is specified,
any columns added to the table later are automatically replicated.

~

That still doesn't quite make sense. I think instead of saying "This
means..." it needs to say something a bit like below:

However, a normal column list (without EXCEPT) only replicates the
specified columns and no more. Therefore, having a column list that
names all columns is not the same as having no column list at all, as
more columns may be added to the table later.

~

2b.
And the final sentence "If an column list..." looks like a cut/paste error (??)

~

2c.
Maybe here EXCEPT should be written as <literal>EXCEPT</literal>

~~~

2.5A.
The description about generated columns still says this:

CURRENT:
Generated columns can also be specified in a column list. This allows
generated columns to be published, regardless of the publication
parameter publish_generated_columns. See Section 29.6 for details.

~

But I don't think it is quite correct. IMO gencols behaviour is much
more subtle...

e.g.

a) Normal collist - these named cols are published REGARDLESS of the
'publish_generated_cols' parameter (same as before)

b) EXCEPT collist - you can specify gencols in the list REGARDLESS of
the 'publish_generated_cols' parameter, because since they are named
as "except" then they will not be published anyhow....

c) BUT for EXCEPT collist case, I think any gencols that are *not*
covered by that EXCEPT collist should follow the rules according to
the 'publish_generated_cols' parameter.

So, it is much more tricky than the docs currently say:

Also

2.5B.
- The text says "See Section 29.6 for details," but there are no
examples of these combinations (e.g. EXCEPT collist and diff parameter
setting)

2.5C,
- The regression tests also need to be more complex to cover these

2.5D.
- You might need to add something in the CREATE PUBLICATION "NOTES"
section after all -- even if it just refers to here.

~~~

3.
<para>
Create a publication <literal>p1</literal>. A column list is defined for
- table <literal>t1</literal> to reduce the number of columns that will be
- replicated. Notice that the order of column names in the column list does
- not matter.
+ table <literal>t1</literal>, and another column list is defined for table
+ <literal>t2</literal> using the EXCEPT clause to reduce the number of
+ columns that will be replicated. Note that the order of column names in
+ the column lists does not matter.
<programlisting>
-/* pub # */ CREATE PUBLICATION p1 FOR TABLE t1 (id, b, a, d);
+/* pub # */ CREATE PUBLICATION p1 FOR TABLE t1 (id, b, a, d), t2 EXCEPT (d, a);
</programlisting></para>

Maybe here EXCEPT should be written as <literal>EXCEPT</literal>

======
doc/src/sgml/ref/create_publication.sgml

4.
<para>
- When a column list is specified, only the named columns are replicated.
- The column list can contain stored generated columns as well. If the
- column list is omitted, the publication will replicate all non-generated
- columns (including any added in the future) by default. Stored generated
- columns can also be replicated if
<literal>publish_generated_columns</literal>
- is set to <literal>stored</literal>. Specifying a column list has no
- effect on <literal>TRUNCATE</literal> commands. See
+ When a column list without EXCEPT is specified, only the named
columns are
+ replicated. The column list can contain stored generated columns as well.
+ If the column list is omitted, the publication will replicate
+ all non-generated columns (including any added in the future) by default.
+ Stored generated columns can also be replicated if
+ <literal>publish_generated_columns</literal> is set to
+ <literal>stored</literal>. Specifying a column list has no effect on
+ <literal>TRUNCATE</literal> commands. See
<xref linkend="logical-replication-col-lists"/> for details about column
lists.
</para>

Maybe here EXCEPT should be written as <literal>EXCEPT</literal>

~~~

5.
+ <para>
+ When a column list is specified with EXCEPT, the named columns are not
+ replicated. Specifying a column list has no effect on
+ <literal>TRUNCATE</literal> commands.
+ </para>

Maybe here EXCEPT should be written as <literal>EXCEPT</literal>.

** Note all the extra subtleties that I mentioned in the review
comment #2.5 above --- e.g. IMO any *un-listed* gencols still should
follow the parameter rules.

~~~

6.
<para>
Any column list must include the <literal>REPLICA IDENTITY</literal> columns
- in order for <command>UPDATE</command> or <command>DELETE</command>
- operations to be published. There are no column list restrictions if the
- publication publishes only <command>INSERT</command> operations.
+ and any column list specified with EXCEPT must not include the
+ <literal>REPLICA IDENTITY</literal> columns in order for
+ <command>UPDATE</command> or <command>DELETE</command> operations to be
+ published. There are no column list restrictions if the
publication publishes
+ only <command>INSERT</command> operations.
</para>

6a.
CURRENT:
Any column list must include the REPLICA IDENTITY columns, and any
column list specified with EXCEPT must not include the REPLICA
IDENTITY columns in order for UPDATE or DELETE operations to be
published.

~

I felt that might be better expressed the other way around. Also, it
might be better to say "not name" instead of "not include" because
EXCEPT + include seemed a bit contrary.

SUGGESTION (maybe like this)
In order for UPDATE or DELETE operations to work, all the REPLICA
IDENTITY columns must be published. So, any column list must name all
REPLICA IDENTITY columns, and any EXCEPT column list must not name any
REPLICA IDENTITY columns.

~~

6b.
Maybe here EXCEPT should be written as <literal>EXCEPT</literal>

======
src/backend/catalog/pg_publication.c

check_and_fetch_column_list:

7.
+ /* Lookup the except attribute */
+ cfdatum = SysCacheGetAttr(PUBLICATIONRELMAP, cftuple,
+ Anum_pg_publication_rel_prexcept, &isnull);
+
+ if (!isnull)
+ {
+ Assert(!pub->alltables);
+ *except_columns = DatumGetBool(cfdatum);
+ }
+

I felt it would be safer to also assign *except_columns = false;
up-front so the caller could be sure this flag was meaningful on
return.

~~~

pub_form_cols_map:

8.
Maybe use snake case like for other params, so /excepcols/except_cols/

~~~

pg_get_publication_tables:

9.

I felt all the logic in this function maybe can be simpler:

e.g. If you just have "Bitmapset *except_columns = NULL;" then null
nmeans there is no except columns; otherwise there is. This means you
don't need a separate 'bool except_column' variable.

e.g. Assign the Bitmapset *except_columns after you already have the
values[2], instead of doing it later.

e.g. The skip code if (except_columns && bms_is_member(att->attnum,
columns)) could just check the list member, I think, without the
additional bool.

~~~

10.
+ /*
+ * We fetch pubtuple if publication is not FOR ALL TABLES and not
+ * FOR TABLES IN SCHEMA. So if prexcept is true, it indicate that
+ * prattrs contains columns to be excluded for replication.
+ */
+ if (!isnull)
+ except_columns = DatumGetBool(exceptDatum);

/indicate/indicates/

======
src/backend/parser/gram.y

11.
+ | TABLE relation_expr EXCEPT opt_except_column_list OptWhereClause
+ {
+ $$ = makeNode(PublicationObjSpec);
+ $$->pubobjtype = PUBLICATIONOBJ_TABLE;
+ $$->pubtable = makeNode(PublicationTable);
+ $$->pubtable->relation = $2;
+ $$->pubtable->columns = $4;
+ $$->pubtable->whereClause = $5;
+ $$->pubtable->except = true;
+ $$->location = @1;
+ }

I wasn't expecting you would need another 'opt_except_column_list' and
all the code duplication that causes. AFAIK, the syntax is identical
for 'opt_column_list' apart from the preceding EXCEPT so I thought all
you need is to allow the 'opt_column_list' to have an optional EXCEPT
qualifier.

======
src/backend/replication/pgoutput/pgoutput.c

12.
+
+ /*
+ * Indicates whether no columns are published for a given relation. With
+ * the introduction of the EXCEPT clause in column lists, it is now
+ * possible to define a publication that excludes all columns of a table.
+ * However, the 'columns' attribute cannot represent this case, since a
+ * NULL value implies that all columns are published. To distinguish this
+ * scenario, the 'no_cols_published' flag is introduced.
+ */
+ bool no_cols_published;
} RelationSyncEntry;

But, what about when Bitmapset *columns is not null, but has no bits
set -- doesn't that mean the same as "no columns"?

======
src/include/catalog/pg_publication.h

13.
extern Bitmapset *pub_form_cols_map(Relation relation,
- PublishGencolsType include_gencols_type);
+ PublishGencolsType include_gencols_type,
+ Bitmapset *exceptcols);

Maybe snake-case like the other params: /exceptcols/except_cols/

======
src/test/regress/sql/publication.sql

14.
+-- Verify that publication is created with EXCEPT
+CREATE PUBLICATION testpub_except FOR TABLE pub_test_except1,
pub_sch1.pub_test_except2 EXCEPT (b, c);
+SELECT * FROM pg_publication_tables WHERE pubname = 'testpub_except';
+

I think tests should also use psql \dRp+ commands in places to show
that the "describe" stuff is working correctly.

~~~

15.
+-- Check for invalid cases
+CREATE PUBLICATION testpub_except2 FOR TABLES IN SCHEMA pub_sch1,
TABLE pub_test_except1 EXCEPT (b, c);
+CREATE PUBLICATION testpub_except2 FOR TABLE pub_test_except1 EXCEPT;

Should explain more about what you are testing here:
a) cannot use EXCEPT col-lists combined with TABLES IN SCHEMA
b) syntax error EXCEPT without a col-list

~~~

16.
+-- Verify that publication can be altered with EXCEPT
+ALTER PUBLICATION testpub_except SET TABLE pub_test_except1 EXCEPT
(a, b), pub_sch1.pub_test_except2;
+SELECT * FROM pg_publication_tables WHERE pubname = 'testpub_except';

The comment is a bit misleading because there are many kinds of
"alter". Maybe say more like
Verify ok - ALTER PUBLICATION ... SET ... EXCEPT (col-list)

~~~

17.
+-- Verify ALTER PUBLICATION ... DROP
+ALTER PUBLICATION testpub_except DROP TABLE pub_test_except1 EXCEPT (a, b);
+ALTER PUBLICATION testpub_except DROP TABLE pub_test_except1;

Should explain more:
+-- Verify fails - ALTER PUBLICATION ... DROP ... EXCEPT (col-list)
+-- Verify ok - ALTER PUBLICATION ... DROP ...

~~~

18.
+ALTER PUBLICATION testpub_except ADD TABLE pub_test_except1 EXCEPT (c, d);
+SELECT * FROM pg_publication_tables WHERE pubname = 'testpub_except';

Missing comment:
+-- Verify ok - ALTER PUBLICATION ... ADD ... EXCEPT (col-list)

~~~

19.
+-- Verify excluded columns cannot be part of REPLICA IDENTITY
+ALTER TABLE pub_test_except1 REPLICA IDENTITY FULL;
+UPDATE pub_test_except1 SET a = 3 WHERE a = 1;

+CREATE UNIQUE INDEX pub_test_except1_a_idx ON pub_test_except1 (a, c);
+ALTER TABLE pub_test_except1 REPLICA IDENTITY USING INDEX
pub_test_except1_a_idx;
+UPDATE pub_test_except1 SET a = 3 WHERE a = 1;

+DROP INDEX pub_test_except1_a_idx;
+CREATE UNIQUE INDEX pub_test_except1_a_idx ON pub_test_except1 (a);
+ALTER TABLE pub_test_except1 REPLICA IDENTITY USING INDEX
pub_test_except1_a_idx;
+UPDATE pub_test_except1 SET a = 3 WHERE a = 1;
+
+DROP INDEX pub_test_except1_a_idx;

19a.
IIUC, really there are multiple tests here, so I think it should all
be split and commented separately.

a) Verify that EXCEPT col-list cannot contain RI cols (when using RI FULL)
b) Verify that EXCEPT col-list cannot contain RI cols (when using INDEX)
c) Verify that so long as no clash between RI cols and the EXCEPT
col-list, then it is ok

~

19b.
IMO, some index names could be better:

CREATE UNIQUE INDEX pub_test_except1_a_idx ON pub_test_except1 (a, c);
How about 'pub_test_except1_ac_idx'?

~~~

20.
+DROP PUBLICATION testpub_except;
+DROP TABLE pub_test_except1;
+DROP TABLE pub_sch1.pub_test_except2;

Add a "cleanup" comment.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-06-30 06:23:44
Message-ID: CAHut+PvqwShhes_xNGi5WKB_WSB3ue8s6G4=3YC2PQxNowN8vg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok,

One more thing, I noticed there is no tab-completion code yet for this
new EXCEPT (column_list) syntax.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2025-06-30 06:58:25
Message-ID: CAJpy0uDWRRgg9O8dmbBsS2Lu7SJMMOmsbfYNJG4R8saPVK-EQw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Jun 27, 2025 at 3:44 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> On Thu, 26 Jun 2025 at 15:27, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > On Tue, Jun 24, 2025 at 9:48 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > >
> > > I have included the changes for
> > > it in v14-0003 patch.
> > >
> > Thanks for the patches. I have reviewed patch001 alone, please find
> > few comments:
> >
> > 1)
> > + <para>
> > + The <literal>RESET</literal> clause will reset the publication to the
> > + default state which includes resetting the publication parameters, setting
> > + <literal>ALL TABLES</literal> flag to <literal>false</literal> and
> > + dropping all relations and schemas that are associated with the
> > + publication.
> > </para>
> >
> > It is misleading, as far as I have understood, we do not drop the
> > tables or schemas associated with the pub; we just remove those from
> > the publication's object list. See previous doc:
> > "The ADD and DROP clauses will add and remove one or more
> > tables/schemas from the publication"
> >
> > Perhaps we want to say the same thing when we speak about the 'drop'
> > aspect of RESET.
> I have updated the document.
>
> > 2)
> > AlterPublicationReset():
> >
> > + if (!OidIsValid(prid))
> > + ereport(ERROR,
> > + (errcode(ERRCODE_UNDEFINED_OBJECT),
> > + errmsg("relation \"%s\" is not part of the publication",
> > + get_rel_name(relid))));
> >
> > Can you please help me understand which scenario will give this error?
> >
> > Another question is do we really need this error? IIUC, we generally
> > give errors if a user has explicitly called out a name of an object
> > and that object is not found. Example:
> >
> > postgres=# alter publication pubnew drop table t1,tab2;
> > ERROR: relation "t1" is not part of the publication
> >
> > While in a few other cases, we pass missing_okay as true and do not
> > give errors. Please see other callers of performDeletion in
> > publicationcmds.c itself. There we have usage of missing_okay=true. I
> > have not researched myself, but please analyze the cases where
> > missing_okay is passed as true to figure out if those match our RESET
> > case. Try to reproduce if possible and then take a call.
> I thought about the above point and I also think this check is not
> required. Also, the function was calling PublicationDropSchemas with
> missing_ok as false. I have changed it to be true.
>

Okay. Is there a reason for not using PublicationDropTables() here? We
have rewritten similar code in the Reset flow.

> > 3)
> > +ALTER PUBLICATION testpub_reset ADD ALL TABLES IN SCHEMA public;
> > +ERROR: syntax error at or near "ALL"
> > +LINE 1: ALTER PUBLICATION testpub_reset ADD ALL TABLES IN SCHEMA pub...
> >
> > There is a problem in syntax, I think the intention of testcase was to
> > run this query successfully.
>
> I have fixed it.
>
> Thanks Shveta for reviewing the patch. I have addressed the comments
> and posted an updated version v15 in [1].

Thanks for the patches. My review is in progress but please find few
comments on 002:

1)
where exception_object is:
[ ONLY ] table_name [ * ]

We have the above in CREATE and ALTER pub docs, but we do not explain
ONLY with EXCEPT. We do have an explanation of ONLY under 'FOR TABLE'.
But since 'FOR TABLE' and 'EXCEPT' do not go together, it is somewhat
difficult to connect the dots and find the information ONLY in the
context of EXCEPT. We shall have ONLY explained for EXCEPT as well. Or
we can have ONLY defined in a way that both 'FOR TABLE' and 'EXCEPT'
can refer to it.

2)
We get tab-completion options in this command:
postgres=# create publication pub5 for TABLE tab1 W
WHERE ( WITH (

Similarly in this command:
create publication pub5 for TABLES IN SCHEMA s1

But once we have 'EXCEPT TABLE', we do not get further tab-completion
option like WITH(...)
create publication pub5 for ALL TABLES EXCEPT TABLE tab1

3)
During tab-expansion, 'EXCEPT TABLE' and 'WITH (' in the below
command looks like they are connecting words. Can the gap be increased
similar to tab-expansion of next command shown below:

postgres=# create publication pub4 for ALL TABLES
EXCEPT TABLE WITH (

postgres=# create publication pub4 for
ALL TABLES TABLE TABLES IN SCHEMA

4)
alter_publication.sgml.orig is a left-over in patch002.

thanks
Shveta


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2025-06-30 10:55:18
Message-ID: CAJpy0uAB+4nB5s2P0YdFAbNhOuB1UFFL5SyogDuGNedETA+d_w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Few more comments on 002:

5)
+GetAllTablesPublicationRelations(Oid pubid, bool pubviaroot)
{

+ List *exceptlist;
+
+ exceptlist = GetPublicationRelations(pubid, PUBLICATION_PART_ALL);

a) Here, we are assuming that the list provided by
GetPublicationRelations() will be except-tables list only, but there
is no validation of that.
b) We are using GetPublicationRelations() to get the relations which
are excluded from the publication. The name of function and comments
atop function are not in alignment with this usage.

Suggestion:
We can have a new GetPublicationExcludeRelations() function for the
concerned usage. The existing logic of GetPublicationRelations() can
be shifted to a new internal-logic function which will accept a
'except-flag' as well. Both GetPublicationRelations() and
GetPublicationExcludeRelations() can call that new function by passing
'except-flag' as false and true respectively. The new internal
function will validate 'prexcept' against that except-flag passed and
will return the results.

6)
Before your patch002, GetTopMostAncestorInPublication() was checking
pg_publication_rel and pg_publication_namespace to find out if the
table in the ancestor-list is part of a given particular. Both
pg_publication_rel and pg_publication_namespace did not have the entry
"for all tables" publications. That means
GetTopMostAncestorInPublication() was originally not checking whether
the given puboid is an "for all tables" publication to see if a rel
belongs to that particular pub or not. I

But now with the current change, we do check if pub is all-tables pub,
if so, return relid and mark ancestor_level (provided table is not
part of the except list). IIUC, the result in 2 cases may be
different. Is that the intention? Let me know if my understanding is
wrong.

thanks
Shveta


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-07-19 10:44:03
Message-ID: CANhcyEW2LK4diNeCG862DE40yQoV3VAgf59kXUq2TuR8fnw5vQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 30 Jun 2025 at 11:37, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok.
>
> Some review comments for v15-0003.
>
> ======
> doc/src/sgml/catalogs.sgml
>
> 1.
> <para>
> - True if the relation must be excluded
> + True if the column list or relation must be excluded from publication.
> + If a column list is specified in <literal>prattrs</literal>, then
> + exclude only those columns. If <literal>prattrs</literal> is NULL,
> + then exclude the entire relation.
> </para></entry>
>
> I noticed other fields on this page say "null" instead of "NULL". It
> seems like "null" is more conventional.
>
Fixed

> ======
> doc/src/sgml/logical-replication.sgml
>
> 2.
> <para>
> If no column list is specified, any columns added to the table later are
> automatically replicated. This means that having a column list which names
> - all columns is not the same as having no column list at all.
> + all columns is not the same as having no column list at all.
> Similarly, if an
> + column list is specified with EXCEPT, any columns added to the table later
> + are also replicated automatically.
> </para>
>
> 2a.
> CURRENTLY
> If no column list or a column list with EXCEPT is specified, any
> columns added to the table later are automatically replicated. This
> means that having a column list which names all columns is not the
> same as having no column list at all. If an column list is specified,
> any columns added to the table later are automatically replicated.
>
> ~
>
> That still doesn't quite make sense. I think instead of saying "This
> means..." it needs to say something a bit like below:
>
> However, a normal column list (without EXCEPT) only
> specified columns and no more. Therefore, having a column list that
> names all columns is not the same as having no column list at all, as
> more columns may be added to the table later.
>
Fixed

> ~
>
> 2b.
> And the final sentence "If an column list..." looks like a cut/paste error (??)
>
Yes it was a mistake.

> ~
>
> 2c.
> Maybe here EXCEPT should be written as <literal>EXCEPT</literal>
>
Fixed.

> ~~~
>
> 2.5A.
> The description about generated columns still says this:
>
> CURRENT:
> Generated columns can also be specified in a column list. This allows
> generated columns to be published, regardless of the publication
> parameter publish_generated_columns. See Section 29.6 for details.
>
> ~
>
> But I don't think it is quite correct. IMO gencols behaviour is much
> more subtle...
>
> e.g.
>
> a) Normal collist - these named cols are published REGARDLESS of the
> 'publish_generated_cols' parameter (same as before)
>
> b) EXCEPT collist - you can specify gencols in the list REGARDLESS of
> the 'publish_generated_cols' parameter, because since they are named
> as "except" then they will not be published anyhow....
>
> c) BUT for EXCEPT collist case, I think any gencols that are *not*
> covered by that EXCEPT collist should follow the rules according to
> the 'publish_generated_cols' parameter.
>
> So, it is much more tricky than the docs currently say:
>
Modified the documentation

> Also
>
> 2.5B.
> - The text says "See Section 29.6 for details," but there are no
> examples of these combinations (e.g. EXCEPT collist and diff parameter
> setting)
>
Added documentation.

> 2.5C,
> - The regression tests also need to be more complex to cover these
>
Added tests related to these

> 2.5D.
> - You might need to add something in the CREATE PUBLICATION "NOTES"
> section after all -- even if it just refers to here.
>
Added documentation

> ~~~
>
> 3.
> <para>
> Create a publication <literal>p1</literal>. A column list is defined for
> - table <literal>t1</literal> to reduce the number of columns that will be
> - replicated. Notice that the order of column names in the column list does
> - not matter.
> + table <literal>t1</literal>, and another column list is defined for table
> + <literal>t2</literal> using the EXCEPT clause to reduce the number of
> + columns that will be replicated. Note that the order of column names in
> + the column lists does not matter.
> <programlisting>
> -/* pub # */ CREATE PUBLICATION p1 FOR TABLE t1 (id, b, a, d);
> +/* pub # */ CREATE PUBLICATION p1 FOR TABLE t1 (id, b, a, d), t2 EXCEPT (d, a);
> </programlisting></para>
>
> Maybe here EXCEPT should be written as <literal>EXCEPT</literal>
>
Fixed

> ======
> doc/src/sgml/ref/create_publication.sgml
>
> 4.
> <para>
> - When a column list is specified, only the named columns are replicated.
> - The column list can contain stored generated columns as well. If the
> - column list is omitted, the publication will replicate all non-generated
> - columns (including any added in the future) by default. Stored generated
> - columns can also be replicated if
> <literal>publish_generated_columns</literal>
> - is set to <literal>stored</literal>. Specifying a column list has no
> - effect on <literal>TRUNCATE</literal> commands. See
> + When a column list without EXCEPT is specified, only the named
> columns are
> + replicated. The column list can contain stored generated columns as well.
> + If the column list is omitted, the publication will replicate
> + all non-generated columns (including any added in the future) by default.
> + Stored generated columns can also be replicated if
> + <literal>publish_generated_columns</literal> is set to
> + <literal>stored</literal>. Specifying a column list has no effect on
> + <literal>TRUNCATE</literal> commands. See
> <xref linkend="logical-replication-col-lists"/> for details about column
> lists.
> </para>
>
> Maybe here EXCEPT should be written as <literal>EXCEPT</literal>
>
Fixed
> ~~~
>
> 5.
> + <para>
> + When a column list is specified with EXCEPT, the named columns are not
> + replicated. Specifying a column list has no effect on
> + <literal>TRUNCATE</literal> commands.
> + </para>
>
> Maybe here EXCEPT should be written as <literal>EXCEPT</literal>.
>
Fixed

> ** Note all the extra subtleties that I mentioned in the review
> comment #2.5 above --- e.g. IMO any *un-listed* gencols still should
> follow the parameter rules.
>
> ~~~
>
> 6.
> <para>
> Any column list must include the <literal>REPLICA IDENTITY</literal> columns
> - in order for <command>UPDATE</command> or <command>DELETE</command>
> - operations to be published. There are no column list restrictions if the
> - publication publishes only <command>INSERT</command> operations.
> + and any column list specified with EXCEPT must not include the
> + <literal>REPLICA IDENTITY</literal> columns in order for
> + <command>UPDATE</command> or <command>DELETE</command> operations to be
> + published. There are no column list restrictions if the
> publication publishes
> + only <command>INSERT</command> operations.
> </para>
>
> 6a.
> CURRENT:
> Any column list must include the REPLICA IDENTITY columns, and any
> column list specified with EXCEPT must not include the REPLICA
> IDENTITY columns in order for UPDATE or DELETE operations to be
> published.
>
> ~
>
> I felt that might be better expressed the other way around. Also, it
> might be better to say "not name" instead of "not include" because
> EXCEPT + include seemed a bit contrary.
>
>
> SUGGESTION (maybe like this)
> In order for UPDATE or DELETE operations to work, all the REPLICA
> IDENTITY columns must be published. So, any column list must name all
> REPLICA IDENTITY columns, and any EXCEPT column list must not name any
> REPLICA IDENTITY columns.
>
Fixed

> ~~
>
> 6b.
> Maybe here EXCEPT should be written as <literal>EXCEPT</literal>
>
Fixed

> ======
> src/backend/catalog/pg_publication.c
>
> check_and_fetch_column_list:
>
> 7.
> + /* Lookup the except attribute */
> + cfdatum = SysCacheGetAttr(PUBLICATIONRELMAP, cftuple,
> + Anum_pg_publication_rel_prexcept, &isnull);
> +
> + if (!isnull)
> + {
> + Assert(!pub->alltables);
> + *except_columns = DatumGetBool(cfdatum);
> + }
> +
>
> I felt it would be safer to also assign *except_columns = false;
> up-front so the caller could be sure this flag was meaningful on
> return.
>
Fixed

> ~~~
>
> pub_form_cols_map:
>
> 8.
> Maybe use snake case like for other params, so /excepcols/except_cols/
>
Fixed

> ~~~
>
> pg_get_publication_tables:
>
> 9.
>
> I felt all the logic in this function maybe can be simpler:
>
> e.g. If you just have "Bitmapset *except_columns = NULL;" then null
> nmeans there is no except columns; otherwise there is. This means you
> don't need a separate 'bool except_column' variable.
>
> e.g. Assign the Bitmapset *except_columns after you already have the
> values[2], instead of doing it later.
>
> e.g. The skip code if (except_columns && bms_is_member(att->attnum,
> columns)) could just check the list member, I think, without the
> additional bool.
>
> ~~~
>
Fixed

> 10.
> + /*
> + * We fetch pubtuple if publication is not FOR ALL TABLES and not
> + * FOR TABLES IN SCHEMA. So if prexcept is true, it indicate that
> + * prattrs contains columns to be excluded for replication.
> + */
> + if (!isnull)
> + except_columns = DatumGetBool(exceptDatum);
>
>
> /indicate/indicates/
>
Fixed

> ======
> src/backend/parser/gram.y
>
> 11.
> + | TABLE relation_expr EXCEPT opt_except_column_list OptWhereClause
> + {
> + $$ = makeNode(PublicationObjSpec);
> + $$->pubobjtype = PUBLICATIONOBJ_TABLE;
> + $$->pubtable = makeNode(PublicationTable);
> + $$->pubtable->relation = $2;
> + $$->pubtable->columns = $4;
> + $$->pubtable->whereClause = $5;
> + $$->pubtable->except = true;
> + $$->location = @1;
> + }
>
> I wasn't expecting you would need another 'opt_except_column_list' and
> all the code duplication that causes. AFAIK, the syntax is identical
> for 'opt_column_list' apart from the preceding EXCEPT so I thought all
> you need is to allow the 'opt_column_list' to have an optional EXCEPT
> qualifier.
>
The main reason I used a separate 'opt_except_column_list' is because
'opt_column_list' can also be NULL. But the column list specified with
EXCEPT not be NULL. So, 'opt_except_column_list' is defined such that
it cannot be null.

> ======
> src/backend/replication/pgoutput/pgoutput.c
>
> 12.
> +
> + /*
> + * Indicates whether no columns are published for a given relation. With
> + * the introduction of the EXCEPT clause in column lists, it is now
> + * possible to define a publication that excludes all columns of a table.
> + * However, the 'columns' attribute cannot represent this case, since a
> + * NULL value implies that all columns are published. To distinguish this
> + * scenario, the 'no_cols_published' flag is introduced.
> + */
> + bool no_cols_published;
> } RelationSyncEntry;
>
> But, what about when Bitmapset *columns is not null, but has no bits
> set -- doesn't that mean the same as "no columns"?
>
I think this is possible. A bitmapset which has no set bit is NULL. I
saw following comment in bitmapset.c
"By convention, we always represent a set with
* the minimum possible number of words, i.e, there are never any trailing
* zero words. Enforcing this requires that an empty set is represented as
* NULL. Because an empty Bitmapset is represented as NULL, a non-NULL
* Bitmapset always has at least 1 Bitmapword."

> ======
> src/include/catalog/pg_publication.h
>
> 13.
> extern Bitmapset *pub_form_cols_map(Relation relation,
> - PublishGencolsType include_gencols_type);
> + PublishGencolsType include_gencols_type,
> + Bitmapset *exceptcols);
>
> Maybe snake-case like the other params: /exceptcols/except_cols/
>
Fixed

> ======
> src/test/regress/sql/publication.sql
>
> 14.
> +-- Verify that publication is created with EXCEPT
> +CREATE PUBLICATION testpub_except FOR TABLE pub_test_except1,
> pub_sch1.pub_test_except2 EXCEPT (b, c);
> +SELECT * FROM pg_publication_tables WHERE pubname = 'testpub_except';
> +
>
> I think tests should also use psql \dRp+ commands in places to show
> that the "describe" stuff is working correctly.
>
> ~~~
Fixed

>
> 15.
> +-- Check for invalid cases
> +CREATE PUBLICATION testpub_except2 FOR TABLES IN SCHEMA pub_sch1,
> TABLE pub_test_except1 EXCEPT (b, c);
> +CREATE PUBLICATION testpub_except2 FOR TABLE pub_test_except1 EXCEPT;
>
> Should explain more about what you are testing here:
> a) cannot use EXCEPT col-lists combined with TABLES IN SCHEMA
> b) syntax error EXCEPT without a col-list
>
> ~~~
fixed

>
> 16.
> +-- Verify that publication can be altered with EXCEPT
> +ALTER PUBLICATION testpub_except SET TABLE pub_test_except1 EXCEPT
> (a, b), pub_sch1.pub_test_except2;
> +SELECT * FROM pg_publication_tables WHERE pubname = 'testpub_except';
>
> The comment is a bit misleading because there are many kinds of
> "alter". Maybe say more like
> Verify ok - ALTER PUBLICATION ... SET ... EXCEPT (col-list)
>
> ~~~
Fixed

>
> 17.
> +-- Verify ALTER PUBLICATION ... DROP
> +ALTER PUBLICATION testpub_except DROP TABLE pub_test_except1 EXCEPT (a, b);
> +ALTER PUBLICATION testpub_except DROP TABLE pub_test_except1;
>
> Should explain more:
> +-- Verify fails - ALTER PUBLICATION ... DROP ... EXCEPT (col-list)
> +-- Verify ok - ALTER PUBLICATION ... DROP ...
>
> ~~~
Fixed

>
> 18.
> +ALTER PUBLICATION testpub_except ADD TABLE pub_test_except1 EXCEPT (c, d);
> +SELECT * FROM pg_publication_tables WHERE pubname = 'testpub_except';
>
> Missing comment:
> +-- Verify ok - ALTER PUBLICATION ... ADD ... EXCEPT (col-list)
>
> ~~~
Fixed

>
> 19.
> +-- Verify excluded columns cannot be part of REPLICA IDENTITY
> +ALTER TABLE pub_test_except1 REPLICA IDENTITY FULL;
> +UPDATE pub_test_except1 SET a = 3 WHERE a = 1;
>
> +CREATE UNIQUE INDEX pub_test_except1_a_idx ON pub_test_except1 (a, c);
> +ALTER TABLE pub_test_except1 REPLICA IDENTITY USING INDEX
> pub_test_except1_a_idx;
> +UPDATE pub_test_except1 SET a = 3 WHERE a = 1;
>
> +DROP INDEX pub_test_except1_a_idx;
> +CREATE UNIQUE INDEX pub_test_except1_a_idx ON pub_test_except1 (a);
> +ALTER TABLE pub_test_except1 REPLICA IDENTITY USING INDEX
> pub_test_except1_a_idx;
> +UPDATE pub_test_except1 SET a = 3 WHERE a = 1;
> +
> +DROP INDEX pub_test_except1_a_idx;
>
> 19a.
> IIUC, really there are multiple tests here, so I think it should all
> be split and commented separately.
>
> a) Verify that EXCEPT col-list cannot contain RI cols (when using RI FULL)
> b) Verify that EXCEPT col-list cannot contain RI cols (when using INDEX)
> c) Verify that so long as no clash between RI cols and the EXCEPT
> col-list, then it is ok
>
> ~
Fixed

>
> 19b.
> IMO, some index names could be better:
>
> CREATE UNIQUE INDEX pub_test_except1_a_idx ON pub_test_except1 (a, c);
> How about 'pub_test_except1_ac_idx'?
>
> ~~~
>
Fixed

> 20.
> +DROP PUBLICATION testpub_except;
> +DROP TABLE pub_test_except1;
> +DROP TABLE pub_sch1.pub_test_except2;
>
> Add a "cleanup" comment.
>
Added

I have addressed the comments and added the latest v16.

Thanks and Regards,
Shlok Kyal

Attachment Content-Type Size
v16-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 71.8 KB
v16-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 20.2 KB
v16-0003-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 61.8 KB

From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-07-19 10:44:51
Message-ID: CANhcyEWvrPh6zMVXHQ53vY09erraumgmddRwUsA-36dQu4tt6w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 30 Jun 2025 at 12:28, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Fri, Jun 27, 2025 at 3:44 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > On Thu, 26 Jun 2025 at 15:27, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> > >
> > > On Tue, Jun 24, 2025 at 9:48 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > > >
> > > > I have included the changes for
> > > > it in v14-0003 patch.
> > > >
> > > Thanks for the patches. I have reviewed patch001 alone, please find
> > > few comments:
> > >
> > > 1)
> > > + <para>
> > > + The <literal>RESET</literal> clause will reset the publication to the
> > > + default state which includes resetting the publication parameters, setting
> > > + <literal>ALL TABLES</literal> flag to <literal>false</literal> and
> > > + dropping all relations and schemas that are associated with the
> > > + publication.
> > > </para>
> > >
> > > It is misleading, as far as I have understood, we do not drop the
> > > tables or schemas associated with the pub; we just remove those from
> > > the publication's object list. See previous doc:
> > > "The ADD and DROP clauses will add and remove one or more
> > > tables/schemas from the publication"
> > >
> > > Perhaps we want to say the same thing when we speak about the 'drop'
> > > aspect of RESET.
> > I have updated the document.
> >
> > > 2)
> > > AlterPublicationReset():
> > >
> > > + if (!OidIsValid(prid))
> > > + ereport(ERROR,
> > > + (errcode(ERRCODE_UNDEFINED_OBJECT),
> > > + errmsg("relation \"%s\" is not part of the publication",
> > > + get_rel_name(relid))));
> > >
> > > Can you please help me understand which scenario will give this error?
> > >
> > > Another question is do we really need this error? IIUC, we generally
> > > give errors if a user has explicitly called out a name of an object
> > > and that object is not found. Example:
> > >
> > > postgres=# alter publication pubnew drop table t1,tab2;
> > > ERROR: relation "t1" is not part of the publication
> > >
> > > While in a few other cases, we pass missing_okay as true and do not
> > > give errors. Please see other callers of performDeletion in
> > > publicationcmds.c itself. There we have usage of missing_okay=true. I
> > > have not researched myself, but please analyze the cases where
> > > missing_okay is passed as true to figure out if those match our RESET
> > > case. Try to reproduce if possible and then take a call.
> > I thought about the above point and I also think this check is not
> > required. Also, the function was calling PublicationDropSchemas with
> > missing_ok as false. I have changed it to be true.
> >
>
> Okay. Is there a reason for not using PublicationDropTables() here? We
> have rewritten similar code in the Reset flow.
>
I feel it's better to use the function PublicationDropTables(). Also
proper locking would be required on tables while dropping them from
publication.
Made changes for the same.

> > > 3)
> > > +ALTER PUBLICATION testpub_reset ADD ALL TABLES IN SCHEMA public;
> > > +ERROR: syntax error at or near "ALL"
> > > +LINE 1: ALTER PUBLICATION testpub_reset ADD ALL TABLES IN SCHEMA pub...
> > >
> > > There is a problem in syntax, I think the intention of testcase was to
> > > run this query successfully.
> >
> > I have fixed it.
> >
> > Thanks Shveta for reviewing the patch. I have addressed the comments
> > and posted an updated version v15 in [1].
>
> Thanks for the patches. My review is in progress but please find few
> comments on 002:
>
> 1)
> where exception_object is:
> [ ONLY ] table_name [ * ]
>
> We have the above in CREATE and ALTER pub docs, but we do not explain
> ONLY with EXCEPT. We do have an explanation of ONLY under 'FOR TABLE'.
> But since 'FOR TABLE' and 'EXCEPT' do not go together, it is somewhat
> difficult to connect the dots and find the information ONLY in the
> context of EXCEPT. We shall have ONLY explained for EXCEPT as well. Or
> we can have ONLY defined in a way that both 'FOR TABLE' and 'EXCEPT'
> can refer to it.
>
In create_publication.sgml, added it under "EXCEPT_TABLE'. In
alter_publication.sgml, modified the document under item 'table_name'
under "<title>Parameters</title>"

> 2)
> We get tab-completion options in this command:
> postgres=# create publication pub5 for TABLE tab1 W
> WHERE ( WITH (
>
> Similarly in this command:
> create publication pub5 for TABLES IN SCHEMA s1
>
> But once we have 'EXCEPT TABLE', we do not get further tab-completion
> option like WITH(...)
> create publication pub5 for ALL TABLES EXCEPT TABLE tab1
Fixed

> 3)
> During tab-expansion, 'EXCEPT TABLE' and 'WITH (' in the below
> command looks like they are connecting words. Can the gap be increased
> similar to tab-expansion of next command shown below:
>
> postgres=# create publication pub4 for ALL TABLES
> EXCEPT TABLE WITH (
>
I did not find a place to add any custom space. It is default
behaviour to add 2 spaces between different words. See similar:
postgres=# CREATE PUBLICATION pub1 FOR TABLE t1 W
WHERE ( WITH (

> postgres=# create publication pub4 for
> ALL TABLES TABLE TABLES IN SCHEMA
>
I observed that the space between word is dependent on the length of
longest word. Here the longest word is "TABLES IN SCHEMA". The space
between the words are quite noticeable.

> 4)
> alter_publication.sgml.orig is a left-over in patch002.
Fixed

I have added the changes in the latest v16 patch [1].
[1]: https://www.postgresql.org/message-id/CANhcyEW2LK4diNeCG862DE40yQoV3VAgf59kXUq2TuR8fnw5vQ%40mail.gmail.com

Thanks and Regards,
Shlok Kyal


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-07-19 10:45:42
Message-ID: CANhcyEURo-tW1F1bOcT4dpE5wtnibJw0iPTCFArSTrqVgY7o0g@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 30 Jun 2025 at 11:54, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok,
>
> One more thing, I noticed there is no tab-completion code yet for this
> new EXCEPT (column_list) syntax.
>

I have added the tab-completion code in the latest v16 patch [1].
[1]: https://www.postgresql.org/message-id/CANhcyEW2LK4diNeCG862DE40yQoV3VAgf59kXUq2TuR8fnw5vQ%40mail.gmail.com

Thanks and Regards,
Shlok Kyal


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-07-19 10:47:06
Message-ID: CANhcyEU9ENjbfEMRmw3MAZsOP04ORXB0Se+t_7Qcqv61sLc0dA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 30 Jun 2025 at 16:25, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> Few more comments on 002:
>
> 5)
> +GetAllTablesPublicationRelations(Oid pubid, bool pubviaroot)
> {
>
> + List *exceptlist;
> +
> + exceptlist = GetPublicationRelations(pubid, PUBLICATION_PART_ALL);
>
>
> a) Here, we are assuming that the list provided by
> GetPublicationRelations() will be except-tables list only, but there
> is no validation of that.
> b) We are using GetPublicationRelations() to get the relations which
> are excluded from the publication. The name of function and comments
> atop function are not in alignment with this usage.
>
> Suggestion:
> We can have a new GetPublicationExcludeRelations() function for the
> concerned usage. The existing logic of GetPublicationRelations() can
> be shifted to a new internal-logic function which will accept a
> 'except-flag' as well. Both GetPublicationRelations() and
> GetPublicationExcludeRelations() can call that new function by passing
> 'except-flag' as false and true respectively. The new internal
> function will validate 'prexcept' against that except-flag passed and
> will return the results.
>
I have made the above change.

> 6)
> Before your patch002, GetTopMostAncestorInPublication() was checking
> pg_publication_rel and pg_publication_namespace to find out if the
> table in the ancestor-list is part of a given particular. Both
> pg_publication_rel and pg_publication_namespace did not have the entry
> "for all tables" publications. That means
> GetTopMostAncestorInPublication() was originally not checking whether
> the given puboid is an "for all tables" publication to see if a rel
> belongs to that particular pub or not. I
>
> But now with the current change, we do check if pub is all-tables pub,
> if so, return relid and mark ancestor_level (provided table is not
> part of the except list). IIUC, the result in 2 cases may be
> different. Is that the intention? Let me know if my understanding is
> wrong.
>
This is intentional, in function get_rel_sync_entry, we are setting
pub_relid to the topmost published ancestor. In HEAD we are directly
setting using:
/*
* If this is a FOR ALL TABLES publication, pick the partition
* root and set the ancestor level accordingly.
*/
if (pub->alltables)
{
publish = true;
if (pub->pubviaroot && am_partition)
{
List *ancestors = get_partition_ancestors(relid);

pub_relid = llast_oid(ancestors);
ancestor_level = list_length(ancestors);
}
}
In HEAD, we can directly use 'llast_oid(ancestors)' to get the topmost
ancestor for case of FOR ALL TABLES.
But with this proposal. This change will no longer be valid as the
'llast_oid(ancestors)' may be excluded in the publication. So, to
handle this change was made in GetTopMostAncestorInPublication.

Also, during testing with the partitioned table and
publish_via_partition_root the behaviour of the current patch is as
below:
For example we have a partitioned table t1. It has partitions part1
and part2. Now consider the following cases:
1. with publish_via_partition_root = true
I. If we create publication on all tables with EXCEPT t1, no data
for t1, part1 or part2 is replicated.
II. If we create publication on all tables with EXCEPT part1,
data for all tables t1, part1 and part2 is replicated.
2. with publish_via_partition_root = false
I. If we create publication on all tables with EXCEPT t1, no data
for t1, part1 or part2 is replicated.
II. If we create publication on all tables with EXCEPT part1,
data for part1 is not replicated

Is this behaviour fine?
I checked for other databases such as MySQL, SQL Server. In that we do
not have such cases as either we replicate the whole partitioned table
or we not replicated at all. We do not have partition level control.
For Oracle, I found that we can include or exclude partitions using
'PARTITIONEXCLUDE' [2], but did not find something similar to
publish_via_partition_root or where partitions are published as
separate tables.
What are your thoughts on the above behaviour?

I have addressed the comments and added the changes in the latest v16 patch [1].
[1]:https://www.postgresql.org/message-id/CANhcyEW2LK4diNeCG862DE40yQoV3VAgf59kXUq2TuR8fnw5vQ%40mail.gmail.com
[2]: https://docs.oracle.com/en/middleware/goldengate/core/23/reference/partition-partitionexclude.html
Thanks,
Shlok Kyal


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-07-21 06:46:48
Message-ID: CAHut+PuSHScrODVGCM7P53Mv1HE2N6ThzkH4+gQ1eFXVeD-OCA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok.

Some review comments for patch v16-0003.

======
Commit message

1.
The column "prexcept" of system catalog "pg_publication_rel" is set to
"true" when publication is created with EXCEPT table or EXCEPT column
list. If column "prattrs" of system catalog "pg_publication_rel" is also
set or column "puballtables" of system catalog "pg_publication" is
"false", it indicates the column list is specified with EXCEPT clause
and columns in "prattrs" are excluded from being published.

~

Somehow, this seems to contain too much information, making it a bit
confusing. Can't you chop this down to something like below?

SUGESTION
When column "prexcept" of system catalog "pg_publication_rel" is set
to "true", and column "prattrs" of system catalog "pg_publication_rel"
is not NULL, that means the publication was created with "EXCEPT
(column-list)", and the columns in "prattrs" will be excluded from
being published.

======
doc/src/sgml/logical-replication.sgml

2.
Generated columns can also be specified in a column list. This allows
generated columns to be published, regardless of the publication parameter
<link linkend="sql-createpublication-params-with-publish-generated-columns">
+ <literal>publish_generated_columns</literal></link>. Generated
columns can be
+ specified in a column list using the <literal>EXCEPT</literal> clause. This
+ excludes the specified generated columns from being published, regardless of
+ the <link linkend="sql-createpublication-params-with-publish-generated-columns">
+ <literal>publish_generated_columns</literal></link> setting. However, for
+ generated columns that are not listed in the <literal>EXCEPT</literal>
+ clause, whether they are published or not still depends on the value of
+ <link linkend="sql-createpublication-params-with-publish-generated-columns">
<literal>publish_generated_columns</literal></link>. See
<xref linkend="logical-replication-gencols"/> for details.
</para>

~~

For this part:

"Generated columns can be specified in a column list using the
<literal>EXCEPT</literal> clause. This excludes the specified
generated columns from being published, regardless of..."

I think the whole paragraph already said "Generated columns can also
be specified in a column list", so you don't need to repeat it.
Instead, maybe say something like below.

SUGGESTION
Specifying generated columns in a column list using the
<literal>EXCEPT</literal> clause excludes those columns from being
published, regardless of...

~~~

3.
- Publication p1
- Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
-----------+------------+---------+---------+---------+-----------+----------
- postgres | f | t | t | t | t | f
+ Publication p1
+ Owner | All tables | Inserts | Updates | Deletes | Truncates |
Generated columns | Via root
+--------+------------+---------+---------+---------+-----------+-------------------+----------
+ ubuntu | f | t | t | t | t | none
| f
Tables:
"public.t1" (id, a, b, d)
+ "public.t2" EXCEPT (a, d)
</programlisting></para>

I noticed the Owner changed from "postgres" to "ubuntu". Do you think
it is better to keep this as "postgres" for the example?

======
doc/src/sgml/ref/create_publication.sgml

4.
The tables added to a publication that publishes UPDATE and/or DELETE
operations must have REPLICA IDENTITY defined. Otherwise those
operations will be disallowed on those tables.

In order for UPDATE or DELETE operations to work, all the REPLICA
IDENTITY columns must be published. So, any column list must name all
REPLICA IDENTITY columns, and any EXCEPT column list must not name any
REPLICA IDENTITY columns.

A row filter expression (i.e., the WHERE clause) must contain only
columns that are covered by the REPLICA IDENTITY, in order for UPDATE
and DELETE operations to be published. For publication of INSERT
operations, any column may be used in the WHERE expression. The row
filter allows simple expressions that don't have user-defined
functions, user-defined operators, user-defined types, user-defined
collations, non-immutable built-in functions, or references to system
columns.

The generated columns that are part of the column list specified with
the EXCEPT clause are not published, regardless of the
publish_generated_columns option. However, generated columns that are
not part of the column list specified with the EXCEPT clause are
published according to the value of the publish_generated_columns
option. See Section 29.6 for details.

The generated columns that are part of REPLICA IDENTITY must be
published explicitly either by listing them in the column list or by
enabling the publish_generated_columns option, in order for UPDATE and
DELETE operations to be published.

~~

Notice all those 5 paragraphs (above) are talking about REPLICA
IDENTITY, except the 4th paragraph. Maybe the 4th paragraph should be
moved to last, to keep all the REPLICA IDENTITY stuff together.

======
src/backend/catalog/pg_publication.c

5. pub_form_cols_map

* Returns a bitmap representing the columns of the specified table.
*
* Generated columns are included if include_gencols_type is
- * PUBLISH_GENCOLS_STORED.
+ * PUBLISH_GENCOLS_STORED. Columns that are in the exceptcols are excluded from
+ * the column list.
*/
Bitmapset *
-pub_form_cols_map(Relation relation, PublishGencolsType include_gencols_type)
+pub_form_cols_map(Relation relation, PublishGencolsType include_gencols_type,
+ Bitmapset *except_cols)

Forgot to add the underscore in the function comment.

/exceptcols/except_cols/

~~~

6. pg_get_publication_tables

+
+ /*
+ * We fetch pubtuple if publication is not FOR ALL TABLES and not
+ * FOR TABLES IN SCHEMA. So if prexcept is true, it indicates that
+ * prattrs contains columns to be excluded for replication.
+ */
+ exceptDatum = SysCacheGetAttr(PUBLICATIONRELMAP, pubtuple,
+ Anum_pg_publication_rel_prexcept,
+ &isnull);
+
+ if (!isnull && DatumGetBool(exceptDatum) && !nulls[2])
+ except_columns = pub_collist_to_bitmapset(NULL, values[2], NULL);

But, you cannot have EXCEPT for null column list, so shouldn't the
!nulls[2] check be done to also guard the SysCacheGetAttr call?

======
src/backend/parser/gram.y

7.

Shlok wrote [1-reply #11]
The main reason I used a separate 'opt_except_column_list' is because
'opt_column_list' can also be NULL. But the column list specified with
EXCEPT not be NULL. So, 'opt_except_column_list' is defined such that
it cannot be null.

~

Yeah, but IMO that leads to excessive duplicated code. I think the
code can perhaps be a lot simpler if the grammar is written more like
the synopsis:

e.g. TABLE name opt_EXCEPT opt_column_list

where - opt_EXCEPT is null, and opt_column_list is null... means no col list
where - opt_EXCEPT is null, and opt_column_list is not null... means
normal col list
where - opt_EXCEPT is not null, and opt_column_list not null... means
EXCEPT col list
where - opt_EXCEPT is not null, and opt_column_list null... SYNTAX ERROR

So code it something like this (just adding opt_EXCEPT to the existing
productions)

%type <boolean> opt_ordinality opt_without_overlaps opt_EXCEPT
...
opt_EXCEPT:
EXCEPT { $$ = true; }
| /*EMPTY*/ { $$ = false; }
;
...
TABLE relation_expr opt_EXCEPT opt_column_list OptWhereClause
{
$$ = makeNode(PublicationObjSpec);
$$->pubobjtype = PUBLICATIONOBJ_TABLE;
$$->pubtable = makeNode(PublicationTable);
$$->pubtable->relation = $2;
$$->pubtable->except = $3;
$$->pubtable->columns = $4;
if ($3 && !$4)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("EXCEPT without column list"),
parser_errposition(@3)));
$$->pubtable->whereClause = $5;
$$->location = @1;
}

etc.

======
src/bin/psql/describe.c

8.
if (!PQgetisnull(res, i, 3))
+ {
+ if (!PQgetisnull(res, i, 4) && strcmp(PQgetvalue(res, i, 4), "t") == 0)
+ appendPQExpBuffer(buf, " EXCEPT");
appendPQExpBuffer(buf, " (%s)", PQgetvalue(res, i, 3));
+ }

This growing list of columns makes it hard to understand this function
without looking back at the caller all the time. Maybe you can add a
function comment that at least explains what those attributes 1,2,3,4
represent?

======
src/bin/psql/tab-complete.in.c

9.
+ else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|SET",
"TABLE", MatchAny))
+ COMPLETE_WITH("EXCEPT");

Since it is not allowed to have an EXCEPT with no column list,
shouldn't this say "EXCEPT ("?

~~~

10.
else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE",
MatchAny) && !ends_with(prev_wd, ','))
- COMPLETE_WITH("WHERE (", "WITH (");
+ COMPLETE_WITH("EXCEPT", "WHERE (", "WITH (");

Ditto. Since it is not allowed to have an EXCEPT with no column list,
shouldn't this say "EXCEPT ("?

======
src/test/regress/expected/publication.out

11.
+-- Verify that EXCEPT col-list cannot contain RI cols (when using INDEX)
+CREATE UNIQUE INDEX pub_test_except1_ac_idx ON pub_test_except1 (a, c);
+ALTER TABLE pub_test_except1 REPLICA IDENTITY USING INDEX
pub_test_except1_a_idx;
+ERROR: index "pub_test_except1_a_idx" for table "pub_test_except1"
does not exist
+UPDATE pub_test_except1 SET a = 3 WHERE a = 1;
+ERROR: cannot update table "pub_test_except1"
+DETAIL: Column list used by the publication does not cover the
replica identity.
+DROP INDEX pub_test_except1_ac_idx;

What's happening here? I'm not sure these are the kind of errors you
were trying to cause.

======
src/test/regress/sql/publication.sql

12.
+-- Verify that EXCEPT col-list cannot contain RI cols (when using RI FULL)
+ALTER TABLE pub_test_except1 REPLICA IDENTITY FULL;
+UPDATE pub_test_except1 SET a = 3 WHERE a = 1;

SUGGESTION. Change that comment to:
Verify fails - EXCEPT col-list cannot...

~~~

13.
+-- Verify that EXCEPT col-list cannot contain RI cols (when using INDEX)
+CREATE UNIQUE INDEX pub_test_except1_ac_idx ON pub_test_except1 (a, c);
+ALTER TABLE pub_test_except1 REPLICA IDENTITY USING INDEX
pub_test_except1_a_idx;
+UPDATE pub_test_except1 SET a = 3 WHERE a = 1;
+DROP INDEX pub_test_except1_ac_idx;

SUGGESTION. Change that comment to:
Verify fails - EXCEPT col-list cannot...

~~~

14.
+-- Verify that so long as no clash between RI cols and the EXCEPT
+CREATE UNIQUE INDEX pub_test_except1_a_idx ON pub_test_except1 (a);
+ALTER TABLE pub_test_except1 REPLICA IDENTITY USING INDEX
pub_test_except1_a_idx;
+UPDATE pub_test_except1 SET a = 3 WHERE a = 1;
+

That comment doesn't make sense. Missing words?

======
.../t/036_rep_changes_except_table.pl

15.
(I haven't reviewed this file in detail yet, but here is a general comment)

I know this patch currently lives in the same thread as all the EXCEPT
TABLE stuff, but that seems just happenstance to me. IMO, this is a
separate enhancement that just shares the keyword EXCEPT. So, I felt
it should have quite separate tests too.

e.g. How about: 037_rep_changes_except_collist.pl

======
[1] https://www.postgresql.org/message-id/CANhcyEW2LK4diNeCG862DE40yQoV3VAgf59kXUq2TuR8fnw5vQ%40mail.gmail.com

Kind Regards,
Peter Smith.
Fujitsu Australia


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2025-07-21 10:52:42
Message-ID: CAJpy0uB=J9a=zQXKuznTYqRrCYy8rm1pHfWLA10XHp0UojYpdA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, Jul 19, 2025 at 4:17 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> On Mon, 30 Jun 2025 at 16:25, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > Few more comments on 002:
> >
> > 5)
> > +GetAllTablesPublicationRelations(Oid pubid, bool pubviaroot)
> > {
> >
> > + List *exceptlist;
> > +
> > + exceptlist = GetPublicationRelations(pubid, PUBLICATION_PART_ALL);
> >
> >
> > a) Here, we are assuming that the list provided by
> > GetPublicationRelations() will be except-tables list only, but there
> > is no validation of that.
> > b) We are using GetPublicationRelations() to get the relations which
> > are excluded from the publication. The name of function and comments
> > atop function are not in alignment with this usage.
> >
> > Suggestion:
> > We can have a new GetPublicationExcludeRelations() function for the
> > concerned usage. The existing logic of GetPublicationRelations() can
> > be shifted to a new internal-logic function which will accept a
> > 'except-flag' as well. Both GetPublicationRelations() and
> > GetPublicationExcludeRelations() can call that new function by passing
> > 'except-flag' as false and true respectively. The new internal
> > function will validate 'prexcept' against that except-flag passed and
> > will return the results.
> >
> I have made the above change.
>
>
> > 6)
> > Before your patch002, GetTopMostAncestorInPublication() was checking
> > pg_publication_rel and pg_publication_namespace to find out if the
> > table in the ancestor-list is part of a given particular. Both
> > pg_publication_rel and pg_publication_namespace did not have the entry
> > "for all tables" publications. That means
> > GetTopMostAncestorInPublication() was originally not checking whether
> > the given puboid is an "for all tables" publication to see if a rel
> > belongs to that particular pub or not. I
> >
> > But now with the current change, we do check if pub is all-tables pub,
> > if so, return relid and mark ancestor_level (provided table is not
> > part of the except list). IIUC, the result in 2 cases may be
> > different. Is that the intention? Let me know if my understanding is
> > wrong.
> >
> This is intentional, in function get_rel_sync_entry, we are setting
> pub_relid to the topmost published ancestor. In HEAD we are directly
> setting using:
> /*
> * If this is a FOR ALL TABLES publication, pick the partition
> * root and set the ancestor level accordingly.
> */
> if (pub->alltables)
> {
> publish = true;
> if (pub->pubviaroot && am_partition)
> {
> List *ancestors = get_partition_ancestors(relid);
>
> pub_relid = llast_oid(ancestors);
> ancestor_level = list_length(ancestors);
> }
> }
> In HEAD, we can directly use 'llast_oid(ancestors)' to get the topmost
> ancestor for case of FOR ALL TABLES.
> But with this proposal. This change will no longer be valid as the
> 'llast_oid(ancestors)' may be excluded in the publication. So, to
> handle this change was made in GetTopMostAncestorInPublication.
>
>
> Also, during testing with the partitioned table and
> publish_via_partition_root the behaviour of the current patch is as
> below:
> For example we have a partitioned table t1. It has partitions part1
> and part2. Now consider the following cases:
> 1. with publish_via_partition_root = true
> I. If we create publication on all tables with EXCEPT t1, no data
> for t1, part1 or part2 is replicated.
> II. If we create publication on all tables with EXCEPT part1,
> data for all tables t1, part1 and part2 is replicated.
> 2. with publish_via_partition_root = false
> I. If we create publication on all tables with EXCEPT t1, no data
> for t1, part1 or part2 is replicated.
> II. If we create publication on all tables with EXCEPT part1,
> data for part1 is not replicated
>
> Is this behaviour fine?
> I checked for other databases such as MySQL, SQL Server. In that we do
> not have such cases as either we replicate the whole partitioned table
> or we not replicated at all. We do not have partition level control.
> For Oracle, I found that we can include or exclude partitions using
> 'PARTITIONEXCLUDE' [2], but did not find something similar to
> publish_via_partition_root or where partitions are published as
> separate tables.
> What are your thoughts on the above behaviour?
>

Thank You for the details. I will review this behaviour soon and will
let you know my comments. Meanwhile, please find a few comments on
v16-0001:

1)
we do LockSchemaList() everywhere before we call
PublicationDropSchemas() to prevent concurrent schema deletion. Do we
need that in reset flow as well?

2)
+ /* Drop the schemas associated with the publication */
+ schemas = GetPublicationSchemas(pubid);
+ PublicationDropSchemas(pubid, schemas, true);
+
+ /* Get all relations associated with the publication */
+ relids = GetPublicationRelations(pubid, PUBLICATION_PART_ROOT);

We can rename schemas to schemaids similar to relids, as
GetPublicationSchemas return oids.

3)
+ /* Drop the relations associated with the publication */
+ PublicationDropTables(pubform->oid, rels, true);

we can pass 'pubid' here instead of pubform->oid

4)
Shall we modify the comments:
'Drop the relations associated with the publication' to 'Remove the
associated relations from the publication'
'Drop the schemas associated with the publication' to 'Remove the
associated schemas from the publication'

Similar changes can be done in test file's comments as well
--Verify that tables associated with the publication are dropped after
RESET
--Verify that schemas associated with the publication are dropped after RESET

thanks
Shveta


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-07-21 19:33:37
Message-ID: CANhcyEUtYV-9ujtxLasnxN_peT+3LuZjcRx1xUECh1CCmANB8w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 21 Jul 2025 at 12:17, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok.
>
> Some review comments for patch v16-0003.
>
> ======
> Commit message
>
> 1.
> The column "prexcept" of system catalog "pg_publication_rel" is set to
> "true" when publication is created with EXCEPT table or EXCEPT column
> list. If column "prattrs" of system catalog "pg_publication_rel" is also
> set or column "puballtables" of system catalog "pg_publication" is
> "false", it indicates the column list is specified with EXCEPT clause
> and columns in "prattrs" are excluded from being published.
>
> ~
>
> Somehow, this seems to contain too much information, making it a bit
> confusing. Can't you chop this down to something like below?
>
> SUGESTION
> When column "prexcept" of system catalog "pg_publication_rel" is set
> to "true", and column "prattrs" of system catalog "pg_publication_rel"
> is not NULL, that means the publication was created with "EXCEPT
> (column-list)", and the columns in "prattrs" will be excluded from
> being published.
>
Modified the commit message as per suggestion.

> ======
> doc/src/sgml/logical-replication.sgml
>
> 2.
> Generated columns can also be specified in a column list. This allows
> generated columns to be published, regardless of the publication parameter
> <link linkend="sql-createpublication-params-with-publish-generated-columns">
> + <literal>publish_generated_columns</literal></link>. Generated
> columns can be
> + specified in a column list using the <literal>EXCEPT</literal> clause. This
> + excludes the specified generated columns from being published, regardless of
> + the <link linkend="sql-createpublication-params-with-publish-generated-columns">
> + <literal>publish_generated_columns</literal></link> setting. However, for
> + generated columns that are not listed in the <literal>EXCEPT</literal>
> + clause, whether they are published or not still depends on the value of
> + <link linkend="sql-createpublication-params-with-publish-generated-columns">
> <literal>publish_generated_columns</literal></link>. See
> <xref linkend="logical-replication-gencols"/> for details.
> </para>
>
> ~~
>
> For this part:
>
> "Generated columns can be specified in a column list using the
> <literal>EXCEPT</literal> clause. This excludes the specified
> generated columns from being published, regardless of..."
>
> I think the whole paragraph already said "Generated columns can also
> be specified in a column list", so you don't need to repeat it.
> Instead, maybe say something like below.
>
> SUGGESTION
> Specifying generated columns in a column list using the
> <literal>EXCEPT</literal> clause excludes those columns from being
> published, regardless of...
>
> ~~~
>
Modified

> 3.
> - Publication p1
> - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
> -----------+------------+---------+---------+---------+-----------+----------
> - postgres | f | t | t | t | t | f
> + Publication p1
> + Owner | All tables | Inserts | Updates | Deletes | Truncates |
> Generated columns | Via root
> +--------+------------+---------+---------+---------+-----------+-------------------+----------
> + ubuntu | f | t | t | t | t | none
> | f
> Tables:
> "public.t1" (id, a, b, d)
> + "public.t2" EXCEPT (a, d)
> </programlisting></para>
>
>
> I noticed the Owner changed from "postgres" to "ubuntu". Do you think
> it is better to keep this as "postgres" for the example?
I agree that it is better to keep "postgres". I have reverted back to
the use "postgres"..

>
> ======
> doc/src/sgml/ref/create_publication.sgml
>
> 4.
> The tables added to a publication that publishes UPDATE and/or DELETE
> operations must have REPLICA IDENTITY defined. Otherwise those
> operations will be disallowed on those tables.
>
> In order for UPDATE or DELETE operations to work, all the REPLICA
> IDENTITY columns must be published. So, any column list must name all
> REPLICA IDENTITY columns, and any EXCEPT column list must not name any
> REPLICA IDENTITY columns.
>
> A row filter expression (i.e., the WHERE clause) must contain only
> columns that are covered by the REPLICA IDENTITY, in order for UPDATE
> and DELETE operations to be published. For publication of INSERT
> operations, any column may be used in the WHERE expression. The row
> filter allows simple expressions that don't have user-defined
> functions, user-defined operators, user-defined types, user-defined
> collations, non-immutable built-in functions, or references to system
> columns.
>
> The generated columns that are part of the column list specified with
> the EXCEPT clause are not published, regardless of the
> publish_generated_columns option. However, generated columns that are
> not part of the column list specified with the EXCEPT clause are
> published according to the value of the publish_generated_columns
> option. See Section 29.6 for details.
>
> The generated columns that are part of REPLICA IDENTITY must be
> published explicitly either by listing them in the column list or by
> enabling the publish_generated_columns option, in order for UPDATE and
> DELETE operations to be published.
>
> ~~
>
> Notice all those 5 paragraphs (above) are talking about REPLICA
> IDENTITY, except the 4th paragraph. Maybe the 4th paragraph should be
> moved to last, to keep all the REPLICA IDENTITY stuff together.
>
Fixed

> ======
> src/backend/catalog/pg_publication.c
>
> 5. pub_form_cols_map
>
> * Returns a bitmap representing the columns of the specified table.
> *
> * Generated columns are included if include_gencols_type is
> - * PUBLISH_GENCOLS_STORED.
> + * PUBLISH_GENCOLS_STORED. Columns that are in the exceptcols are excluded from
> + * the column list.
> */
> Bitmapset *
> -pub_form_cols_map(Relation relation, PublishGencolsType include_gencols_type)
> +pub_form_cols_map(Relation relation, PublishGencolsType include_gencols_type,
> + Bitmapset *except_cols)
>
> Forgot to add the underscore in the function comment.
>
> /exceptcols/except_cols/
>
Fixed

> ~~~
>
> 6. pg_get_publication_tables
>
> +
> + /*
> + * We fetch pubtuple if publication is not FOR ALL TABLES and not
> + * FOR TABLES IN SCHEMA. So if prexcept is true, it indicates that
> + * prattrs contains columns to be excluded for replication.
> + */
> + exceptDatum = SysCacheGetAttr(PUBLICATIONRELMAP, pubtuple,
> + Anum_pg_publication_rel_prexcept,
> + &isnull);
> +
> + if (!isnull && DatumGetBool(exceptDatum) && !nulls[2])
> + except_columns = pub_collist_to_bitmapset(NULL, values[2], NULL);
>
> But, you cannot have EXCEPT for null column list, so shouldn't the
> !nulls[2] check be done to also guard the SysCacheGetAttr call?
>
Fixed

> ======
> src/backend/parser/gram.y
>
> 7.
>
> Shlok wrote [1-reply #11]
> The main reason I used a separate 'opt_except_column_list' is because
> 'opt_column_list' can also be NULL. But the column list specified with
> EXCEPT not be NULL. So, 'opt_except_column_list' is defined such that
> it cannot be null.
>
> ~
>
> Yeah, but IMO that leads to excessive duplicated code. I think the
> code can perhaps be a lot simpler if the grammar is written more like
> the synopsis:
>
> e.g. TABLE name opt_EXCEPT opt_column_list
>
> where - opt_EXCEPT is null, and opt_column_list is null... means no col list
> where - opt_EXCEPT is null, and opt_column_list is not null... means
> normal col list
> where - opt_EXCEPT is not null, and opt_column_list not null... means
> EXCEPT col list
> where - opt_EXCEPT is not null, and opt_column_list null... SYNTAX ERROR
>
> So code it something like this (just adding opt_EXCEPT to the existing
> productions)
>
> %type <boolean> opt_ordinality opt_without_overlaps opt_EXCEPT
> ...
> opt_EXCEPT:
> EXCEPT { $$ = true; }
> | /*EMPTY*/ { $$ = false; }
> ;
> ...
> TABLE relation_expr opt_EXCEPT opt_column_list OptWhereClause
> {
> $$ = makeNode(PublicationObjSpec);
> $$->pubobjtype = PUBLICATIONOBJ_TABLE;
> $$->pubtable = makeNode(PublicationTable);
> $$->pubtable->relation = $2;
> $$->pubtable->except = $3;
> $$->pubtable->columns = $4;
> if ($3 && !$4)
> ereport(ERROR,
> (errcode(ERRCODE_SYNTAX_ERROR),
> errmsg("EXCEPT without column list"),
> parser_errposition(@3)));
> $$->pubtable->whereClause = $5;
> $$->location = @1;
> }
>
> etc.
>
I have modified it. I have created a function 'check_except_collist'
to throw error, to avoid duplication code for error message.

> ======
> src/bin/psql/describe.c
>
> 8.
> if (!PQgetisnull(res, i, 3))
> + {
> + if (!PQgetisnull(res, i, 4) && strcmp(PQgetvalue(res, i, 4), "t") == 0)
> + appendPQExpBuffer(buf, " EXCEPT");
> appendPQExpBuffer(buf, " (%s)", PQgetvalue(res, i, 3));
> + }
>
> This growing list of columns makes it hard to understand this function
> without looking back at the caller all the time. Maybe you can add a
> function comment that at least explains what those attributes 1,2,3,4
> represent?
>
Added a comment

> ======
> src/bin/psql/tab-complete.in.c
>
> 9.
> + else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|SET",
> "TABLE", MatchAny))
> + COMPLETE_WITH("EXCEPT");
>
> Since it is not allowed to have an EXCEPT with no column list,
> shouldn't this say "EXCEPT ("?
>
Fixed

> ~~~
>
> 10.
> else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE",
> MatchAny) && !ends_with(prev_wd, ','))
> - COMPLETE_WITH("WHERE (", "WITH (");
> + COMPLETE_WITH("EXCEPT", "WHERE (", "WITH (");
>
> Ditto. Since it is not allowed to have an EXCEPT with no column list,
> shouldn't this say "EXCEPT ("?
>
Fixed

>
> ======
> src/test/regress/expected/publication.out
>
> 11.
> +-- Verify that EXCEPT col-list cannot contain RI cols (when using INDEX)
> +CREATE UNIQUE INDEX pub_test_except1_ac_idx ON pub_test_except1 (a, c);
> +ALTER TABLE pub_test_except1 REPLICA IDENTITY USING INDEX
> pub_test_except1_a_idx;
> +ERROR: index "pub_test_except1_a_idx" for table "pub_test_except1"
> does not exist
> +UPDATE pub_test_except1 SET a = 3 WHERE a = 1;
> +ERROR: cannot update table "pub_test_except1"
> +DETAIL: Column list used by the publication does not cover the
> replica identity.
> +DROP INDEX pub_test_except1_ac_idx;
>
>
> What's happening here? I'm not sure these are the kind of errors you
> were trying to cause.
>
Yes, it is not the error I was trying to cause. I have modified it.

> ======
> src/test/regress/sql/publication.sql
>
> 12.
> +-- Verify that EXCEPT col-list cannot contain RI cols (when using RI FULL)
> +ALTER TABLE pub_test_except1 REPLICA IDENTITY FULL;
> +UPDATE pub_test_except1 SET a = 3 WHERE a = 1;
>
>
> SUGGESTION. Change that comment to:
> Verify fails - EXCEPT col-list cannot...
>
Fixed

> ~~~
>
> 13.
> +-- Verify that EXCEPT col-list cannot contain RI cols (when using INDEX)
> +CREATE UNIQUE INDEX pub_test_except1_ac_idx ON pub_test_except1 (a, c);
> +ALTER TABLE pub_test_except1 REPLICA IDENTITY USING INDEX
> pub_test_except1_a_idx;
> +UPDATE pub_test_except1 SET a = 3 WHERE a = 1;
> +DROP INDEX pub_test_except1_ac_idx;
>
> SUGGESTION. Change that comment to:
> Verify fails - EXCEPT col-list cannot...
>
Fixed

> ~~~
>
> 14.
> +-- Verify that so long as no clash between RI cols and the EXCEPT
> +CREATE UNIQUE INDEX pub_test_except1_a_idx ON pub_test_except1 (a);
> +ALTER TABLE pub_test_except1 REPLICA IDENTITY USING INDEX
> pub_test_except1_a_idx;
> +UPDATE pub_test_except1 SET a = 3 WHERE a = 1;
> +
>
> That comment doesn't make sense. Missing words?
>
Fixed

> ======
> .../t/036_rep_changes_except_table.pl
>
> 15.
> (I haven't reviewed this file in detail yet, but here is a general comment)
>
> I know this patch currently lives in the same thread as all the EXCEPT
> TABLE stuff, but that seems just happenstance to me. IMO, this is a
> separate enhancement that just shares the keyword EXCEPT. So, I felt
> it should have quite separate tests too.
>
> e.g. How about: 037_rep_changes_except_collist.pl
>
Modified

> ======
> [1] https://www.postgresql.org/message-id/CANhcyEW2LK4diNeCG862DE40yQoV3VAgf59kXUq2TuR8fnw5vQ%40mail.gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v17-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 20.4 KB
v17-0003-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 64.4 KB
v17-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 71.8 KB

From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-07-21 19:35:40
Message-ID: CANhcyEXYrzFrGqzw+=qjuC0RFMDaoX+b1SZV4yCJNG6KWxodPQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 21 Jul 2025 at 16:22, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Sat, Jul 19, 2025 at 4:17 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > On Mon, 30 Jun 2025 at 16:25, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> > >
> > > Few more comments on 002:
> > >
> > > 5)
> > > +GetAllTablesPublicationRelations(Oid pubid, bool pubviaroot)
> > > {
> > >
> > > + List *exceptlist;
> > > +
> > > + exceptlist = GetPublicationRelations(pubid, PUBLICATION_PART_ALL);
> > >
> > >
> > > a) Here, we are assuming that the list provided by
> > > GetPublicationRelations() will be except-tables list only, but there
> > > is no validation of that.
> > > b) We are using GetPublicationRelations() to get the relations which
> > > are excluded from the publication. The name of function and comments
> > > atop function are not in alignment with this usage.
> > >
> > > Suggestion:
> > > We can have a new GetPublicationExcludeRelations() function for the
> > > concerned usage. The existing logic of GetPublicationRelations() can
> > > be shifted to a new internal-logic function which will accept a
> > > 'except-flag' as well. Both GetPublicationRelations() and
> > > GetPublicationExcludeRelations() can call that new function by passing
> > > 'except-flag' as false and true respectively. The new internal
> > > function will validate 'prexcept' against that except-flag passed and
> > > will return the results.
> > >
> > I have made the above change.
> >
> >
> > > 6)
> > > Before your patch002, GetTopMostAncestorInPublication() was checking
> > > pg_publication_rel and pg_publication_namespace to find out if the
> > > table in the ancestor-list is part of a given particular. Both
> > > pg_publication_rel and pg_publication_namespace did not have the entry
> > > "for all tables" publications. That means
> > > GetTopMostAncestorInPublication() was originally not checking whether
> > > the given puboid is an "for all tables" publication to see if a rel
> > > belongs to that particular pub or not. I
> > >
> > > But now with the current change, we do check if pub is all-tables pub,
> > > if so, return relid and mark ancestor_level (provided table is not
> > > part of the except list). IIUC, the result in 2 cases may be
> > > different. Is that the intention? Let me know if my understanding is
> > > wrong.
> > >
> > This is intentional, in function get_rel_sync_entry, we are setting
> > pub_relid to the topmost published ancestor. In HEAD we are directly
> > setting using:
> > /*
> > * If this is a FOR ALL TABLES publication, pick the partition
> > * root and set the ancestor level accordingly.
> > */
> > if (pub->alltables)
> > {
> > publish = true;
> > if (pub->pubviaroot && am_partition)
> > {
> > List *ancestors = get_partition_ancestors(relid);
> >
> > pub_relid = llast_oid(ancestors);
> > ancestor_level = list_length(ancestors);
> > }
> > }
> > In HEAD, we can directly use 'llast_oid(ancestors)' to get the topmost
> > ancestor for case of FOR ALL TABLES.
> > But with this proposal. This change will no longer be valid as the
> > 'llast_oid(ancestors)' may be excluded in the publication. So, to
> > handle this change was made in GetTopMostAncestorInPublication.
> >
> >
> > Also, during testing with the partitioned table and
> > publish_via_partition_root the behaviour of the current patch is as
> > below:
> > For example we have a partitioned table t1. It has partitions part1
> > and part2. Now consider the following cases:
> > 1. with publish_via_partition_root = true
> > I. If we create publication on all tables with EXCEPT t1, no data
> > for t1, part1 or part2 is replicated.
> > II. If we create publication on all tables with EXCEPT part1,
> > data for all tables t1, part1 and part2 is replicated.
> > 2. with publish_via_partition_root = false
> > I. If we create publication on all tables with EXCEPT t1, no data
> > for t1, part1 or part2 is replicated.
> > II. If we create publication on all tables with EXCEPT part1,
> > data for part1 is not replicated
> >
> > Is this behaviour fine?
> > I checked for other databases such as MySQL, SQL Server. In that we do
> > not have such cases as either we replicate the whole partitioned table
> > or we not replicated at all. We do not have partition level control.
> > For Oracle, I found that we can include or exclude partitions using
> > 'PARTITIONEXCLUDE' [2], but did not find something similar to
> > publish_via_partition_root or where partitions are published as
> > separate tables.
> > What are your thoughts on the above behaviour?
> >
>
> Thank You for the details. I will review this behaviour soon and will
> let you know my comments. Meanwhile, please find a few comments on
> v16-0001:
>
> 1)
> we do LockSchemaList() everywhere before we call
> PublicationDropSchemas() to prevent concurrent schema deletion. Do we
> need that in reset flow as well?
Added

>
> 2)
> + /* Drop the schemas associated with the publication */
> + schemas = GetPublicationSchemas(pubid);
> + PublicationDropSchemas(pubid, schemas, true);
> +
> + /* Get all relations associated with the publication */
> + relids = GetPublicationRelations(pubid, PUBLICATION_PART_ROOT);
>
> We can rename schemas to schemaids similar to relids, as
> GetPublicationSchemas return oids.
>
Fixed

> 3)
> + /* Drop the relations associated with the publication */
> + PublicationDropTables(pubform->oid, rels, true);
>
> we can pass 'pubid' here instead of pubform->oid
>
Modified

> 4)
> Shall we modify the comments:
> 'Drop the relations associated with the publication' to 'Remove the
> associated relations from the publication'
> 'Drop the schemas associated with the publication' to 'Remove the
> associated schemas from the publication'
>
> Similar changes can be done in test file's comments as well
> --Verify that tables associated with the publication are dropped after
> RESET
> --Verify that schemas associated with the publication are dropped after RESET
>
Fixed

I have made the changes in the latest v17 patch [1].
[1]: https://www.postgresql.org/message-id/CANhcyEUtYV-9ujtxLasnxN_peT%2B3LuZjcRx1xUECh1CCmANB8w%40mail.gmail.com

Thanks,
Shlok Kyal


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-07-22 01:58:29
Message-ID: CAHut+PuviFA6C7qps=+kDYfe3P99as8NCjbR=SYxoi0o96ipoA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok,

Some review comments for patch v17-0003. I also checked the TAP test this time.

======
doc/src/sgml/logical-replication.sgml

1.
+ <literal>publish_generated_columns</literal></link>. Specifying generated
+ columns in a column list using the <literal>EXCEPT</literal> clause excludes
+ the specified generated columns from being published, regardless of the
+ <link linkend="sql-createpublication-params-with-publish-generated-columns">
+ <literal>publish_generated_columns</literal></link> setting. However, for

I think that is not quite the same wording I had previously suggested.
It sounds a bit odd/redundant saying "Specifying" and "specified" in
the same sentence.

======
src/backend/parser/gram.y

2. check_except_collist

I'm wondering if this checking should be done within the existing
preprocess_pubobj_list() function, alongside all the other ERROR
checking. Care needs to be taken to make sure the pubtable->except is
referring to an EXCEPT (col-list), instead of the other kind of EXCEPT
tables, but in general I think it is better to keep all the
publication combinations checking errors like this in one place.

======
src/bin/psql/describe.c

3. addFooterToPublicationDesc

- appendPQExpBuffer(&buf, " (%s)",
- PQgetvalue(result, i, 2));
+ {
+ if (!PQgetisnull(result, i, 3) &&
+ strcmp(PQgetvalue(result, i, 3), "t") == 0)
+ appendPQExpBuffer(&buf, " EXCEPT (%s)",
+ PQgetvalue(result, i, 2));
+ else
+ appendPQExpBuffer(&buf, " (%s)",
+ PQgetvalue(result, i, 2));
+ }

Do you really need to check !PQgetisnull(result, i, 3) here? (e.g.
The comment does not say that this attribute can be NULL)

======
.../t/037_rep_changes_except_collist.pl

4.
+# Copyright (c) 2021-2025, PostgreSQL Global Development Group
+
+# Logical replication tests for except table publications

Comment is wrong. These tests are for EXCEPT (column-list)

~~~

5.
+# Test for except column publications
+# Initial setup
+$node_publisher->safe_psql('postgres', "CREATE SCHEMA sch1");
+$node_publisher->safe_psql('postgres',
+ "CREATE TABLE tab2 (a int, b int NOT NULL, c int)");
+$node_publisher->safe_psql('postgres',
+ "CREATE TABLE sch1.tab2 (a int, b int, c int)");
+$node_publisher->safe_psql('postgres',
+ "CREATE TABLE tab3 (a int, b int, c int)");
+$node_publisher->safe_psql('postgres',
+ "CREATE TABLE tab4 (a int, b int GENERATED ALWAYS AS (a * 2) STORED,
c int GENERATED ALWAYS AS (a * 3) STORED)"
+);
+$node_publisher->safe_psql('postgres',
+ "CREATE TABLE tab5 (a int, b int GENERATED ALWAYS AS (a * 2) STORED,
c int GENERATED ALWAYS AS (a * 3) STORED)"
+);
+$node_publisher->safe_psql('postgres', "INSERT INTO tab2 VALUES (1, 2, 3)");
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO sch1.tab2 VALUES (1, 2, 3)");
+$node_publisher->safe_psql('postgres',
+ "CREATE PUBLICATION tap_pub_col FOR TABLE tab2 EXCEPT (a), sch1.tab2
EXCEPT (b, c)"
+);

5a.
I think you don't need to say "Test for except column publications",
because that is the purpose of thie entire file.

~

5b.
You can combine multiple of these safe_psql calls together

~

5c.
It might help make tests easier to read if you named those generated
columns 'b', 'c' cols as 'bgen', 'cgen' instead.

~

5d.
The table names are strange, because why does it start at tab2 when
there is not a tab1?

~~~

6.
+$node_subscriber->safe_psql('postgres', "CREATE SCHEMA sch1");
+$node_subscriber->safe_psql('postgres',
+ "CREATE TABLE tab2 (a int, b int NOT NULL, c int)");
+$node_subscriber->safe_psql('postgres',
+ "CREATE TABLE sch1.tab2 (a int, b int, c int)");
+$node_subscriber->safe_psql('postgres',
+ "CREATE TABLE tab3 (a int, b int, c int)");
+$node_subscriber->safe_psql('postgres',
+ "CREATE TABLE tab4 (a int, b int, c int)");
+$node_subscriber->safe_psql('postgres',
+ "CREATE TABLE tab5 (a int, b int, c int)");

You can combine multiple of these safe_psql calls together

~~~

7.
+# Test initial sync
+my $result = $node_subscriber->safe_psql('postgres', "SELECT * FROM tab2");
+is($result, qq(|2|3),
+ 'check that initial sync for except column publication');

The message seems strange. Do you mean "check initial sync for an
'EXCEPT (column-list)' publication"

NOTE: There are many other messages where you wrote "for except column
publication" but I think maybe all of those can be improved a bit like
above.

~~~

8.
+$node_publisher->safe_psql('postgres', "INSERT INTO tab2 VALUES (4, 5, 6)");
+$node_publisher->safe_psql('postgres',
+ "INSERT INTO sch1.tab2 VALUES (4, 5, 6)");
+$node_publisher->wait_for_catchup('tap_sub_col');

8a.
You can combine multiple of these safe_psql calls together.

NOTE: I won't keep repeating this review comment but I think maybe
there are lots more places where the safe_psql can all be combined to
expected multiple statements.

~

8b.
I felt all those commands should be under the "Test incremental
changes" comment.

~~~

9.
+is($result, qq(1||3), 'check alter publication with EXCEPT');

Maybe that should've said with 'EXCEPT (column-list)'

~~~

10.
+# Test for publication created with publish_generated_columns as true on table
+# with generated columns and column list specified with EXCEPT
+$node_publisher->safe_psql('postgres', "INSERT INTO tab4 VALUES (1)");
+$node_publisher->safe_psql('postgres',
+ "ALTER PUBLICATION tap_pub_col SET (publish_generated_columns)");
+$node_publisher->safe_psql('postgres',
+ "ALTER PUBLICATION tap_pub_col SET TABLE tab4 EXCEPT(b)");
+$node_subscriber->safe_psql('postgres',
+ "ALTER SUBSCRIPTION tap_sub_col REFRESH PUBLICATION");
+$node_subscriber->wait_for_subscription_sync($node_publisher, 'tap_sub_col');

10a.
I felt the test comments for both those generated columns parameter
test should give more explanation to say what is the expected result
and why.

~

10b.
How does "ALTER PUBLICATION tap_pub_col SET
(publish_generated_columns)" even work? I thought the
"pubish_generated_columns" is an enum but you did not specify any enum
value here (???)

~~~

11.
+ 'check publication(publish_generated_columns as false) with
generated columns and EXCEPT'

Hmm. I thought there is no such thing as "publish_generated_columns as
false", and also the EXCEPT should say 'EXCEPT (column-list)'

~~~

12.
I wonder if there should be another boundary condition test case as follows:
- have some table with cols a,b,c.
- create a publication 'EXCEPT (a,b,c)', so you don't publish anything at all.
- then ALTER the TABLE to add a column 'd'.
- now the publication should publish only 'd'.

======

Kind Regards,
Peter Smith.
Fujitsu Australia


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2025-07-22 08:59:45
Message-ID: CAJpy0uBE65YAkAQ+q75b3WZteAZszeRgsQifTsJTb0JDsNQTSw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, Jul 19, 2025 at 4:17 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> On Mon, 30 Jun 2025 at 16:25, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > Few more comments on 002:
> >
> > 5)
> > +GetAllTablesPublicationRelations(Oid pubid, bool pubviaroot)
> > {
> >
> > + List *exceptlist;
> > +
> > + exceptlist = GetPublicationRelations(pubid, PUBLICATION_PART_ALL);
> >
> >
> > a) Here, we are assuming that the list provided by
> > GetPublicationRelations() will be except-tables list only, but there
> > is no validation of that.
> > b) We are using GetPublicationRelations() to get the relations which
> > are excluded from the publication. The name of function and comments
> > atop function are not in alignment with this usage.
> >
> > Suggestion:
> > We can have a new GetPublicationExcludeRelations() function for the
> > concerned usage. The existing logic of GetPublicationRelations() can
> > be shifted to a new internal-logic function which will accept a
> > 'except-flag' as well. Both GetPublicationRelations() and
> > GetPublicationExcludeRelations() can call that new function by passing
> > 'except-flag' as false and true respectively. The new internal
> > function will validate 'prexcept' against that except-flag passed and
> > will return the results.
> >
> I have made the above change.

Thank You for the changes.

1)
But on rethinking, shall we make GetPublicationRelations() similar to :

/* Gets list of publication oids for a relation that matches the except_flag */
GetRelationPublications(Oid relid, bool except_flag)

i.e. we can have a single function GetPublicationRelations() taking
except_flag and comment can say: 'Gets list of relation oids for a
publication that matches the except_flag.'

We can get rid of GetPubIncludedOrExcludedRels() and
GetPublicationExcludeRelations().

Thoughts?

2)
we can rename except_table to except_flag to be consistent with
GetRelationPublications()

3)
+ if ((except_table && pubrel->prexcept) || !except_table)
+ result = GetPubPartitionOptionRelations(result, pub_partopt,
+ pubrel->prrelid);

3a)
In the case of '!except_table', we are not matching it with
'pubrel->prexcept', is that intentional?

3 b)
Shall we simplify this similar to the changes in GetRelationPublications() i.e.
if (except_table/flag == pubrel->prexcept)
result = GetPubPartitionOptionRelations(...)

>
> > 6)
> > Before your patch002, GetTopMostAncestorInPublication() was checking
> > pg_publication_rel and pg_publication_namespace to find out if the
> > table in the ancestor-list is part of a given particular. Both
> > pg_publication_rel and pg_publication_namespace did not have the entry
> > "for all tables" publications. That means
> > GetTopMostAncestorInPublication() was originally not checking whether
> > the given puboid is an "for all tables" publication to see if a rel
> > belongs to that particular pub or not. I
> >
> > But now with the current change, we do check if pub is all-tables pub,
> > if so, return relid and mark ancestor_level (provided table is not
> > part of the except list). IIUC, the result in 2 cases may be
> > different. Is that the intention? Let me know if my understanding is
> > wrong.
> >
> This is intentional, in function get_rel_sync_entry, we are setting
> pub_relid to the topmost published ancestor. In HEAD we are directly
> setting using:
> /*
> * If this is a FOR ALL TABLES publication, pick the partition
> * root and set the ancestor level accordingly.
> */
> if (pub->alltables)
> {
> publish = true;
> if (pub->pubviaroot && am_partition)
> {
> List *ancestors = get_partition_ancestors(relid);
>
> pub_relid = llast_oid(ancestors);
> ancestor_level = list_length(ancestors);
> }
> }
> In HEAD, we can directly use 'llast_oid(ancestors)' to get the topmost
> ancestor for case of FOR ALL TABLES.
> But with this proposal. This change will no longer be valid as the
> 'llast_oid(ancestors)' may be excluded in the publication. So, to
> handle this change was made in GetTopMostAncestorInPublication.
>
>
> Also, during testing with the partitioned table and
> publish_via_partition_root the behaviour of the current patch is as
> below:
> For example we have a partitioned table t1. It has partitions part1
> and part2. Now consider the following cases:
> 1. with publish_via_partition_root = true
> I. If we create publication on all tables with EXCEPT t1, no data
> for t1, part1 or part2 is replicated.

Okay. Agreed.

> II. If we create publication on all tables with EXCEPT part1,
> data for all tables t1, part1 and part2 is replicated.

Okay. Is this because part1 changes are replicated through t1 and
since t1 changes are not restricted, part1 changes will also not be
restricted? In other words, part1 was never published directly in the
first place and thus 'EXCEPT part1' has no meaning when
'publish_via_partition_root' = true? IMO, it is in alignment with the
'publish_via_partition_root' definition but it might not be that
intuitive for users. So shall we emit a WARNING:

WARNING: Partition "part1" is excluded, but publish_via_partition_root
= true, so this will have no effect.
Thoughts?

> 2. with publish_via_partition_root = false
> I. If we create publication on all tables with EXCEPT t1, no data
> for t1, part1 or part2 is replicated.

I think we shall still publish partitions here. Since
publish_via_partition_root is false, part1 and part2 are published
individually and thus shall we allow publishing of part1 and part 2
here? Thoughts?

> II. If we create publication on all tables with EXCEPT part1,
> data for part1 is not replicated
>

Agreed.

thanks
Shveta


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2025-07-22 10:27:34
Message-ID: CAJpy0uCjAvaGn5y_48MR=DHahoB36VpqK6RkMryLKYBU+YHE5g@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Shlok, I was trying to validate the interaction of
'publish_via_partition_root' with 'EXCEPT". Found some unexpected
behaviour, can you please review:

Pub:
---------
CREATE TABLE tab_root (range_col int,i int,j int) PARTITION BY RANGE
(range_col);
CREATE TABLE tab_part_1 PARTITION OF tab_root FOR VALUES FROM (1) to (1000);
CREATE TABLE tab_part_2 PARTITION OF tab_root FOR VALUES FROM (1000) to (2000);
create publication pub2 for all tables except tab_part_2 WITH
(publish_via_partition_root=true);

Sub (tables without partition):
--------
CREATE TABLE tab_root (range_col int,i int,j int);
CREATE TABLE tab_part_1(range_col int,i int,j int);
CREATE TABLE tab_part_2(range_col int,i int,j int);
create subscription sub2 connection '...' publication pub2;

Pub:
--------
insert into tab_part_2 values(1001,1,1);

On Sub, the above row is replicated as expected in tab_root due to
publish_via_partition_root=true on pub.

Now on Pub:
--------
alter publication pub2 set (publish_via_partition_root=false);
insert into tab_part_2 values(1002,2,2);

Now with publish_via_partition_root=false and 'except tab_part_2', the
above row is correctly ignored and not replicated on sub.

But when I try this:
insert into tab_part_1 values(1,1,1);
insert into tab_root values(5,5,5);

Expectation was that the above rows are replicated but that is not the
case. Can you please review? Please let me know if my understanding is
wrong.

thanks
Shveta


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2025-07-23 04:38:43
Message-ID: CAJpy0uCuNJLRLuWfU1EEwaEUjpNVVwo2+k3rP9=Uv9Z-BOLm0Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

I further tested inherited tables flow as well wrt ONLY and EXCEPT, it
works well. But while reading docs for the saem, I have few concerns.

1)
While explaining ONLY for EXCEPT, create-publication doc says this

+ This does not apply to a partitioned table, however. The partitions of
+ a partitioned table are always implicitly considered part of the
+ publication, so they are never explicitly excluded from the publication.

I do not understand the last line: "so they are never explicitly
excluded from the publication" . But we can explicitly exclude them
using EXCEPT <partition_name>. Do you mean to say something else here?

2)
alter-publication doc says (in context of EXCEPT):

"If ONLY is specified before the table name, only that table is
affected. If ONLY is not specified, the table and all its descendant
tables (if any) are affected. Optionally, * can be specified after
the table name to explicitly indicate that descendant tables are
affected."

But it does not mention anything for partitions. I think we shall
mention here as well that this does not apply to a partitioned table.
(I tested ONLY and EXCEPT for partition-root. UNLIKE inherited tables,
ONLY has no impact on partitioned tables.)

3)
Shall we explain the relation of 'publish_via_partition_root' with
EXCEPT briefly in docs(once we conclude that design)?

Please note that I have performed all the tests (mentioned here and in
previous emails) on patch001 and patch002. patch003 is not applied in
these tests.

thanks
Shveta


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-08-03 16:07:00
Message-ID: CANhcyEXkeg3sjkS3DS9yU1ckz4ozUBNZ+RmrWaRNSSVCR8RquA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, 22 Jul 2025 at 07:28, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok,
>
> Some review comments for patch v17-0003. I also checked the TAP test this time.
>
> ======
> doc/src/sgml/logical-replication.sgml
>
> 1.
> + <literal>publish_generated_columns</literal></link>. Specifying generated
> + columns in a column list using the <literal>EXCEPT</literal> clause excludes
> + the specified generated columns from being published, regardless of the
> + <link linkend="sql-createpublication-params-with-publish-generated-columns">
> + <literal>publish_generated_columns</literal></link> setting. However, for
>
> I think that is not quite the same wording I had previously suggested.
> It sounds a bit odd/redundant saying "Specifying" and "specified" in
> the same sentence.
>
> ======
> src/backend/parser/gram.y
>
> 2. check_except_collist
>
> I'm wondering if this checking should be done within the existing
> preprocess_pubobj_list() function, alongside all the other ERROR
> checking. Care needs to be taken to make sure the pubtable->except is
> referring to an EXCEPT (col-list), instead of the other kind of EXCEPT
> tables, but in general I think it is better to keep all the
> publication combinations checking errors like this in one place.
>
Added the check in preprocess_pubobj_list(). I checked the syntaxes
and found that this function is not called for "FOR ALL TABLES" cases
and EXCEPT tables can only be used with "FOR ALL TABLES" publications.
So, I think handling for "EXCEPT tables" will not be required in the
function preprocess_pubobj_list()

>
> ======
> src/bin/psql/describe.c
>
> 3. addFooterToPublicationDesc
>
> - appendPQExpBuffer(&buf, " (%s)",
> - PQgetvalue(result, i, 2));
> + {
> + if (!PQgetisnull(result, i, 3) &&
> + strcmp(PQgetvalue(result, i, 3), "t") == 0)
> + appendPQExpBuffer(&buf, " EXCEPT (%s)",
> + PQgetvalue(result, i, 2));
> + else
> + appendPQExpBuffer(&buf, " (%s)",
> + PQgetvalue(result, i, 2));
> + }
>
> Do you really need to check !PQgetisnull(result, i, 3) here? (e.g.
> The comment does not say that this attribute can be NULL)
>
> ======
> .../t/037_rep_changes_except_collist.pl
>
> 4.
> +# Copyright (c) 2021-2025, PostgreSQL Global Development Group
> +
> +# Logical replication tests for except table publications
>
> Comment is wrong. These tests are for EXCEPT (column-list)
>
> ~~~
>
> 5.
> +# Test for except column publications
> +# Initial setup
> +$node_publisher->safe_psql('postgres', "CREATE SCHEMA sch1");
> +$node_publisher->safe_psql('postgres',
> + "CREATE TABLE tab2 (a int, b int NOT NULL, c int)");
> +$node_publisher->safe_psql('postgres',
> + "CREATE TABLE sch1.tab2 (a int, b int, c int)");
> +$node_publisher->safe_psql('postgres',
> + "CREATE TABLE tab3 (a int, b int, c int)");
> +$node_publisher->safe_psql('postgres',
> + "CREATE TABLE tab4 (a int, b int GENERATED ALWAYS AS (a * 2) STORED,
> c int GENERATED ALWAYS AS (a * 3) STORED)"
> +);
> +$node_publisher->safe_psql('postgres',
> + "CREATE TABLE tab5 (a int, b int GENERATED ALWAYS AS (a * 2) STORED,
> c int GENERATED ALWAYS AS (a * 3) STORED)"
> +);
> +$node_publisher->safe_psql('postgres', "INSERT INTO tab2 VALUES (1, 2, 3)");
> +$node_publisher->safe_psql('postgres',
> + "INSERT INTO sch1.tab2 VALUES (1, 2, 3)");
> +$node_publisher->safe_psql('postgres',
> + "CREATE PUBLICATION tap_pub_col FOR TABLE tab2 EXCEPT (a), sch1.tab2
> EXCEPT (b, c)"
> +);
>
> 5a.
> I think you don't need to say "Test for except column publications",
> because that is the purpose of thie entire file.
>
> ~
>
> 5b.
> You can combine multiple of these safe_psql calls together
>
> ~
>
> 5c.
> It might help make tests easier to read if you named those generated
> columns 'b', 'c' cols as 'bgen', 'cgen' instead.
>
> ~
> 5d.
> The table names are strange, because why does it start at tab2 when
> there is not a tab1?
> ~~~
>
> 6.
> +$node_subscriber->safe_psql('postgres', "CREATE SCHEMA sch1");
> +$node_subscriber->safe_psql('postgres',
> + "CREATE TABLE tab2 (a int, b int NOT NULL, c int)");
> +$node_subscriber->safe_psql('postgres',
> + "CREATE TABLE sch1.tab2 (a int, b int, c int)");
> +$node_subscriber->safe_psql('postgres',
> + "CREATE TABLE tab3 (a int, b int, c int)");
> +$node_subscriber->safe_psql('postgres',
> + "CREATE TABLE tab4 (a int, b int, c int)");
> +$node_subscriber->safe_psql('postgres',
> + "CREATE TABLE tab5 (a int, b int, c int)");
>
> You can combine multiple of these safe_psql calls together
>
> ~~~
>
> 7.
> +# Test initial sync
> +my $result = $node_subscriber->safe_psql('postgres', "SELECT * FROM tab2");
> +is($result, qq(|2|3),
> + 'check that initial sync for except column publication');
>
> The message seems strange. Do you mean "check initial sync for an
> 'EXCEPT (column-list)' publication"
>
> NOTE: There are many other messages where you wrote "for except column
> publication" but I think maybe all of those can be improved a bit like
> above.
>
> ~~~
>
> 8.
> +$node_publisher->safe_psql('postgres', "INSERT INTO tab2 VALUES (4, 5, 6)");
> +$node_publisher->safe_psql('postgres',
> + "INSERT INTO sch1.tab2 VALUES (4, 5, 6)");
> +$node_publisher->wait_for_catchup('tap_sub_col');
>
> 8a.
> You can combine multiple of these safe_psql calls together.
>
> NOTE: I won't keep repeating this review comment but I think maybe
> there are lots more places where the safe_psql can all be combined to
> expected multiple statements.
>
> ~
>
> 8b.
> I felt all those commands should be under the "Test incremental
> changes" comment.
>
> ~~~
>
> 9.
> +is($result, qq(1||3), 'check alter publication with EXCEPT');
>
> Maybe that should've said with 'EXCEPT (column-list)'
>
> ~~~
>
> 10.
> +# Test for publication created with publish_generated_columns as true on table
> +# with generated columns and column list specified with EXCEPT
> +$node_publisher->safe_psql('postgres', "INSERT INTO tab4 VALUES (1)");
> +$node_publisher->safe_psql('postgres',
> + "ALTER PUBLICATION tap_pub_col SET (publish_generated_columns)");
> +$node_publisher->safe_psql('postgres',
> + "ALTER PUBLICATION tap_pub_col SET TABLE tab4 EXCEPT(b)");
> +$node_subscriber->safe_psql('postgres',
> + "ALTER SUBSCRIPTION tap_sub_col REFRESH PUBLICATION");
> +$node_subscriber->wait_for_subscription_sync($node_publisher, 'tap_sub_col');
>
> 10a.
> I felt the test comments for both those generated columns parameter
> test should give more explanation to say what is the expected result
> and why.
>
> ~
>
> 10b.
> How does "ALTER PUBLICATION tap_pub_col SET
> (publish_generated_columns)" even work? I thought the
> "pubish_generated_columns" is an enum but you did not specify any enum
> value here (???)
>
> ~~~
Yes, it works. It works equivalent to publish_generated_columns = stored.
Eg:
postgres=# CREATE PUBLICATION pub1 FOR TABLE t1 with
(publish_generated_columns);
CREATE PUBLICATION
postgres=# select * from pg_publication;
oid | pubname | pubowner | puballtables | pubinsert | pubupdate |
pubdelete | pubtruncate | pubviaroot | pubgencols
-------+---------+----------+--------------+-----------+-----------+-----------+-------------+------------+------------
16395 | pub1 | 10 | f | t | t | t
| t | f | s
(1 row)

For this patch, I have modified the test to use
'publish_generated_columns = stored'.

>
> 11.
> + 'check publication(publish_generated_columns as false) with
> generated columns and EXCEPT'
>
> Hmm. I thought there is no such thing as "publish_generated_columns as
> false", and also the EXCEPT should say 'EXCEPT (column-list)'
>
> ~~~
>
> 12.
> I wonder if there should be another boundary condition test case as follows:
> - have some table with cols a,b,c.
> - create a publication 'EXCEPT (a,b,c)', so you don't publish anything at all.
> - then ALTER the TABLE to add a column 'd'.
> - now the publication should publish only 'd'.
> ======

I have fixed all the comments and added the changes in the latest v18 patch.

Thanks,
Shlok Kyal

Attachment Content-Type Size
v18-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 20.4 KB
v18-0003-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 67.8 KB
v18-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 79.0 KB

From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-08-03 16:10:22
Message-ID: CANhcyEVB3bHYBsi1fnVaAMm6skkLbu9AdDbzKJ+q3io7uVMQQQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, 22 Jul 2025 at 14:29, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Sat, Jul 19, 2025 at 4:17 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > On Mon, 30 Jun 2025 at 16:25, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> > >
> > > Few more comments on 002:
> > >
> > > 5)
> > > +GetAllTablesPublicationRelations(Oid pubid, bool pubviaroot)
> > > {
> > >
> > > + List *exceptlist;
> > > +
> > > + exceptlist = GetPublicationRelations(pubid, PUBLICATION_PART_ALL);
> > >
> > >
> > > a) Here, we are assuming that the list provided by
> > > GetPublicationRelations() will be except-tables list only, but there
> > > is no validation of that.
> > > b) We are using GetPublicationRelations() to get the relations which
> > > are excluded from the publication. The name of function and comments
> > > atop function are not in alignment with this usage.
> > >
> > > Suggestion:
> > > We can have a new GetPublicationExcludeRelations() function for the
> > > concerned usage. The existing logic of GetPublicationRelations() can
> > > be shifted to a new internal-logic function which will accept a
> > > 'except-flag' as well. Both GetPublicationRelations() and
> > > GetPublicationExcludeRelations() can call that new function by passing
> > > 'except-flag' as false and true respectively. The new internal
> > > function will validate 'prexcept' against that except-flag passed and
> > > will return the results.
> > >
> > I have made the above change.
>
> Thank You for the changes.
>
> 1)
> But on rethinking, shall we make GetPublicationRelations() similar to :
>
> /* Gets list of publication oids for a relation that matches the except_flag */
> GetRelationPublications(Oid relid, bool except_flag)
>
> i.e. we can have a single function GetPublicationRelations() taking
> except_flag and comment can say: 'Gets list of relation oids for a
> publication that matches the except_flag.'
>
> We can get rid of GetPubIncludedOrExcludedRels() and
> GetPublicationExcludeRelations().
>
> Thoughts?
>
This seems reasonable to me. I have made the changes for the same.

>
> 2)
> we can rename except_table to except_flag to be consistent with
> GetRelationPublications()
>
> 3)
> + if ((except_table && pubrel->prexcept) || !except_table)
> + result = GetPubPartitionOptionRelations(result, pub_partopt,
> + pubrel->prrelid);
>
> 3a)
> In the case of '!except_table', we are not matching it with
> 'pubrel->prexcept', is that intentional?
>
> 3 b)
> Shall we simplify this similar to the changes in GetRelationPublications() i.e.
> if (except_table/flag == pubrel->prexcept)
> result = GetPubPartitionOptionRelations(...)
>
>
> >
> > > 6)
> > > Before your patch002, GetTopMostAncestorInPublication() was checking
> > > pg_publication_rel and pg_publication_namespace to find out if the
> > > table in the ancestor-list is part of a given particular. Both
> > > pg_publication_rel and pg_publication_namespace did not have the entry
> > > "for all tables" publications. That means
> > > GetTopMostAncestorInPublication() was originally not checking whether
> > > the given puboid is an "for all tables" publication to see if a rel
> > > belongs to that particular pub or not. I
> > >
> > > But now with the current change, we do check if pub is all-tables pub,
> > > if so, return relid and mark ancestor_level (provided table is not
> > > part of the except list). IIUC, the result in 2 cases may be
> > > different. Is that the intention? Let me know if my understanding is
> > > wrong.
> > >
> > This is intentional, in function get_rel_sync_entry, we are setting
> > pub_relid to the topmost published ancestor. In HEAD we are directly
> > setting using:
> > /*
> > * If this is a FOR ALL TABLES publication, pick the partition
> > * root and set the ancestor level accordingly.
> > */
> > if (pub->alltables)
> > {
> > publish = true;
> > if (pub->pubviaroot && am_partition)
> > {
> > List *ancestors = get_partition_ancestors(relid);
> >
> > pub_relid = llast_oid(ancestors);
> > ancestor_level = list_length(ancestors);
> > }
> > }
> > In HEAD, we can directly use 'llast_oid(ancestors)' to get the topmost
> > ancestor for case of FOR ALL TABLES.
> > But with this proposal. This change will no longer be valid as the
> > 'llast_oid(ancestors)' may be excluded in the publication. So, to
> > handle this change was made in GetTopMostAncestorInPublication.
> >
> >
> > Also, during testing with the partitioned table and
> > publish_via_partition_root the behaviour of the current patch is as
> > below:
> > For example we have a partitioned table t1. It has partitions part1
> > and part2. Now consider the following cases:
> > 1. with publish_via_partition_root = true
> > I. If we create publication on all tables with EXCEPT t1, no data
> > for t1, part1 or part2 is replicated.
>
> Okay. Agreed.
>
> > II. If we create publication on all tables with EXCEPT part1,
> > data for all tables t1, part1 and part2 is replicated.
>
> Okay. Is this because part1 changes are replicated through t1 and
> since t1 changes are not restricted, part1 changes will also not be
> restricted? In other words, part1 was never published directly in the
> first place and thus 'EXCEPT part1' has no meaning when
> 'publish_via_partition_root' = true? IMO, it is in alignment with the
> 'publish_via_partition_root' definition but it might not be that
> intuitive for users. So shall we emit a WARNING:
>
> WARNING: Partition "part1" is excluded, but publish_via_partition_root
> = true, so this will have no effect.
> Thoughts?
Your understanding is correct. I have added a WARNING for this case

>
> > 2. with publish_via_partition_root = false
> > I. If we create publication on all tables with EXCEPT t1, no data
> > for t1, part1 or part2 is replicated.
>
> I think we shall still publish partitions here. Since
> publish_via_partition_root is false, part1 and part2 are published
> individually and thus shall we allow publishing of part1 and part 2
> here? Thoughts?
I made a mistake in explaining this point. Yes your point is correct.
Changes for partitions part1 and part2 will be replicated.
I have documented the behaviour in the docs.

>
> > II. If we create publication on all tables with EXCEPT part1,
> > data for part1 is not replicated
> >
>
> Agreed.
>

I have addressed the comments and have attached the updated patch in [1].
[1]: https://www.postgresql.org/message-id/CANhcyEXkeg3sjkS3DS9yU1ckz4ozUBNZ%2BRmrWaRNSSVCR8RquA%40mail.gmail.com

Thanks,
Shlok Kyal


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-08-03 16:11:24
Message-ID: CANhcyEXWkUbssy06k-uL8CxVquJ0qaUWxzAPJu0ynAzLY=FkSA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, 22 Jul 2025 at 15:57, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> Shlok, I was trying to validate the interaction of
> 'publish_via_partition_root' with 'EXCEPT". Found some unexpected
> behaviour, can you please review:
>
> Pub:
> ---------
> CREATE TABLE tab_root (range_col int,i int,j int) PARTITION BY RANGE
> (range_col);
> CREATE TABLE tab_part_1 PARTITION OF tab_root FOR VALUES FROM (1) to (1000);
> CREATE TABLE tab_part_2 PARTITION OF tab_root FOR VALUES FROM (1000) to (2000);
> create publication pub2 for all tables except tab_part_2 WITH
> (publish_via_partition_root=true);
>
> Sub (tables without partition):
> --------
> CREATE TABLE tab_root (range_col int,i int,j int);
> CREATE TABLE tab_part_1(range_col int,i int,j int);
> CREATE TABLE tab_part_2(range_col int,i int,j int);
> create subscription sub2 connection '...' publication pub2;
>
> Pub:
> --------
> insert into tab_part_2 values(1001,1,1);
>
> On Sub, the above row is replicated as expected in tab_root due to
> publish_via_partition_root=true on pub.
>
> Now on Pub:
> --------
> alter publication pub2 set (publish_via_partition_root=false);
> insert into tab_part_2 values(1002,2,2);
>
> Now with publish_via_partition_root=false and 'except tab_part_2', the
> above row is correctly ignored and not replicated on sub.
>
> But when I try this:
> insert into tab_part_1 values(1,1,1);
> insert into tab_root values(5,5,5);
>
> Expectation was that the above rows are replicated but that is not the
> case. Can you please review? Please let me know if my understanding is
> wrong.

Hi Shveta,

I checked this behaviour on HEAD and found that it is the same
behaviour as HEAD. I think if we alter the parameter
'publish_via_partition_root', we should do ALTER SUBSCRIPTION ..
REFRESH PUBLICATION on subscriber.
I reviewed your behaviour and saw that after the 'alter publication
pub2 set (publish_via_partition_root=false)', the changes are still
being replicated to 'tab_root' on subscriber. And this behaviour is
similar to HEAD.

For example:
Pub:
---------
CREATE TABLE tab_root (range_col int,i int,j int) PARTITION BY RANGE
(range_col);
CREATE TABLE tab_part_1 PARTITION OF tab_root FOR VALUES FROM (1) to (1000);
CREATE TABLE tab_part_2 PARTITION OF tab_root FOR VALUES FROM (1000) to (2000);
create publication pub2 for table tab_root WITH
(publish_via_partition_root=true);

Sub (tables without partition):
--------
CREATE TABLE tab_root (range_col int,i int,j int);
CREATE TABLE tab_part_1(range_col int,i int,j int);
CREATE TABLE tab_part_2(range_col int,i int,j int);
create subscription sub2 connection '...' publication pub2;

Pub:
--------
insert into tab_part_2 values(1001,1,1);

On Sub, the above row is replicated as expected in tab_root.

Now on Pub:
--------
alter publication pub2 set (publish_via_partition_root=false);

when I try this the data:
insert into tab_part_2 values(1002,2,2);
insert into tab_part_1 values(1,1,1);
insert into tab_root values(5,5,5);

The data is being replicated to tab_root on the subscriber.

After I do ALTER SUBSCRIPTION .. REFRESH PUBLICATION on subscriber,
replication happens as expected.

Also I found following documentation:
"Altering the <literal>publish_via_partition_root</literal> parameter can
lead to data loss or duplication at the subscriber because it changes
the identity and schema of the published tables. Note this happens only
when a partition root table is specified as the replication target."

Thanks,
Shlok Kyal


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-08-03 16:12:16
Message-ID: CANhcyEWDB9ALsbMJ3RsrXs78TSdHoeUGpm2oKr8EdhwCtEYXXQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 23 Jul 2025 at 10:08, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> I further tested inherited tables flow as well wrt ONLY and EXCEPT, it
> works well. But while reading docs for the saem, I have few concerns.
>
> 1)
> While explaining ONLY for EXCEPT, create-publication doc says this
>
> + This does not apply to a partitioned table, however. The partitions of
> + a partitioned table are always implicitly considered part of the
> + publication, so they are never explicitly excluded from the publication.
>
> I do not understand the last line: "so they are never explicitly
> excluded from the publication" . But we can explicitly exclude them
> using EXCEPT <partition_name>. Do you mean to say something else here?
>
> 2)
> alter-publication doc says (in context of EXCEPT):
>
> "If ONLY is specified before the table name, only that table is
> affected. If ONLY is not specified, the table and all its descendant
> tables (if any) are affected. Optionally, * can be specified after
> the table name to explicitly indicate that descendant tables are
> affected."
>
> But it does not mention anything for partitions. I think we shall
> mention here as well that this does not apply to a partitioned table.
> (I tested ONLY and EXCEPT for partition-root. UNLIKE inherited tables,
> ONLY has no impact on partitioned tables.)
>
> 3)
> Shall we explain the relation of 'publish_via_partition_root' with
> EXCEPT briefly in docs(once we conclude that design)?
>
> Please note that I have performed all the tests (mentioned here and in
> previous emails) on patch001 and patch002. patch003 is not applied in
> these tests.
>
I have added/ modified the documentations as per the comments. The
changes are present in patch [1].
[1]: https://www.postgresql.org/message-id/CANhcyEXkeg3sjkS3DS9yU1ckz4ozUBNZ%2BRmrWaRNSSVCR8RquA%40mail.gmail.com

Thanks,
Shlok Kyal


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-08-04 07:33:21
Message-ID: CAHut+PsHavMy_KJ0MwR9J6q0BTTty54TxS-KBZc7X6tb4u7rfA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Aug 4, 2025 at 2:07 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
...
> > 10b.
> > How does "ALTER PUBLICATION tap_pub_col SET
> > (publish_generated_columns)" even work? I thought the
> > "pubish_generated_columns" is an enum but you did not specify any enum
> > value here (???)
> >
> > ~~~
> Yes, it works. It works equivalent to publish_generated_columns = stored.
> Eg:
> postgres=# CREATE PUBLICATION pub1 FOR TABLE t1 with
> (publish_generated_columns);
> CREATE PUBLICATION
> postgres=# select * from pg_publication;
> oid | pubname | pubowner | puballtables | pubinsert | pubupdate |
> pubdelete | pubtruncate | pubviaroot | pubgencols
> -------+---------+----------+--------------+-----------+-----------+-----------+-------------+------------+------------
> 16395 | pub1 | 10 | f | t | t | t
> | t | f | s
> (1 row)
>

Hmm -- it's not documented to behave like that, so I've created
another thread for getting to the bottom of this topic.

~~~

Meanwhile, here are my review comments for patch v18-0003

======
src/backend/catalog/pg_publication.c

pg_get_publication_tables:

1.
if (nattnums > 0)
{
values[2] = PointerGetDatum(buildint2vector(attnums, nattnums));
nulls[2] = false;
}
else
nulls[2] = true;

Is there any possibility that values[2] might not be null, but then
nattrnums skips some cols so remains 0? Then the final values[2] would
conflict with nulls[2], which seems strange. Maybe it is safer to also
assign values[2] = null in the else.

======
src/backend/replication/logical/tablesync.c

fetch_remote_table_info:

2.
static void
fetch_remote_table_info(char *nspname, char *relname, LogicalRepRelation *lrel,
- List **qual, bool *gencol_published)
+ List **qual, bool *gencol_published,
+ bool *no_cols_published)

This new parameter should be documented in the function comment.

~~~

3.
+ if (server_version >= 190000)
+ *no_cols_published = DatumGetBool(slot_getattr(tslot, 2, &isnull));
+

It seems that *no_cols_published (and *gencol_published) are assigned
false by the caller. I had to go looking for that, so IMO it would be
better to put Assert at the top of here so it is self-documenting

Assert(*gencol_published == false);
Assert(*no_cols_published == false);

======
src/backend/replication/pgoutput/pgoutput.c

4.
+ /*
+ * Indicates whether no columns are published for a given relation. With
+ * the introduction of the EXCEPT clause in column lists, it is now
+ * possible to define a publication that excludes all columns of a table.
+ * However, the 'columns' attribute cannot represent this case, since a
+ * NULL value implies that all columns are published. To distinguish this
+ * scenario, the 'no_cols_published' flag is introduced.
+ */
+ bool no_cols_published;

The wording of the comment seems a bit strange -- EXCEPT is not a clause.

BEFORE:
the introduction of the EXCEPT clause in column lists, ...

SUGGESTION
the introduction of the EXCEPT qualifier for column lists, ....

~~~

5.
Bitmapset *cols = NULL;
+ bool except_columns = false;
+ bool no_col_published = false;

There are multiple places in this patch that say:

'no_col_published'
or 'no_cols_published'

I felt this var name can be misunderstood because it is easy to read
"no" as meaning "no." (aka number), and then misinterpret as
"number_of_cols_published".

Maybe an unambiguous name can be found, like
- 'zero_cols_published' or
- 'nothing_published' or
- really make it 'num_cols_published' and check for 0.

(so this comment applies to multiple places in the patch)

~~

6.
* of the table (including generated columns when
* 'publish_generated_columns' parameter is true).
*/
- if (!cols)
+ if (!no_col_published && !cols)
{

The existing comment above this code fragment also needs to mention
"EXCEPT (column-list)" where all the columns are excluded

======
src/bin/psql/describe.c

describeOneTableDetails:

7.
/* column list (if any) */
if (!PQgetisnull(result, i, 2))
- appendPQExpBuffer(&buf, " (%s)",
- PQgetvalue(result, i, 2));
+ {
+ if (strcmp(PQgetvalue(result, i, 3), "t") == 0)
+ appendPQExpBuffer(&buf, " EXCEPT (%s)",
+ PQgetvalue(result, i, 2));
+ else
+ appendPQExpBuffer(&buf, " (%s)",
+ PQgetvalue(result, i, 2));
+ }

Isn't this code fragment (and also surrounding code) using the same
logic as what is already encapsulated in the function
addFooterToPublicationDesc()?
Superficially, it seems like a large chunk can all be replaced with a
single call to the existing function.

======
src/test/regress/expected/publication.out

8.
+-- Syntax error EXCEPT without a col-list
+CREATE PUBLICATION testpub_except2 FOR TABLE pub_test_except1 EXCEPT;
+ERROR: EXCEPT clause not allowed for table without column list
+LINE 1: CREATE PUBLICATION testpub_except2 FOR TABLE pub_test_except...
+ ^

Is that a bad syntax position marker (^)? e.g. Why is it pointed at
the word "TABLE" instead of "EXCEPT"?

======
.../t/037_rep_changes_except_collist.pl

9.
+# Test initial sync
+my $result = $node_subscriber->safe_psql('postgres', "SELECT * FROM tab1");
+is($result, qq(|2|3),
+ 'check that initial sync for EXCEPT (column-list) publication');
+$result = $node_subscriber->safe_psql('postgres', "SELECT * FROM sch1.tab1");
+is($result, qq(1||),
+ 'check that initial sync for EXCEPT (column-list) publication');

These messages still seem to have missing or extra words: "check that
initial sync" (??). Maybe just remove the word 'that'?

~~~

10.
# Test for update
$node_subscriber->safe_psql(
'postgres', qq(
CREATE UNIQUE INDEX b_idx ON tab1 (b);
ALTER TABLE tab1 REPLICA IDENTITY USING INDEX b_idx;
));
$node_publisher->safe_psql(
'postgres', qq(
CREATE UNIQUE INDEX b_idx ON tab1 (b);
ALTER TABLE tab1 REPLICA IDENTITY USING INDEX b_idx;
UPDATE tab1 SET a = 3, b = 4, c = 5 WHERE a = 1;
));
$node_publisher->wait_for_catchup('tap_sub_col');
$result = $node_subscriber->safe_psql('postgres', "SELECT * FROM tab1");
is( $result, qq(|5|6
|4|5),
'check update for EXCEPT (column-list) publication');

~

10a.
I think the test is OK, but your chosen numbers like 1,2,3, then 4,5,6
and then updating to 1,2,3 to 3,4,5 make it quite hard to review.
Maybe use easier numbers that are more identifiable, e.g. update 1,2,3
=> 991,992,993 or something like that.

~

10b.
You may need to put some ORDER BY in all these queries just to make
sure they are always reproducible, giving rows in the expected order.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-08-06 13:10:55
Message-ID: CANhcyEU=k4+0BqOu25N76g738XKUwfLGGdf8e+ssGiRKHC4RwQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 4 Aug 2025 at 13:03, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> On Mon, Aug 4, 2025 at 2:07 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> ...
> > > 10b.
> > > How does "ALTER PUBLICATION tap_pub_col SET
> > > (publish_generated_columns)" even work? I thought the
> > > "pubish_generated_columns" is an enum but you did not specify any enum
> > > value here (???)
> > >
> > > ~~~
> > Yes, it works. It works equivalent to publish_generated_columns = stored.
> > Eg:
> > postgres=# CREATE PUBLICATION pub1 FOR TABLE t1 with
> > (publish_generated_columns);
> > CREATE PUBLICATION
> > postgres=# select * from pg_publication;
> > oid | pubname | pubowner | puballtables | pubinsert | pubupdate |
> > pubdelete | pubtruncate | pubviaroot | pubgencols
> > -------+---------+----------+--------------+-----------+-----------+-----------+-------------+------------+------------
> > 16395 | pub1 | 10 | f | t | t | t
> > | t | f | s
> > (1 row)
> >
>
> Hmm -- it's not documented to behave like that, so I've created
> another thread for getting to the bottom of this topic.
>
> ~~~
>
> Meanwhile, here are my review comments for patch v18-0003
>
> ======
> src/backend/catalog/pg_publication.c
>
> pg_get_publication_tables:
>
> 1.
> if (nattnums > 0)
> {
> values[2] = PointerGetDatum(buildint2vector(attnums, nattnums));
> nulls[2] = false;
> }
> else
> nulls[2] = true;
>
> Is there any possibility that values[2] might not be null, but then
> nattrnums skips some cols so remains 0? Then the final values[2] would
> conflict with nulls[2], which seems strange. Maybe it is safer to also
> assign values[2] = null in the else.
>
Yes, When all the columns of a table are present in 'EXCEPT
(column-list)'. Then effectively no column should be replicated. In
such cases we should mark nulls[2] as true.
I agree with your point that values[2] should be made null. I have
used '(Datum) 0', in accordance with other places.

> ======
> src/backend/replication/logical/tablesync.c
>
> fetch_remote_table_info:
>
> 2.
> static void
> fetch_remote_table_info(char *nspname, char *relname, LogicalRepRelation *lrel,
> - List **qual, bool *gencol_published)
> + List **qual, bool *gencol_published,
> + bool *no_cols_published)
>
> This new parameter should be documented in the function comment.
>
> ~~~
>
> 3.
> + if (server_version >= 190000)
> + *no_cols_published = DatumGetBool(slot_getattr(tslot, 2, &isnull));
> +
>
> It seems that *no_cols_published (and *gencol_published) are assigned
> false by the caller. I had to go looking for that, so IMO it would be
> better to put Assert at the top of here so it is self-documenting
>
> Assert(*gencol_published == false);
> Assert(*no_cols_published == false);
>
> ======
> src/backend/replication/pgoutput/pgoutput.c
>
> 4.
> + /*
> + * Indicates whether no columns are published for a given relation. With
> + * the introduction of the EXCEPT clause in column lists, it is now
> + * possible to define a publication that excludes all columns of a table.
> + * However, the 'columns' attribute cannot represent this case, since a
> + * NULL value implies that all columns are published. To distinguish this
> + * scenario, the 'no_cols_published' flag is introduced.
> + */
> + bool no_cols_published;
>
> The wording of the comment seems a bit strange -- EXCEPT is not a clause.
>
> BEFORE:
> the introduction of the EXCEPT clause in column lists, ...
>
> SUGGESTION
> the introduction of the EXCEPT qualifier for column lists, ....
>
> ~~~
>
> 5.
> Bitmapset *cols = NULL;
> + bool except_columns = false;
> + bool no_col_published = false;
>
> There are multiple places in this patch that say:
>
> 'no_col_published'
> or 'no_cols_published'
>
> I felt this var name can be misunderstood because it is easy to read
> "no" as meaning "no." (aka number), and then misinterpret as
> "number_of_cols_published".
>
> Maybe an unambiguous name can be found, like
> - 'zero_cols_published' or
> - 'nothing_published' or
> - really make it 'num_cols_published' and check for 0.
>
> (so this comment applies to multiple places in the patch)
>
How about 'all_cols_excluded'? Or 'has_published_cols'?
I have used 'all_cols_excluded' in this patch. Thoughts?

> ~~
>
> 6.
> * of the table (including generated columns when
> * 'publish_generated_columns' parameter is true).
> */
> - if (!cols)
> + if (!no_col_published && !cols)
> {
>
> The existing comment above this code fragment also needs to mention
> "EXCEPT (column-list)" where all the columns are excluded
>
> ======
> src/bin/psql/describe.c
>
> describeOneTableDetails:
>
> 7.
> /* column list (if any) */
> if (!PQgetisnull(result, i, 2))
> - appendPQExpBuffer(&buf, " (%s)",
> - PQgetvalue(result, i, 2));
> + {
> + if (strcmp(PQgetvalue(result, i, 3), "t") == 0)
> + appendPQExpBuffer(&buf, " EXCEPT (%s)",
> + PQgetvalue(result, i, 2));
> + else
> + appendPQExpBuffer(&buf, " (%s)",
> + PQgetvalue(result, i, 2));
> + }
>
> Isn't this code fragment (and also surrounding code) using the same
> logic as what is already encapsulated in the function
> addFooterToPublicationDesc()?
> Superficially, it seems like a large chunk can all be replaced with a
> single call to the existing function.
>
'addFooterToPublicationDesc' is called when we use \dRp+ and print in format:
"schema_name.table_name" EXCEPT (column-list)
Whereas code pasted above is executed when we use \d+ table_name and
the output is the format:
"publication_name" EXCEPT (column-list)

These pieces of code are used to print different info. One is used to
print info related to tables and the other is used to print info
related to publication.
Should we use a common function for this?

> ======
> src/test/regress/expected/publication.out
>
> 8.
> +-- Syntax error EXCEPT without a col-list
> +CREATE PUBLICATION testpub_except2 FOR TABLE pub_test_except1 EXCEPT;
> +ERROR: EXCEPT clause not allowed for table without column list
> +LINE 1: CREATE PUBLICATION testpub_except2 FOR TABLE pub_test_except...
> + ^
>
> Is that a bad syntax position marker (^)? e.g. Why is it pointed at
> the word "TABLE" instead of "EXCEPT"?
>
In function 'preprocess_pubobj_list' the position of position marker
(^) is decided by "pubobj->location". Function handles multiple errors
and setting "$$->location" only specific to EXCEPT qualifier would not
be appropriate. One solution I feel is to not show "position marker
(^)" in the case of EXCEPT. Or maybe we can add a new variable to
'PublicationTable' for except_location but I think we should not do
that. Thoughts?

For this version of patch, I have removed the "position marker (^)" in
the case of EXCEPT.

> ======
> .../t/037_rep_changes_except_collist.pl
>
> 9.
> +# Test initial sync
> +my $result = $node_subscriber->safe_psql('postgres', "SELECT * FROM tab1");
> +is($result, qq(|2|3),
> + 'check that initial sync for EXCEPT (column-list) publication');
> +$result = $node_subscriber->safe_psql('postgres', "SELECT * FROM sch1.tab1");
> +is($result, qq(1||),
> + 'check that initial sync for EXCEPT (column-list) publication');
>
> These messages still seem to have missing or extra words: "check that
> initial sync" (??). Maybe just remove the word 'that'?
>
> ~~~
>
> 10.
> # Test for update
> $node_subscriber->safe_psql(
> 'postgres', qq(
> CREATE UNIQUE INDEX b_idx ON tab1 (b);
> ALTER TABLE tab1 REPLICA IDENTITY USING INDEX b_idx;
> ));
> $node_publisher->safe_psql(
> 'postgres', qq(
> CREATE UNIQUE INDEX b_idx ON tab1 (b);
> ALTER TABLE tab1 REPLICA IDENTITY USING INDEX b_idx;
> UPDATE tab1 SET a = 3, b = 4, c = 5 WHERE a = 1;
> ));
> $node_publisher->wait_for_catchup('tap_sub_col');
> $result = $node_subscriber->safe_psql('postgres', "SELECT * FROM tab1");
> is( $result, qq(|5|6
> |4|5),
> 'check update for EXCEPT (column-list) publication');
>
> ~
>
> 10a.
> I think the test is OK, but your chosen numbers like 1,2,3, then 4,5,6
> and then updating to 1,2,3 to 3,4,5 make it quite hard to review.
> Maybe use easier numbers that are more identifiable, e.g. update 1,2,3
> => 991,992,993 or something like that.
>
> ~
>
> 10b.
> You may need to put some ORDER BY in all these queries just to make
> sure they are always reproducible, giving rows in the expected order.
>

I have also addressed the remaining comments and attached the latest
v19 patches.

Thanks,
Shlok Kyal

Attachment Content-Type Size
v19-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 20.4 KB
v19-0003-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 69.0 KB
v19-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 79.0 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-08-11 08:25:12
Message-ID: CAHut+Ptdi8txJbMc+5Sp2uB4QLGOp-rZdkBbXyhAkxim0iAhBQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok.

On Wed, Aug 6, 2025 at 11:11 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
...
> > 5.
> > Bitmapset *cols = NULL;
> > + bool except_columns = false;
> > + bool no_col_published = false;
> >
> > There are multiple places in this patch that say:
> >
> > 'no_col_published'
> > or 'no_cols_published'
> >
> > I felt this var name can be misunderstood because it is easy to read
> > "no" as meaning "no." (aka number), and then misinterpret as
> > "number_of_cols_published".
> >
> > Maybe an unambiguous name can be found, like
> > - 'zero_cols_published' or
> > - 'nothing_published' or
> > - really make it 'num_cols_published' and check for 0.
> >
> > (so this comment applies to multiple places in the patch)
> >
> How about 'all_cols_excluded'? Or 'has_published_cols'?
> I have used 'all_cols_excluded' in this patch. Thoughts?

The new name is good.

> > ======
> > src/bin/psql/describe.c
> >
> > describeOneTableDetails:
> >
> > 7.
> > /* column list (if any) */
> > if (!PQgetisnull(result, i, 2))
> > - appendPQExpBuffer(&buf, " (%s)",
> > - PQgetvalue(result, i, 2));
> > + {
> > + if (strcmp(PQgetvalue(result, i, 3), "t") == 0)
> > + appendPQExpBuffer(&buf, " EXCEPT (%s)",
> > + PQgetvalue(result, i, 2));
> > + else
> > + appendPQExpBuffer(&buf, " (%s)",
> > + PQgetvalue(result, i, 2));
> > + }
> >
> > Isn't this code fragment (and also surrounding code) using the same
> > logic as what is already encapsulated in the function
> > addFooterToPublicationDesc()?
> > Superficially, it seems like a large chunk can all be replaced with a
> > single call to the existing function.
> >
> 'addFooterToPublicationDesc' is called when we use \dRp+ and print in format:
> "schema_name.table_name" EXCEPT (column-list)
> Whereas code pasted above is executed when we use \d+ table_name and
> the output is the format:
> "publication_name" EXCEPT (column-list)
>
> These pieces of code are used to print different info. One is used to
> print info related to tables and the other is used to print info
> related to publication.
> Should we use a common function for this?

It still seems like quite a lot of overlap. e.g. I thought there were
~30 lines common. OTOH, perhaps you'll need to pass another boolean to
the function to indicate it is a "Publication:" footer. I guess you'd
have to try it out first to see if the changes required to save those
30 LOC are worthwhile or not.

>
> > ======
> > src/test/regress/expected/publication.out
> >
> > 8.
> > +-- Syntax error EXCEPT without a col-list
> > +CREATE PUBLICATION testpub_except2 FOR TABLE pub_test_except1 EXCEPT;
> > +ERROR: EXCEPT clause not allowed for table without column list
> > +LINE 1: CREATE PUBLICATION testpub_except2 FOR TABLE pub_test_except...
> > + ^
> >
> > Is that a bad syntax position marker (^)? e.g. Why is it pointed at
> > the word "TABLE" instead of "EXCEPT"?
> >
> In function 'preprocess_pubobj_list' the position of position marker
> (^) is decided by "pubobj->location". Function handles multiple errors
> and setting "$$->location" only specific to EXCEPT qualifier would not
> be appropriate. One solution I feel is to not show "position marker
> (^)" in the case of EXCEPT. Or maybe we can add a new variable to
> 'PublicationTable' for except_location but I think we should not do
> that. Thoughts?

In the review comments below, I suggest putting this location back,
but changing the message.

>
> For this version of patch, I have removed the "position marker (^)" in
> the case of EXCEPT.
>

//////

Here are my review comments for the patch v19-0003.

======
1. General - SGML tags in docs for table/column names.

There is nothing to change just yet, but keep an eye on the thread
[1], because if/when that gets pushed, then there will several tags
in this patch for table/column names that will need to be updated for
consistency.

======
src/backend/catalog/pg_publication.c

pg_get_publication_tables:

2.
+
+ if (!nulls[2])
+ {
+ Datum exceptDatum;
+ bool isnull;
+
+ /*
+ * We fetch pubtuple if publication is not FOR ALL TABLES and
+ * not FOR TABLES IN SCHEMA. So if prexcept is true, it
+ * indicates that prattrs contains columns to be excluded for
+ * replication.
+ */
+ exceptDatum = SysCacheGetAttr(PUBLICATIONRELMAP, pubtuple,
+ Anum_pg_publication_rel_prexcept,
+ &isnull);
+
+ if (!isnull && DatumGetBool(exceptDatum))
+ except_columns = pub_collist_to_bitmapset(NULL, values[2], NULL);
+ }

Maybe this should be done a few lines earlier, to keep all the
values[2]/nulls[2] code together, ahead of the values[3]/nulls[3]
code. Indeed, there is lots of other values[2]/nulls[2] logic that
comes later in this function, so maybe it is better to do all of that
first, instead of mingling it with values[3]/nulls[3].

======
src/backend/commands/publicationcmds.c

pub_contains_invalid_column:

3.
* 1. Ensures that all columns referenced in the REPLICA IDENTITY are covered
- * by the column list. If any column is missing, *invalid_column_list is set
+ * by the column list and are not part of column list specified with EXCEPT.
+ * If any column is missing, *invalid_column_list is set
* to true.

Whitespace problem here; there is some tab instead of space in this comment.

Also /part of column list/part of the column list/

~~~

AlterPublicationTables:

4.
bool isnull = true;
Datum whereClauseDatum;
Datum columnListDatum;
+ Datum exceptDatum;

It's not necessary to have all these different Datum variables; they
are only temporary storage. It might be simpler to use a single "Datum
datum;" which is reused 3x.

~

5.
+ exceptDatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
+ Anum_pg_publication_rel_prexcept,
+ &isnull);
+
+ if (!isnull)
+ oldexcept = DatumGetBool(exceptDatum);
+

Isn't the 'prexcept' also used for EXCEPT TABLE as well as EXCEPT
(column-list)? In other words, should the change to this function be
done already in one of the earlier patches?

~

6.
if (equal(oldrelwhereclause, newpubrel->whereClause) &&
- bms_equal(oldcolumns, newcolumns))
+ bms_equal(oldcolumns, newcolumns) &&
+ oldexcept == newpubrel->except)

The code comment about this code fragment should also mention EXCEPT.

======
src/backend/parser/gram.y

preprocess_pubobj_list:

7.
+ if (pubobj->pubtable && pubobj->pubtable->except &&
+ pubobj->pubtable->columns == NULL)
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("EXCEPT clause not allowed for table without column list"));
+

Having the syntax error location (like before in v18) might be better,
but since that location is associated with the TABLE, then the error
message should also be reworded so the subject is the table.

SUGGESTION
errmsg("table without column list cannot use EXCEPT clause")

======
src/bin/psql/describe.c

describeOneTableDetails:

8.
- if (pset.sversion >= 150000)
+ if (pset.sversion >= 190000)
{
printfPQExpBuffer(&buf,
"SELECT pubname\n"
" , NULL\n"
" , NULL\n"
+ " , NULL\n"
"FROM pg_catalog.pg_publication p\n"
" JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n"
" JOIN pg_catalog.pg_class pc ON pc.relnamespace = pn.pnnspid\n"
@@ -3038,35 +3039,62 @@ describeOneTableDetails(const char *schemaname,
" pg_catalog.pg_attribute\n"
" WHERE attrelid = pr.prrelid AND attnum = prattrs[s])\n"
" ELSE NULL END) "
+ " , prexcept "
"FROM pg_catalog.pg_publication p\n"
" JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
" JOIN pg_catalog.pg_class c ON c.oid = pr.prrelid\n"
- "WHERE pr.prrelid = '%s'\n",
- oid, oid, oid);
-
- if (pset.sversion >= 190000)
- appendPQExpBufferStr(&buf, " AND NOT pr.prexcept\n");
+ "WHERE pr.prrelid = '%s' "
+ "AND c.relnamespace NOT IN (\n "
+ " SELECT pnnspid FROM\n"
+ " pg_catalog.pg_publication_namespace)\n"

- appendPQExpBuffer(&buf,
"UNION\n"
"SELECT pubname\n"
" , NULL\n"
" , NULL\n"
+ " , NULL\n"
"FROM pg_catalog.pg_publication p\n"
- "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n",
- oid);
-
- if (pset.sversion >= 190000)
- appendPQExpBuffer(&buf,
- " AND NOT EXISTS (\n"
- " SELECT 1\n"
- " FROM pg_catalog.pg_publication_rel pr\n"
- " JOIN pg_catalog.pg_class pc\n"
- " ON pr.prrelid = pc.oid\n"
- " WHERE pr.prrelid = '%s' AND pr.prpubid = p.oid)\n",
- oid);
-
- appendPQExpBufferStr(&buf, "ORDER BY 1;");
+ "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
+ " AND NOT EXISTS (\n"
+ " SELECT 1\n"
+ " FROM pg_catalog.pg_publication_rel pr\n"
+ " JOIN pg_catalog.pg_class pc\n"
+ " ON pr.prrelid = pc.oid\n"
+ " WHERE pr.prrelid = '%s' AND pr.prpubid = p.oid)\n"
+ "ORDER BY 1;",
+ oid, oid, oid, oid, oid);
+ }
+ else if (pset.sversion >= 150000)
+ {
+ printfPQExpBuffer(&buf,
+ "SELECT pubname\n"
+ " , NULL\n"
+ " , NULL\n"
+ "FROM pg_catalog.pg_publication p\n"
+ " JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n"
+ " JOIN pg_catalog.pg_class pc ON pc.relnamespace = pn.pnnspid\n"
+ "WHERE pc.oid ='%s' and pg_catalog.pg_relation_is_publishable('%s')\n"
+ "UNION\n"
+ "SELECT pubname\n"
+ " , pg_get_expr(pr.prqual, c.oid)\n"
+ " , (CASE WHEN pr.prattrs IS NOT NULL THEN\n"
+ " (SELECT string_agg(attname, ', ')\n"
+ " FROM pg_catalog.generate_series(0,
pg_catalog.array_upper(pr.prattrs::pg_catalog.int2[], 1)) s,\n"
+ " pg_catalog.pg_attribute\n"
+ " WHERE attrelid = pr.prrelid AND attnum = prattrs[s])\n"
+ " ELSE NULL END) "
+ "FROM pg_catalog.pg_publication p\n"
+ " JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
+ " JOIN pg_catalog.pg_class c ON c.oid = pr.prrelid\n"
+ "WHERE pr.prrelid = '%s'\n"
+ "UNION\n"
+ "SELECT pubname\n"
+ " , NULL\n"
+ " , NULL\n"
+ "FROM pg_catalog.pg_publication p\n"
+ "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
+ "ORDER BY 1;",
+ oid, oid, oid, oid);

I found these large SQL selects with 3x UNIONs are difficult to read.
Maybe you can add more comments to describe the intention of each of
the UNION SELECTs?

~~~

9.
/* column list (if any) */
if (!PQgetisnull(result, i, 2))
- appendPQExpBuffer(&buf, " (%s)",
- PQgetvalue(result, i, 2));
+ {
+ if (strcmp(PQgetvalue(result, i, 3), "t") == 0)
+ appendPQExpBuffer(&buf, " EXCEPT");
+ appendPQExpBuffer(&buf, " (%s)", PQgetvalue(result, i, 2));
+ }

I did not find any regression test case where the "EXCEPT" col-list is
getting output for a "Publications:" footer.

======
[1] https://www.postgresql.org/message-id/aIELRMAviNiUL1ie%40momjian.us

Kind Regards,
Peter Smith.
Fujitsu Australia


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-08-13 09:21:42
Message-ID: CANhcyEW+uJB_bvQLEaZCgoRTc1=i+QnrPPHxZ2=0SBSCyj9pkg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 11 Aug 2025 at 13:55, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok.
>
> On Wed, Aug 6, 2025 at 11:11 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> ...
> > > 5.
> > > Bitmapset *cols = NULL;
> > > + bool except_columns = false;
> > > + bool no_col_published = false;
> > >
> > > There are multiple places in this patch that say:
> > >
> > > 'no_col_published'
> > > or 'no_cols_published'
> > >
> > > I felt this var name can be misunderstood because it is easy to read
> > > "no" as meaning "no." (aka number), and then misinterpret as
> > > "number_of_cols_published".
> > >
> > > Maybe an unambiguous name can be found, like
> > > - 'zero_cols_published' or
> > > - 'nothing_published' or
> > > - really make it 'num_cols_published' and check for 0.
> > >
> > > (so this comment applies to multiple places in the patch)
> > >
> > How about 'all_cols_excluded'? Or 'has_published_cols'?
> > I have used 'all_cols_excluded' in this patch. Thoughts?
>
> The new name is good.
>
> > > ======
> > > src/bin/psql/describe.c
> > >
> > > describeOneTableDetails:
> > >
> > > 7.
> > > /* column list (if any) */
> > > if (!PQgetisnull(result, i, 2))
> > > - appendPQExpBuffer(&buf, " (%s)",
> > > - PQgetvalue(result, i, 2));
> > > + {
> > > + if (strcmp(PQgetvalue(result, i, 3), "t") == 0)
> > > + appendPQExpBuffer(&buf, " EXCEPT (%s)",
> > > + PQgetvalue(result, i, 2));
> > > + else
> > > + appendPQExpBuffer(&buf, " (%s)",
> > > + PQgetvalue(result, i, 2));
> > > + }
> > >
> > > Isn't this code fragment (and also surrounding code) using the same
> > > logic as what is already encapsulated in the function
> > > addFooterToPublicationDesc()?
> > > Superficially, it seems like a large chunk can all be replaced with a
> > > single call to the existing function.
> > >
> > 'addFooterToPublicationDesc' is called when we use \dRp+ and print in format:
> > "schema_name.table_name" EXCEPT (column-list)
> > Whereas code pasted above is executed when we use \d+ table_name and
> > the output is the format:
> > "publication_name" EXCEPT (column-list)
> >
> > These pieces of code are used to print different info. One is used to
> > print info related to tables and the other is used to print info
> > related to publication.
> > Should we use a common function for this?
>
> It still seems like quite a lot of overlap. e.g. I thought there were
> ~30 lines common. OTOH, perhaps you'll need to pass another boolean to
> the function to indicate it is a "Publication:" footer. I guess you'd
> have to try it out first to see if the changes required to save those
> 30 LOC are worthwhile or not.
>
I have added the code changes for the same in this patch.

> >
> > > ======
> > > src/test/regress/expected/publication.out
> > >
> > > 8.
> > > +-- Syntax error EXCEPT without a col-list
> > > +CREATE PUBLICATION testpub_except2 FOR TABLE pub_test_except1 EXCEPT;
> > > +ERROR: EXCEPT clause not allowed for table without column list
> > > +LINE 1: CREATE PUBLICATION testpub_except2 FOR TABLE pub_test_except...
> > > + ^
> > >
> > > Is that a bad syntax position marker (^)? e.g. Why is it pointed at
> > > the word "TABLE" instead of "EXCEPT"?
> > >
> > In function 'preprocess_pubobj_list' the position of position marker
> > (^) is decided by "pubobj->location". Function handles multiple errors
> > and setting "$$->location" only specific to EXCEPT qualifier would not
> > be appropriate. One solution I feel is to not show "position marker
> > (^)" in the case of EXCEPT. Or maybe we can add a new variable to
> > 'PublicationTable' for except_location but I think we should not do
> > that. Thoughts?
>
> In the review comments below, I suggest putting this location back,
> but changing the message.
>
> >
> > For this version of patch, I have removed the "position marker (^)" in
> > the case of EXCEPT.
> >
>
> //////
>
> Here are my review comments for the patch v19-0003.
>
> ======
> 1. General - SGML tags in docs for table/column names.
>
> There is nothing to change just yet, but keep an eye on the thread
> [1], because if/when that gets pushed, then there will several tags
> in this patch for table/column names that will need to be updated for
> consistency.
>
Noted

> ======
> src/backend/catalog/pg_publication.c
>
> pg_get_publication_tables:
>
> 2.
> +
> + if (!nulls[2])
> + {
> + Datum exceptDatum;
> + bool isnull;
> +
> + /*
> + * We fetch pubtuple if publication is not FOR ALL TABLES and
> + * not FOR TABLES IN SCHEMA. So if prexcept is true, it
> + * indicates that prattrs contains columns to be excluded for
> + * replication.
> + */
> + exceptDatum = SysCacheGetAttr(PUBLICATIONRELMAP, pubtuple,
> + Anum_pg_publication_rel_prexcept,
> + &isnull);
> +
> + if (!isnull && DatumGetBool(exceptDatum))
> + except_columns = pub_collist_to_bitmapset(NULL, values[2], NULL);
> + }
>
> Maybe this should be done a few lines earlier, to keep all the
> values[2]/nulls[2] code together, ahead of the values[3]/nulls[3]
> code. Indeed, there is lots of other values[2]/nulls[2] logic that
> comes later in this function, so maybe it is better to do all of that
> first, instead of mingling it with values[3]/nulls[3].
>
> ======
> src/backend/commands/publicationcmds.c
>
> pub_contains_invalid_column:
>
> 3.
> * 1. Ensures that all columns referenced in the REPLICA IDENTITY are covered
> - * by the column list. If any column is missing, *invalid_column_list is set
> + * by the column list and are not part of column list specified with EXCEPT.
> + * If any column is missing, *invalid_column_list is set
> * to true.
>
> Whitespace problem here; there is some tab instead of space in this comment.
>
> Also /part of column list/part of the column list/
>
> ~~~
>
> AlterPublicationTables:
>
> 4.
> bool isnull = true;
> Datum whereClauseDatum;
> Datum columnListDatum;
> + Datum exceptDatum;
>
> It's not necessary to have all these different Datum variables; they
> are only temporary storage. It might be simpler to use a single "Datum
> datum;" which is reused 3x.
>
> ~
>
> 5.
> + exceptDatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
> + Anum_pg_publication_rel_prexcept,
> + &isnull);
> +
> + if (!isnull)
> + oldexcept = DatumGetBool(exceptDatum);
> +
>
> Isn't the 'prexcept' also used for EXCEPT TABLE as well as EXCEPT
> (column-list)? In other words, should the change to this function be
> done already in one of the earlier patches?
>
> ~
This code path is only executed when running ALTER PUBLICATION ... SET
TABLE and running this command on a ALL TABLES publication throws an
error due to check by function 'CheckAlterPublication' . And EXCEPT
TABLE can only be used for ALL TABLES publications, I think it doesn’t
need to be moved to the 0002 patch.

>
> 6.
> if (equal(oldrelwhereclause, newpubrel->whereClause) &&
> - bms_equal(oldcolumns, newcolumns))
> + bms_equal(oldcolumns, newcolumns) &&
> + oldexcept == newpubrel->except)
>
> The code comment about this code fragment should also mention EXCEPT.
>
> ======
> src/backend/parser/gram.y
>
> preprocess_pubobj_list:
>
> 7.
> + if (pubobj->pubtable && pubobj->pubtable->except &&
> + pubobj->pubtable->columns == NULL)
> + ereport(ERROR,
> + errcode(ERRCODE_SYNTAX_ERROR),
> + errmsg("EXCEPT clause not allowed for table without column list"));
> +
>
> Having the syntax error location (like before in v18) might be better,
> but since that location is associated with the TABLE, then the error
> message should also be reworded so the subject is the table.
>
> SUGGESTION
> errmsg("table without column list cannot use EXCEPT clause")
>
> ======
> src/bin/psql/describe.c
>
> describeOneTableDetails:
>
> 8.
> - if (pset.sversion >= 150000)
> + if (pset.sversion >= 190000)
> {
> printfPQExpBuffer(&buf,
> "SELECT pubname\n"
> " , NULL\n"
> " , NULL\n"
> + " , NULL\n"
> "FROM pg_catalog.pg_publication p\n"
> " JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n"
> " JOIN pg_catalog.pg_class pc ON pc.relnamespace = pn.pnnspid\n"
> @@ -3038,35 +3039,62 @@ describeOneTableDetails(const char *schemaname,
> " pg_catalog.pg_attribute\n"
> " WHERE attrelid = pr.prrelid AND attnum = prattrs[s])\n"
> " ELSE NULL END) "
> + " , prexcept "
> "FROM pg_catalog.pg_publication p\n"
> " JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
> " JOIN pg_catalog.pg_class c ON c.oid = pr.prrelid\n"
> - "WHERE pr.prrelid = '%s'\n",
> - oid, oid, oid);
> -
> - if (pset.sversion >= 190000)
> - appendPQExpBufferStr(&buf, " AND NOT pr.prexcept\n");
> + "WHERE pr.prrelid = '%s' "
> + "AND c.relnamespace NOT IN (\n "
> + " SELECT pnnspid FROM\n"
> + " pg_catalog.pg_publication_namespace)\n"
>
> - appendPQExpBuffer(&buf,
> "UNION\n"
> "SELECT pubname\n"
> " , NULL\n"
> " , NULL\n"
> + " , NULL\n"
> "FROM pg_catalog.pg_publication p\n"
> - "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n",
> - oid);
> -
> - if (pset.sversion >= 190000)
> - appendPQExpBuffer(&buf,
> - " AND NOT EXISTS (\n"
> - " SELECT 1\n"
> - " FROM pg_catalog.pg_publication_rel pr\n"
> - " JOIN pg_catalog.pg_class pc\n"
> - " ON pr.prrelid = pc.oid\n"
> - " WHERE pr.prrelid = '%s' AND pr.prpubid = p.oid)\n",
> - oid);
> -
> - appendPQExpBufferStr(&buf, "ORDER BY 1;");
> + "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
> + " AND NOT EXISTS (\n"
> + " SELECT 1\n"
> + " FROM pg_catalog.pg_publication_rel pr\n"
> + " JOIN pg_catalog.pg_class pc\n"
> + " ON pr.prrelid = pc.oid\n"
> + " WHERE pr.prrelid = '%s' AND pr.prpubid = p.oid)\n"
> + "ORDER BY 1;",
> + oid, oid, oid, oid, oid);
> + }
> + else if (pset.sversion >= 150000)
> + {
> + printfPQExpBuffer(&buf,
> + "SELECT pubname\n"
> + " , NULL\n"
> + " , NULL\n"
> + "FROM pg_catalog.pg_publication p\n"
> + " JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n"
> + " JOIN pg_catalog.pg_class pc ON pc.relnamespace = pn.pnnspid\n"
> + "WHERE pc.oid ='%s' and pg_catalog.pg_relation_is_publishable('%s')\n"
> + "UNION\n"
> + "SELECT pubname\n"
> + " , pg_get_expr(pr.prqual, c.oid)\n"
> + " , (CASE WHEN pr.prattrs IS NOT NULL THEN\n"
> + " (SELECT string_agg(attname, ', ')\n"
> + " FROM pg_catalog.generate_series(0,
> pg_catalog.array_upper(pr.prattrs::pg_catalog.int2[], 1)) s,\n"
> + " pg_catalog.pg_attribute\n"
> + " WHERE attrelid = pr.prrelid AND attnum = prattrs[s])\n"
> + " ELSE NULL END) "
> + "FROM pg_catalog.pg_publication p\n"
> + " JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
> + " JOIN pg_catalog.pg_class c ON c.oid = pr.prrelid\n"
> + "WHERE pr.prrelid = '%s'\n"
> + "UNION\n"
> + "SELECT pubname\n"
> + " , NULL\n"
> + " , NULL\n"
> + "FROM pg_catalog.pg_publication p\n"
> + "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
> + "ORDER BY 1;",
> + oid, oid, oid, oid);
>
> I found these large SQL selects with 3x UNIONs are difficult to read.
> Maybe you can add more comments to describe the intention of each of
> the UNION SELECTs?
>
> ~~~
>
> 9.
> /* column list (if any) */
> if (!PQgetisnull(result, i, 2))
> - appendPQExpBuffer(&buf, " (%s)",
> - PQgetvalue(result, i, 2));
> + {
> + if (strcmp(PQgetvalue(result, i, 3), "t") == 0)
> + appendPQExpBuffer(&buf, " EXCEPT");
> + appendPQExpBuffer(&buf, " (%s)", PQgetvalue(result, i, 2));
> + }
>
> I did not find any regression test case where the "EXCEPT" col-list is
> getting output for a "Publications:" footer.
>
> ======
> [1] https://www.postgresql.org/message-id/aIELRMAviNiUL1ie%40momjian.us
>

I have addressed the comments and the changes in v20 patch.

Thanks,
Shlok Kyal

Attachment Content-Type Size
v20-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 20.4 KB
v20-0003-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 75.0 KB
v20-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 79.0 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-08-15 00:53:10
Message-ID: CAHut+Ptq0-tMYUOvG3yR34AvuEzR9vUH=muqV_=uEO3zCuA6rA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok,

Here are some review comments for v20-0003.

======
src/backend/commands/publicationcmds.c

AlterPublicationTables:

1.
bool isnull = true;
- Datum whereClauseDatum;
- Datum columnListDatum;
+ Datum datum;

I know you did not write the code, but that "isnull = true" is
redundant, and seems kind of misleading because it will always be
re-assigned before it is used.

~~~

2.
/* Load the WHERE clause for this table. */
- whereClauseDatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
- Anum_pg_publication_rel_prqual,
- &isnull);
+ datum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
+ Anum_pg_publication_rel_prqual,
+ &isnull);
if (!isnull)
- oldrelwhereclause = stringToNode(TextDatumGetCString(whereClauseDatum));
+ oldrelwhereclause = stringToNode(TextDatumGetCString(datum));

/* Transform the int2vector column list to a bitmap. */
- columnListDatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
- Anum_pg_publication_rel_prattrs,
- &isnull);
+ datum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
+ Anum_pg_publication_rel_prattrs,
+ &isnull);
+
+ if (!isnull)
+ oldcolumns = pub_collist_to_bitmapset(NULL, datum, NULL);
+
+ /* Load the prexcept flag for this table. */
+ datum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
+ Anum_pg_publication_rel_prexcept,
+ &isnull);

if (!isnull)
- oldcolumns = pub_collist_to_bitmapset(NULL, columnListDatum, NULL);
+ oldexcept = DatumGetBool(datum);

Use consistent spacing. Either do or don't (I prefer don't) put a
blank line between the pairs of "datum =" and "if (!isnull)". Avoid
having a mixture.

======
src/bin/psql/describe.c

addFooterToPublicationOrTableDesc:

3.
+/*
+ * If is_tbl_desc is true add footer to table description else add footer to
+ * publication description.
+ */
+static bool
+addFooterToPublicationOrTableDesc(PQExpBuffer buf, const char *footermsg,
+ bool as_schema, printTableContent *const cont,
+ bool is_tbl_desc)

3a.
Since you are changing this anyway, I think it would be better to keep
those boolean params together (at the end).

~

3b.
It seems a bit mixed up calling this addFooterToPublicationOrTableDesc
but having the variable 'is_tbl_desc', because it seems more natural
to me to read left to right, so the logical order of everything here
should be pub desc then table desc. In other words, use boolean
'is_pub_desc' instead of 'is_tbl_desc'. Also, I think that 'as_schema'
thing is kind of a *subset* of the publication description, so it
makes more sense for that to come last too.

e.g.
CURRENT
addFooterToPublicationOrTableDesc(buf, footermsg, as_schema, cont, is_tbl_desc)
SUGGESTION
addFooterToPublicationOrTableDesc(buf, cont, footermsg, is_pub_desc, as_schema)

~

3c
While you are changing things, maybe also consider changing that
'as_schema' name because I did not understand what "as" means. Perhaps
rename like 'pub_schemas', or 'only_show_schemas' or something better
(???).

~~~

4.
+ PGresult *res;
+ int count = 0;
+ int i = 0;
+ int col = is_tbl_desc ? 0 : 1;
+
+ res = PSQLexec(buf->data);
+ if (!res)
+ return false;
+ else
+ count = PQntuples(res);
+

4a.
Assignment count = 0 is redundant.

~

4b.
Remove the 'i' declaration here. Declare it in the "for" loop later.

~

4c.
The "else" is not required. If 'res' was not good, you already returned.

~~~

5.
+ if (as_schema)
+ printfPQExpBuffer(buf, " \"%s\"", PQgetvalue(res, i, 0));
+ else
+ {
+ if (is_tbl_desc)
+ printfPQExpBuffer(buf, " \"%s\"", PQgetvalue(res, i, col));
+ else
+ printfPQExpBuffer(buf, " \"%s.%s\"", PQgetvalue(res, i, 0),
+ PQgetvalue(res, i, col));

This function is basically either (a) a footer for a table description
or (b) a footer for a publication description. And that all hinges on
the boolean 'is_tbl_desc'. Therefore, it seems more natural for the
main condition to be "if (is_tbl_desc)" here.

This turned everything inside out. PSA: a top-up patch to show a way
to do this. Perhaps my implementation is a bit verbose, but OTOH it
seems easier to understand. Anyway, see what you think...

~~~

6.
+ /*---------------------------------------------------
+ * Publication/ table description columns:
+ * [0]: schema name (nspname)
+ * [col]: table name (relname) / publication name (pubname)
+ * [col + 1]: row filter expression (prqual), may be NULL
+ * [col + 2]: column list (comma-separated), may be NULL
+ * [col + 3]: except flag ("t" if EXCEPT, else "f")
+ *---------------------------------------------------

I've modified this comment slightly so I could understand it better.
See if you agree.

SUGGESTION
/*---------------------------------------------------
* Description columns:
* PUB TBL
* [0] - : schema name (nspname)
* [col] - : table name (relname)
* - [col] : publication name (pubname)
* [col+1] [col+1]: row filter expression (prqual), may be NULL
* [col+2] [col+1]: column list (comma-separated), may be NULL
* [col+3] [col+1]: except flag ("t" if EXCEPT, else "f")
*---------------------------------------------------
*/

~~~

describeOneTableDetails:

7.
+ else if (pset.sversion >= 150000)
+ {
+ printfPQExpBuffer(&buf,
+ "SELECT pubname\n"
+ " , NULL\n"
+ " , NULL\n"
+ "FROM pg_catalog.pg_publication p\n"
+ " JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n"
+ " JOIN pg_catalog.pg_class pc ON pc.relnamespace = pn.pnnspid\n"
+ "WHERE pc.oid ='%s' and pg_catalog.pg_relation_is_publishable('%s')\n"
+ "UNION\n"
+ "SELECT pubname\n"
+ " , pg_get_expr(pr.prqual, c.oid)\n"
+ " , (CASE WHEN pr.prattrs IS NOT NULL THEN\n"
+ " (SELECT string_agg(attname, ', ')\n"
+ " FROM pg_catalog.generate_series(0,
pg_catalog.array_upper(pr.prattrs::pg_catalog.int2[], 1)) s,\n"
+ " pg_catalog.pg_attribute\n"
+ " WHERE attrelid = pr.prrelid AND attnum = prattrs[s])\n"
+ " ELSE NULL END) "
+ "FROM pg_catalog.pg_publication p\n"
+ " JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
+ " JOIN pg_catalog.pg_class c ON c.oid = pr.prrelid\n"
+ "WHERE pr.prrelid = '%s'\n"
+ "UNION\n"
+ "SELECT pubname\n"
+ " , NULL\n"
+ " , NULL\n"
+ "FROM pg_catalog.pg_publication p\n"
+ "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
+ "ORDER BY 1;",
+ oid, oid, oid, oid);

AFAICT, that >= 150000 code seems to have added another UNION at the
end that was not previously there. What's that about? How is that
related to EXCEPT (column-list)?

======
Kind Regards,
Peter Smith.
Fujitsu Australia

Attachment Content-Type Size
PS_addFooterToPublicationOrTableDesc.diff application/octet-stream 4.8 KB

From: Kirill Reshke <reshkekirill(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-08-15 06:16:32
Message-ID: CALdSSPgiDj8S8POf_6kiUkVrt9-EqYmn+2ahDqpdBpyteeAz-Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi

On Fri, 15 Aug 2025 at 05:53, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:

> 1.
> bool isnull = true;
> - Datum whereClauseDatum;
> - Datum columnListDatum;
> + Datum datum;
>
> I know you did not write the code, but that "isnull = true" is
> redundant, and seems kind of misleading because it will always be
> re-assigned before it is used.

People are not generally excited about refactoring code they did not
change. This makes patch to have more review cycles, and less probable
to actually being committed. If we are really wedded with this change,
this could be a separate thread.

> ~~~
>
> 2.
> /* Load the WHERE clause for this table. */
> - whereClauseDatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
> - Anum_pg_publication_rel_prqual,
> - &isnull);
> + datum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
> + Anum_pg_publication_rel_prqual,
> + &isnull);
> if (!isnull)
> - oldrelwhereclause = stringToNode(TextDatumGetCString(whereClauseDatum));
> + oldrelwhereclause = stringToNode(TextDatumGetCString(datum));
>
> /* Transform the int2vector column list to a bitmap. */
> - columnListDatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
> - Anum_pg_publication_rel_prattrs,
> - &isnull);
> + datum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
> + Anum_pg_publication_rel_prattrs,
> + &isnull);
> +
> + if (!isnull)
> + oldcolumns = pub_collist_to_bitmapset(NULL, datum, NULL);
> +
> + /* Load the prexcept flag for this table. */
> + datum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
> + Anum_pg_publication_rel_prexcept,
> + &isnull);
>
> if (!isnull)
> - oldcolumns = pub_collist_to_bitmapset(NULL, columnListDatum, NULL);
> + oldexcept = DatumGetBool(datum);
>
> Use consistent spacing. Either do or don't (I prefer don't) put a
> blank line between the pairs of "datum =" and "if (!isnull)". Avoid
> having a mixture.
>
> ======
> src/bin/psql/describe.c
>
> addFooterToPublicationOrTableDesc:
>
> 3.
> +/*
> + * If is_tbl_desc is true add footer to table description else add footer to
> + * publication description.
> + */
> +static bool
> +addFooterToPublicationOrTableDesc(PQExpBuffer buf, const char *footermsg,
> + bool as_schema, printTableContent *const cont,
> + bool is_tbl_desc)
>
> 3a.
> Since you are changing this anyway, I think it would be better to keep
> those boolean params together (at the end).
>
> ~
>
> 3b.
> It seems a bit mixed up calling this addFooterToPublicationOrTableDesc
> but having the variable 'is_tbl_desc', because it seems more natural
> to me to read left to right, so the logical order of everything here
> should be pub desc then table desc. In other words, use boolean
> 'is_pub_desc' instead of 'is_tbl_desc'. Also, I think that 'as_schema'
> thing is kind of a *subset* of the publication description, so it
> makes more sense for that to come last too.
>
> e.g.
> CURRENT
> addFooterToPublicationOrTableDesc(buf, footermsg, as_schema, cont, is_tbl_desc)
> SUGGESTION
> addFooterToPublicationOrTableDesc(buf, cont, footermsg, is_pub_desc, as_schema)
>
> ~
>
> 3c
> While you are changing things, maybe also consider changing that
> 'as_schema' name because I did not understand what "as" means. Perhaps
> rename like 'pub_schemas', or 'only_show_schemas' or something better
> (???).
>
> ~~~
>
> 4.
> + PGresult *res;
> + int count = 0;
> + int i = 0;
> + int col = is_tbl_desc ? 0 : 1;
> +
> + res = PSQLexec(buf->data);
> + if (!res)
> + return false;
> + else
> + count = PQntuples(res);
> +
>
> 4a.
> Assignment count = 0 is redundant.
>
> ~
>
> 4b.
> Remove the 'i' declaration here. Declare it in the "for" loop later.
>
> ~
>
> 4c.
> The "else" is not required. If 'res' was not good, you already returned.
>
> ~~~
>
> 5.
> + if (as_schema)
> + printfPQExpBuffer(buf, " \"%s\"", PQgetvalue(res, i, 0));
> + else
> + {
> + if (is_tbl_desc)
> + printfPQExpBuffer(buf, " \"%s\"", PQgetvalue(res, i, col));
> + else
> + printfPQExpBuffer(buf, " \"%s.%s\"", PQgetvalue(res, i, 0),
> + PQgetvalue(res, i, col));
>
> This function is basically either (a) a footer for a table description
> or (b) a footer for a publication description. And that all hinges on
> the boolean 'is_tbl_desc'. Therefore, it seems more natural for the
> main condition to be "if (is_tbl_desc)" here.
>
> This turned everything inside out. PSA: a top-up patch to show a way
> to do this. Perhaps my implementation is a bit verbose, but OTOH it
> seems easier to understand. Anyway, see what you think...
>

+ 1

>
> 6.
> + /*---------------------------------------------------
> + * Publication/ table description columns:
> + * [0]: schema name (nspname)
> + * [col]: table name (relname) / publication name (pubname)
> + * [col + 1]: row filter expression (prqual), may be NULL
> + * [col + 2]: column list (comma-separated), may be NULL
> + * [col + 3]: except flag ("t" if EXCEPT, else "f")
> + *---------------------------------------------------
>
> I've modified this comment slightly so I could understand it better.
> See if you agree.

For me that's equal. lets see what other people think

--
Best regards,
Kirill Reshke


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-08-20 09:00:36
Message-ID: CANhcyEUEMWSkTfGc7Q3B+UiOzSiOmOGLgK-+C5DXwtCGOnDBhg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 15 Aug 2025 at 06:23, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok,
>
> Here are some review comments for v20-0003.
>
> ======
> src/backend/commands/publicationcmds.c
>
> AlterPublicationTables:
>
> 1.
> bool isnull = true;
> - Datum whereClauseDatum;
> - Datum columnListDatum;
> + Datum datum;
>
> I know you did not write the code, but that "isnull = true" is
> redundant, and seems kind of misleading because it will always be
> re-assigned before it is used.
>
Since this is part of already existing code, I think this should be a
new thread. I have created a new thread for this. See [1].

> ~~~
>
> 2.
> /* Load the WHERE clause for this table. */
> - whereClauseDatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
> - Anum_pg_publication_rel_prqual,
> - &isnull);
> + datum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
> + Anum_pg_publication_rel_prqual,
> + &isnull);
> if (!isnull)
> - oldrelwhereclause = stringToNode(TextDatumGetCString(whereClauseDatum));
> + oldrelwhereclause = stringToNode(TextDatumGetCString(datum));
>
> /* Transform the int2vector column list to a bitmap. */
> - columnListDatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
> - Anum_pg_publication_rel_prattrs,
> - &isnull);
> + datum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
> + Anum_pg_publication_rel_prattrs,
> + &isnull);
> +
> + if (!isnull)
> + oldcolumns = pub_collist_to_bitmapset(NULL, datum, NULL);
> +
> + /* Load the prexcept flag for this table. */
> + datum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
> + Anum_pg_publication_rel_prexcept,
> + &isnull);
>
> if (!isnull)
> - oldcolumns = pub_collist_to_bitmapset(NULL, columnListDatum, NULL);
> + oldexcept = DatumGetBool(datum);
>
> Use consistent spacing. Either do or don't (I prefer don't) put a
> blank line between the pairs of "datum =" and "if (!isnull)". Avoid
> having a mixture.
>
> ======
> src/bin/psql/describe.c
>
> addFooterToPublicationOrTableDesc:
>
> 3.
> +/*
> + * If is_tbl_desc is true add footer to table description else add footer to
> + * publication description.
> + */
> +static bool
> +addFooterToPublicationOrTableDesc(PQExpBuffer buf, const char *footermsg,
> + bool as_schema, printTableContent *const cont,
> + bool is_tbl_desc)
>
> 3a.
> Since you are changing this anyway, I think it would be better to keep
> those boolean params together (at the end).
>
> ~
>
> 3b.
> It seems a bit mixed up calling this addFooterToPublicationOrTableDesc
> but having the variable 'is_tbl_desc', because it seems more natural
> to me to read left to right, so the logical order of everything here
> should be pub desc then table desc. In other words, use boolean
> 'is_pub_desc' instead of 'is_tbl_desc'. Also, I think that 'as_schema'
> thing is kind of a *subset* of the publication description, so it
> makes more sense for that to come last too.
>
> e.g.
> CURRENT
> addFooterToPublicationOrTableDesc(buf, footermsg, as_schema, cont, is_tbl_desc)
> SUGGESTION
> addFooterToPublicationOrTableDesc(buf, cont, footermsg, is_pub_desc, as_schema)
>
> ~
>
> 3c
> While you are changing things, maybe also consider changing that
> 'as_schema' name because I did not understand what "as" means. Perhaps
> rename like 'pub_schemas', or 'only_show_schemas' or something better
> (???).
>
I have used pub_schemas.
> ~~~
>
> 4.
> + PGresult *res;
> + int count = 0;
> + int i = 0;
> + int col = is_tbl_desc ? 0 : 1;
> +
> + res = PSQLexec(buf->data);
> + if (!res)
> + return false;
> + else
> + count = PQntuples(res);
> +
>
> 4a.
> Assignment count = 0 is redundant.
>
> ~
>
> 4b.
> Remove the 'i' declaration here. Declare it in the "for" loop later.
>
> ~
>
> 4c.
> The "else" is not required. If 'res' was not good, you already returned.
>
> ~~~
>
> 5.
> + if (as_schema)
> + printfPQExpBuffer(buf, " \"%s\"", PQgetvalue(res, i, 0));
> + else
> + {
> + if (is_tbl_desc)
> + printfPQExpBuffer(buf, " \"%s\"", PQgetvalue(res, i, col));
> + else
> + printfPQExpBuffer(buf, " \"%s.%s\"", PQgetvalue(res, i, 0),
> + PQgetvalue(res, i, col));
>
> This function is basically either (a) a footer for a table description
> or (b) a footer for a publication description. And that all hinges on
> the boolean 'is_tbl_desc'. Therefore, it seems more natural for the
> main condition to be "if (is_tbl_desc)" here.
>
> This turned everything inside out. PSA: a top-up patch to show a way
> to do this. Perhaps my implementation is a bit verbose, but OTOH it
> seems easier to understand. Anyway, see what you think...
>
I have also used the patch with minor changes.

> ~~~
>
> 6.
> + /*---------------------------------------------------
> + * Publication/ table description columns:
> + * [0]: schema name (nspname)
> + * [col]: table name (relname) / publication name (pubname)
> + * [col + 1]: row filter expression (prqual), may be NULL
> + * [col + 2]: column list (comma-separated), may be NULL
> + * [col + 3]: except flag ("t" if EXCEPT, else "f")
> + *---------------------------------------------------
>
> I've modified this comment slightly so I could understand it better.
> See if you agree.
>
> SUGGESTION
> /*---------------------------------------------------
> * Description columns:
> * PUB TBL
> * [0] - : schema name (nspname)
> * [col] - : table name (relname)
> * - [col] : publication name (pubname)
> * [col+1] [col+1]: row filter expression (prqual), may be NULL
> * [col+2] [col+1]: column list (comma-separated), may be NULL
> * [col+3] [col+1]: except flag ("t" if EXCEPT, else "f")
> *---------------------------------------------------
> */
>
> ~~~
>
I have used the suggested description with some modifications.

> describeOneTableDetails:
>
> 7.
> + else if (pset.sversion >= 150000)
> + {
> + printfPQExpBuffer(&buf,
> + "SELECT pubname\n"
> + " , NULL\n"
> + " , NULL\n"
> + "FROM pg_catalog.pg_publication p\n"
> + " JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n"
> + " JOIN pg_catalog.pg_class pc ON pc.relnamespace = pn.pnnspid\n"
> + "WHERE pc.oid ='%s' and pg_catalog.pg_relation_is_publishable('%s')\n"
> + "UNION\n"
> + "SELECT pubname\n"
> + " , pg_get_expr(pr.prqual, c.oid)\n"
> + " , (CASE WHEN pr.prattrs IS NOT NULL THEN\n"
> + " (SELECT string_agg(attname, ', ')\n"
> + " FROM pg_catalog.generate_series(0,
> pg_catalog.array_upper(pr.prattrs::pg_catalog.int2[], 1)) s,\n"
> + " pg_catalog.pg_attribute\n"
> + " WHERE attrelid = pr.prrelid AND attnum = prattrs[s])\n"
> + " ELSE NULL END) "
> + "FROM pg_catalog.pg_publication p\n"
> + " JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
> + " JOIN pg_catalog.pg_class c ON c.oid = pr.prrelid\n"
> + "WHERE pr.prrelid = '%s'\n"
> + "UNION\n"
> + "SELECT pubname\n"
> + " , NULL\n"
> + " , NULL\n"
> + "FROM pg_catalog.pg_publication p\n"
> + "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
> + "ORDER BY 1;",
> + oid, oid, oid, oid);
>
> AFAICT, that >= 150000 code seems to have added another UNION at the
> end that was not previously there. What's that about? How is that
> related to EXCEPT (column-list)?
>
This patch does not add any new code to >= 150000. It is the same as
HEAD. This diff appears because of changes in 0002 patchset. In patch
0002, I did not create a separate full query for >= 190000 due to
small changes.

I have addressed the rest of the comments and added the changes in the
latest v21 patchset.

[1]: https://www.postgresql.org/message-id/CANhcyEXHiCbk2q8%3Dbq3boQDyc8ac9fjgK-kkp5PdTYLcAOq80Q%40mail.gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v21-0003-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 75.9 KB
v21-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 20.4 KB
v21-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 79.0 KB

From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Kirill Reshke <reshkekirill(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-08-20 09:02:38
Message-ID: CANhcyEVocpUmFspfPDgdPS7yMcNPPKQAC1GcKWwT-ZzccrCM1w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Kirill,

Thanks for reviewing the patch.

On Fri, 15 Aug 2025 at 11:46, Kirill Reshke <reshkekirill(at)gmail(dot)com> wrote:
>
> Hi
>
> On Fri, 15 Aug 2025 at 05:53, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> > 1.
> > bool isnull = true;
> > - Datum whereClauseDatum;
> > - Datum columnListDatum;
> > + Datum datum;
> >
> > I know you did not write the code, but that "isnull = true" is
> > redundant, and seems kind of misleading because it will always be
> > re-assigned before it is used.
>
> People are not generally excited about refactoring code they did not
> change. This makes patch to have more review cycles, and less probable
> to actually being committed. If we are really wedded with this change,
> this could be a separate thread.
>
I also feel that we should create a new thread for the same. I have
created a new thread. See [1].

>
> > ~~~
> >
> > 2.
> > /* Load the WHERE clause for this table. */
> > - whereClauseDatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
> > - Anum_pg_publication_rel_prqual,
> > - &isnull);
> > + datum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
> > + Anum_pg_publication_rel_prqual,
> > + &isnull);
> > if (!isnull)
> > - oldrelwhereclause = stringToNode(TextDatumGetCString(whereClauseDatum));
> > + oldrelwhereclause = stringToNode(TextDatumGetCString(datum));
> >
> > /* Transform the int2vector column list to a bitmap. */
> > - columnListDatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
> > - Anum_pg_publication_rel_prattrs,
> > - &isnull);
> > + datum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
> > + Anum_pg_publication_rel_prattrs,
> > + &isnull);
> > +
> > + if (!isnull)
> > + oldcolumns = pub_collist_to_bitmapset(NULL, datum, NULL);
> > +
> > + /* Load the prexcept flag for this table. */
> > + datum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
> > + Anum_pg_publication_rel_prexcept,
> > + &isnull);
> >
> > if (!isnull)
> > - oldcolumns = pub_collist_to_bitmapset(NULL, columnListDatum, NULL);
> > + oldexcept = DatumGetBool(datum);
> >
> > Use consistent spacing. Either do or don't (I prefer don't) put a
> > blank line between the pairs of "datum =" and "if (!isnull)". Avoid
> > having a mixture.
> >
> > ======
> > src/bin/psql/describe.c
> >
> > addFooterToPublicationOrTableDesc:
> >
> > 3.
> > +/*
> > + * If is_tbl_desc is true add footer to table description else add footer to
> > + * publication description.
> > + */
> > +static bool
> > +addFooterToPublicationOrTableDesc(PQExpBuffer buf, const char *footermsg,
> > + bool as_schema, printTableContent *const cont,
> > + bool is_tbl_desc)
> >
> > 3a.
> > Since you are changing this anyway, I think it would be better to keep
> > those boolean params together (at the end).
> >
> > ~
> >
> > 3b.
> > It seems a bit mixed up calling this addFooterToPublicationOrTableDesc
> > but having the variable 'is_tbl_desc', because it seems more natural
> > to me to read left to right, so the logical order of everything here
> > should be pub desc then table desc. In other words, use boolean
> > 'is_pub_desc' instead of 'is_tbl_desc'. Also, I think that 'as_schema'
> > thing is kind of a *subset* of the publication description, so it
> > makes more sense for that to come last too.
> >
> > e.g.
> > CURRENT
> > addFooterToPublicationOrTableDesc(buf, footermsg, as_schema, cont, is_tbl_desc)
> > SUGGESTION
> > addFooterToPublicationOrTableDesc(buf, cont, footermsg, is_pub_desc, as_schema)
> >
> > ~
> >
> > 3c
> > While you are changing things, maybe also consider changing that
> > 'as_schema' name because I did not understand what "as" means. Perhaps
> > rename like 'pub_schemas', or 'only_show_schemas' or something better
> > (???).
> >
> > ~~~
> >
> > 4.
> > + PGresult *res;
> > + int count = 0;
> > + int i = 0;
> > + int col = is_tbl_desc ? 0 : 1;
> > +
> > + res = PSQLexec(buf->data);
> > + if (!res)
> > + return false;
> > + else
> > + count = PQntuples(res);
> > +
> >
> > 4a.
> > Assignment count = 0 is redundant.
> >
> > ~
> >
> > 4b.
> > Remove the 'i' declaration here. Declare it in the "for" loop later.
> >
> > ~
> >
> > 4c.
> > The "else" is not required. If 'res' was not good, you already returned.
> >
> > ~~~
> >
> > 5.
> > + if (as_schema)
> > + printfPQExpBuffer(buf, " \"%s\"", PQgetvalue(res, i, 0));
> > + else
> > + {
> > + if (is_tbl_desc)
> > + printfPQExpBuffer(buf, " \"%s\"", PQgetvalue(res, i, col));
> > + else
> > + printfPQExpBuffer(buf, " \"%s.%s\"", PQgetvalue(res, i, 0),
> > + PQgetvalue(res, i, col));
> >
> > This function is basically either (a) a footer for a table description
> > or (b) a footer for a publication description. And that all hinges on
> > the boolean 'is_tbl_desc'. Therefore, it seems more natural for the
> > main condition to be "if (is_tbl_desc)" here.
> >
> > This turned everything inside out. PSA: a top-up patch to show a way
> > to do this. Perhaps my implementation is a bit verbose, but OTOH it
> > seems easier to understand. Anyway, see what you think...
> >
>
> + 1
>
Included these changes in the latest patch [2].

> >
> > 6.
> > + /*---------------------------------------------------
> > + * Publication/ table description columns:
> > + * [0]: schema name (nspname)
> > + * [col]: table name (relname) / publication name (pubname)
> > + * [col + 1]: row filter expression (prqual), may be NULL
> > + * [col + 2]: column list (comma-separated), may be NULL
> > + * [col + 3]: except flag ("t" if EXCEPT, else "f")
> > + *---------------------------------------------------
> >
> > I've modified this comment slightly so I could understand it better.
> > See if you agree.
>
> For me that's equal. lets see what other people think
>
For now I have used the version shared by Peter. I felt it was more descriptive.

[1] : https://www.postgresql.org/message-id/CANhcyEXHiCbk2q8%3Dbq3boQDyc8ac9fjgK-kkp5PdTYLcAOq80Q%40mail.gmail.com
[2] : https://www.postgresql.org/message-id/CANhcyEUEMWSkTfGc7Q3B%2BUiOzSiOmOGLgK-%2BC5DXwtCGOnDBhg%40mail.gmail.com

Thanks,
Shlok Kyal


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-08-21 00:03:31
Message-ID: CAHut+PuAgSDr3kbSxPMYEyCeGiJ5hgaT1JUvuiYPRT=Q+--O-Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok,

I reviewed your latest v20-0003 patch and have no more comments at
this time; I only found one trivial typo.

======
src/bin/psql/describe.c

1.
+ /*
+ * Footers entries for a publication description or a table
+ * description
+ */

Typo. /Footers entries/Footer entries/

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-08-25 08:08:24
Message-ID: CANhcyEU_uuiKMRrd_E_DeYsyCvwY_u995E-Do3d66J7tQnzdzw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 21 Aug 2025 at 05:33, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok,
>
> I reviewed your latest v20-0003 patch and have no more comments at
> this time; I only found one trivial typo.
>
> ======
> src/bin/psql/describe.c
>
> 1.
> + /*
> + * Footers entries for a publication description or a table
> + * description
> + */
>
> Typo. /Footers entries/Footer entries/
>

I have fixed it and attached the updated patches

Thanks,
Shlok Kyal

Attachment Content-Type Size
v22-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 79.0 KB
v22-0003-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 75.9 KB
v22-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 20.4 KB

From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-09-05 06:27:23
Message-ID: CANhcyEWK9sj9UY4uaV36Q8qxUv=8Joch0o98RCN5U3xLjUxAag@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 25 Aug 2025 at 13:38, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> On Thu, 21 Aug 2025 at 05:33, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >
> > Hi Shlok,
> >
> > I reviewed your latest v20-0003 patch and have no more comments at
> > this time; I only found one trivial typo.
> >
> > ======
> > src/bin/psql/describe.c
> >
> > 1.
> > + /*
> > + * Footers entries for a publication description or a table
> > + * description
> > + */
> >
> > Typo. /Footers entries/Footer entries/
> >
>
> I have fixed it and attached the updated patches
>
The patches were not applying on HEAD and needed a Rebase. Here is the
rebased patches

Thanks,
Shlok Kyal

Attachment Content-Type Size
v23-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 20.4 KB
v23-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 79.1 KB
v23-0003-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 76.0 KB

From: vignesh C <vignesh21(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-09-25 08:48:04
Message-ID: CALDaNm3U5NVEGCktcCQFms2nFcrDq42Q6ZWeEV4Hq29OPAQa3A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 5 Sept 2025 at 11:57, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> On Mon, 25 Aug 2025 at 13:38, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > On Thu, 21 Aug 2025 at 05:33, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> > >
> > > Hi Shlok,
> > >
> > > I reviewed your latest v20-0003 patch and have no more comments at
> > > this time; I only found one trivial typo.
> > >
> > > ======
> > > src/bin/psql/describe.c
> > >
> > > 1.
> > > + /*
> > > + * Footers entries for a publication description or a table
> > > + * description
> > > + */
> > >
> > > Typo. /Footers entries/Footer entries/
> > >
> >
> > I have fixed it and attached the updated patches
> >
> The patches were not applying on HEAD and needed a Rebase. Here is the
> rebased patches

Consider the following scenario:
create table t1(c1 int, c2 int);
create publication pub1 for table t1 except (c1, c2);

In this case, the publication is created in such a way that no columns
are included, so effectively no data will be replicated to the
subscriber.
However, when attempting an UPDATE, the following error occurs:
postgres=# update t1 set c1 = 2;
ERROR: cannot update table "t1" because it does not have a replica
identity and publishes updates
HINT: To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.

Is this behavior expected?

Regards,
Vignesh


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-09-25 11:08:54
Message-ID: CALDaNm32XQDR4qsOhPQeophVbZ8r+ShJSSssoVfdPcwG6joPHQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 5 Sept 2025 at 11:57, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> On Mon, 25 Aug 2025 at 13:38, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > On Thu, 21 Aug 2025 at 05:33, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> > >
> > > Hi Shlok,
> > >
> > > I reviewed your latest v20-0003 patch and have no more comments at
> > > this time; I only found one trivial typo.
> > >
> > > ======
> > > src/bin/psql/describe.c
> > >
> > > 1.
> > > + /*
> > > + * Footers entries for a publication description or a table
> > > + * description
> > > + */
> > >
> > > Typo. /Footers entries/Footer entries/
> > >
> >
> > I have fixed it and attached the updated patches
> >
> The patches were not applying on HEAD and needed a Rebase. Here is the
> rebased patches

Few comments:
1) Currently from pg_publication_tables it is not clear if it is
replicating column list or replicating exclude column, can we indicate
if it is exclude or not:
create publication pub1 for table t1(c1);
create publication pub2 for table t1 except ( c1);

postgres=# select * from pg_publication_tables;
pubname | schemaname | tablename | attnames | rowfilter
---------+------------+-----------+----------+-----------
pub1 | public | t1 | {c1} |
pub2 | public | t1 | {c2} |
(2 rows)

2) Tab completion is not correct in this case:
postgres=# alter publication pub3 add table t2 EXCEPT (
, WHERE (

3) tab6 is not used anywhere, it can be removed:
+ CREATE TABLE tab5 (a int, b int, c int);
+ CREATE TABLE tab6 (agen int GENERATED ALWAYS AS (1) STORED,
bgen int GENERATED ALWAYS AS (2) STORED);
+ INSERT INTO tab1 VALUES (1, 2, 3);

4) both these tests are using same message:
+ $node_subscriber->safe_psql('postgres', "SELECT * FROM tab1 ORDER BY a");
+is( $result, qq(|2|3
+|5|6),
+ 'check incremental insert for EXCEPT (column-list) publication');
+$result = $node_subscriber->safe_psql('postgres',
+ "SELECT * FROM sch1.tab1 ORDER BY a");
+is( $result, qq(1||
+4||), 'check incremental insert for EXCEPT (column-list) publication');

we can include table name here to differentiate the test that will
help in identifying test failure easily

5) /newly added column are is replicated/ should be "newly added
column is replicated"
is($result, qq(|||10), 'newly added column are is replicated');

Regards,
Vignesh


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-09-26 18:53:58
Message-ID: CANhcyEX5zTAcqo8+Gz_eCCmc=D5TtnJ_dOydgaqqawNrEn3TNQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 25 Sept 2025 at 14:18, vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Fri, 5 Sept 2025 at 11:57, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > On Mon, 25 Aug 2025 at 13:38, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > >
> > > On Thu, 21 Aug 2025 at 05:33, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> > > >
> > > > Hi Shlok,
> > > >
> > > > I reviewed your latest v20-0003 patch and have no more comments at
> > > > this time; I only found one trivial typo.
> > > >
> > > > ======
> > > > src/bin/psql/describe.c
> > > >
> > > > 1.
> > > > + /*
> > > > + * Footers entries for a publication description or a table
> > > > + * description
> > > > + */
> > > >
> > > > Typo. /Footers entries/Footer entries/
> > > >
> > >
> > > I have fixed it and attached the updated patches
> > >
> > The patches were not applying on HEAD and needed a Rebase. Here is the
> > rebased patches
>
> Consider the following scenario:
> create table t1(c1 int, c2 int);
> create publication pub1 for table t1 except (c1, c2);
>
> In this case, the publication is created in such a way that no columns
> are included, so effectively no data will be replicated to the
> subscriber.
> However, when attempting an UPDATE, the following error occurs:
> postgres=# update t1 set c1 = 2;
> ERROR: cannot update table "t1" because it does not have a replica
> identity and publishes updates
> HINT: To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.
>
> Is this behavior expected?

Hi Vignesh,

I think this behaviour is same as other similar cases like:

1. publication on empty table:
CREATE TABLE t1();
CREATE PUBLICATION pub1 FOR TABLE t1;

postgres=# DELETE FROM t1;
ERROR: cannot delete from table "t1" because it does not have a
replica identity and publishes deletes
HINT: To enable deleting from the table, set REPLICA IDENTITY using
ALTER TABLE.

2. All the columns in a table is a generated column:
CREATE TABLE t2(a int GENERATED ALWAYS AS (2*2) STORED);
CREATE PUBLICATION pub2 FOR TABLE t2 WITH (publish_generated_columns='none');

In this case since "publish_generated_columns=none", should not
publish changes for table t2. But we get following:
postgres=# DELETE FROM t2;
ERROR: cannot delete from table "t2" because it does not have a
replica identity and publishes deletes
HINT: To enable deleting from the table, set REPLICA IDENTITY using
ALTER TABLE.

In above cases as well no columns are published but we have the similar error.
Given these behaviours in HEAD I think it is okay for EXCEPT
column_list to have the similar behaviour when all columns are
excluded. Thought?

Thanks,
Shlok Kyal


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-09-26 19:50:31
Message-ID: CANhcyEVt2CBnG7MOktaPPV4rYapHR-VHe5=qoziTZh1L9SVc6w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 25 Sept 2025 at 16:39, vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Fri, 5 Sept 2025 at 11:57, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > On Mon, 25 Aug 2025 at 13:38, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > >
> > > On Thu, 21 Aug 2025 at 05:33, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> > > >
> > > > Hi Shlok,
> > > >
> > > > I reviewed your latest v20-0003 patch and have no more comments at
> > > > this time; I only found one trivial typo.
> > > >
> > > > ======
> > > > src/bin/psql/describe.c
> > > >
> > > > 1.
> > > > + /*
> > > > + * Footers entries for a publication description or a table
> > > > + * description
> > > > + */
> > > >
> > > > Typo. /Footers entries/Footer entries/
> > > >
> > >
> > > I have fixed it and attached the updated patches
> > >
> > The patches were not applying on HEAD and needed a Rebase. Here is the
> > rebased patches
>
> Few comments:
> 1) Currently from pg_publication_tables it is not clear if it is
> replicating column list or replicating exclude column, can we indicate
> if it is exclude or not:
> create publication pub1 for table t1(c1);
> create publication pub2 for table t1 except ( c1);
>
> postgres=# select * from pg_publication_tables;
> pubname | schemaname | tablename | attnames | rowfilter
> ---------+------------+-----------+----------+-----------
> pub1 | public | t1 | {c1} |
> pub2 | public | t1 | {c2} |
> (2 rows)
>
> 2) Tab completion is not correct in this case:
> postgres=# alter publication pub3 add table t2 EXCEPT (
> , WHERE (
>
> 3) tab6 is not used anywhere, it can be removed:
> + CREATE TABLE tab5 (a int, b int, c int);
> + CREATE TABLE tab6 (agen int GENERATED ALWAYS AS (1) STORED,
> bgen int GENERATED ALWAYS AS (2) STORED);
> + INSERT INTO tab1 VALUES (1, 2, 3);
>
> 4) both these tests are using same message:
> + $node_subscriber->safe_psql('postgres', "SELECT * FROM tab1 ORDER BY a");
> +is( $result, qq(|2|3
> +|5|6),
> + 'check incremental insert for EXCEPT (column-list) publication');
> +$result = $node_subscriber->safe_psql('postgres',
> + "SELECT * FROM sch1.tab1 ORDER BY a");
> +is( $result, qq(1||
> +4||), 'check incremental insert for EXCEPT (column-list) publication');
>
> we can include table name here to differentiate the test that will
> help in identifying test failure easily
>
> 5) /newly added column are is replicated/ should be "newly added
> column is replicated"
> is($result, qq(|||10), 'newly added column are is replicated');
Hi Vignesh,

Thanks for reviewing the patch.
I have addressed the comments and attached the updated version.

Thanks,
Shlok Kyal

Attachment Content-Type Size
v24-0003-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 85.3 KB
v24-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 20.4 KB
v24-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 79.2 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-09-29 03:28:12
Message-ID: CAHut+PuRVPYePeFgaMFs3q3i7nFRmJX9G+XuJGJ0hjWyj7uWYw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok,

I was looking at the recent v24 changes.

======
GENERAL.

I saw that you modified the system view to add a new flag:

+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>exceptcol</structfield> <type>bool</type>
+ </para>
+ <para>
+ True if a column list with <literal>EXCEPT</literal> clause is specified
+ for the table in the publication.
+ </para></entry>
+ </row>

So output now might look like this:

+CREATE TABLE pub_test_except1 (a int NOT NULL, b int, c int NOT NULL, d int);
+CREATE PUBLICATION testpub_except FOR TABLE pub_test_except1,
pub_sch1.pub_test_except2 EXCEPT (b, c);
+SELECT * FROM pg_publication_tables WHERE pubname = 'testpub_except';
+ pubname | schemaname | tablename | attnames |
rowfilter | exceptcol
+----------------+------------+------------------+-----------+-----------+-----------
+ testpub_except | public | pub_test_except1 | {a,b,c,d} | | f
+ testpub_except | pub_sch1 | pub_test_except2 | {a,d} | | t
+(2 rows)

~~~

I think this was done in response to a comment from Vignesh [1], but
it did not get implemented in the way that I had imagined. e.g. I
imagined the view might be more like this:

+ pubname | schemaname | tablename | attnames |
rowfilter | exceptcols
+----------------+------------+------------------+-----------+-----------+-----------
+ testpub_except | public | pub_test_except1 | {a,b,c,d} | |
+ testpub_except | pub_sch1 | pub_test_except2 | {a,d} | | {b,c}

I don't know if broadcasting to the user what the unpublished/hidden
columns' names are is very wise (e.g. "{password,internal_notes,
salary}", but OTOH just having a boolean flag saying that "something"
was excluded ddin't seem useful.

~

Furthermore, having a Boolean seemed strangely incompatible with a
normal column list. e.g. Lets say there is a table T1 with cols
c1,c2,c3,c4.

I could publish that as "FOR TABLE T1(c1,c2,c3)"
Or as "FOR TABLE T1 EXCEPT (c4)"

In the v24 implementation, AFAIK, the view will show those as
"attnames = {c1,c2,c3}", and except will be both "f" and "t". It
seemed odd to.

~

Lastly, I think the EXCEPT (col-list) feature was mostly added just
to help users with 100s of columns to write their CREATE PUBLICATION
statement more easily. Since the view already shows all the columns
that will be published. So, I'm kind of -0.5 on this idea of changing
the view to show how they typed their statement.

======
[1] https://www.postgresql.org/message-id/CALDaNm32XQDR4qsOhPQeophVbZ8r%2BShJSSssoVfdPcwG6joPHQ%40mail.gmail.com

Kind Regards,
Peter Smith.
Fujitsu Australia


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-09-29 15:30:14
Message-ID: CALDaNm3K5SDVHhrnqgb3=FmUg+UJ3GW4H9dU3_zBGi1d+JAVvw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, 27 Sept 2025 at 01:20, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> Thanks for reviewing the patch.
> I have addressed the comments and attached the updated version.

If all columns are excluded, we do not publish the changes. However,
when a table has no columns, the data is still replicated. Should we
make this behavior consistent?
@@ -1482,6 +1525,13 @@ pgoutput_change(LogicalDecodingContext *ctx,
ReorderBufferTXN *txn,
relentry = get_rel_sync_entry(data, relation);
+ /*
+ * If all columns of a table are present in column list specified with
+ * EXCEPT, skip publishing the changes.
+ */
+ if (relentry->all_cols_excluded)
+ return;

Steps to check the above issue:
-- pub
create table t1();
create table t2(c1 int, c2 int);
create publication pub1 FOR table t1;
create publication pub2 FOR table t2 except(c1, c2);

--sub
create table t1(c1 int);
create table t2(c1 int, c2 int);
create subscription sub1 connection 'dbname=postgres host=localhost
port=5432' publication pub1,pub2;

--pub
postgres=# insert into t1 default values ;
INSERT 0 1
postgres=# insert into t2 default values;
INSERT 0 1

--sub
-- In case of table having no columns, data is replicated
postgres=# select * from t1;
c1
----

(1 row)

-- In case of table having all columns excluded, data is not replicated
postgres=# select * from t2;
c1 | c2
----+----
(0 rows)

Thoughts?

Regards,
Vignesh


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-09-30 04:57:48
Message-ID: CALDaNm0xDv96F+5LzcJYV6RC3Jg+RtdUqpQ-zoauwq3woTFzmQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 29 Sept 2025 at 08:58, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok,
>
> I was looking at the recent v24 changes.
>
> ======
> GENERAL.
>
> I saw that you modified the system view to add a new flag:
>
> + <row>
> + <entry role="catalog_table_entry"><para role="column_definition">
> + <structfield>exceptcol</structfield> <type>bool</type>
> + </para>
> + <para>
> + True if a column list with <literal>EXCEPT</literal> clause is specified
> + for the table in the publication.
> + </para></entry>
> + </row>
>
> So output now might look like this:
>
> +CREATE TABLE pub_test_except1 (a int NOT NULL, b int, c int NOT NULL, d int);
> +CREATE PUBLICATION testpub_except FOR TABLE pub_test_except1,
> pub_sch1.pub_test_except2 EXCEPT (b, c);
> +SELECT * FROM pg_publication_tables WHERE pubname = 'testpub_except';
> + pubname | schemaname | tablename | attnames |
> rowfilter | exceptcol
> +----------------+------------+------------------+-----------+-----------+-----------
> + testpub_except | public | pub_test_except1 | {a,b,c,d} | | f
> + testpub_except | pub_sch1 | pub_test_except2 | {a,d} | | t
> +(2 rows)
>
> ~~~
>
> I think this was done in response to a comment from Vignesh [1], but
> it did not get implemented in the way that I had imagined. e.g. I
> imagined the view might be more like this:
>
> + pubname | schemaname | tablename | attnames |
> rowfilter | exceptcols
> +----------------+------------+------------------+-----------+-----------+-----------
> + testpub_except | public | pub_test_except1 | {a,b,c,d} | |
> + testpub_except | pub_sch1 | pub_test_except2 | {a,d} | | {b,c}
>
> I don't know if broadcasting to the user what the unpublished/hidden
> columns' names are is very wise (e.g. "{password,internal_notes,
> salary}", but OTOH just having a boolean flag saying that "something"
> was excluded ddin't seem useful.
>
> ~
>
> Furthermore, having a Boolean seemed strangely incompatible with a
> normal column list. e.g. Lets say there is a table T1 with cols
> c1,c2,c3,c4.
>
> I could publish that as "FOR TABLE T1(c1,c2,c3)"
> Or as "FOR TABLE T1 EXCEPT (c4)"
>
> In the v24 implementation, AFAIK, the view will show those as
> "attnames = {c1,c2,c3}", and except will be both "f" and "t". It
> seemed odd to.
>
> ~
>
> Lastly, I think the EXCEPT (col-list) feature was mostly added just
> to help users with 100s of columns to write their CREATE PUBLICATION
> statement more easily. Since the view already shows all the columns
> that will be published. So, I'm kind of -0.5 on this idea of changing
> the view to show how they typed their statement.

On further consideration, I’m ok with removing this column to avoid
potential confusion.

Regards,
Vignesh


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-10-24 01:11:20
Message-ID: CAHut+PvoOVo=_O-sG8wNaLRBPSD+6S=4PXOH2r=yKTxbpAbHkg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Vignesh,

I had a look at patch v24-0001.

FYI -- a rebase is needed

[postgres(at)CentOS7-x64 oss_postgres_misc]$ git apply
../patches_misc/v24-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch
error: patch failed: doc/src/sgml/ref/alter_publication.sgml:69
error: doc/src/sgml/ref/alter_publication.sgml: patch does not apply

Here are some other review comments:

======

1.
There seems to be some basic omission of the ALTER PUBLICATION in that
it does not support "ALL TABLES" as a publication_object.

Therefore, if you have:
CREATE PUBLICATION mypub FOR ALL TABLES;

and then you do:
ALTER PUBLICATION mypub RESET;

There seems to be no way to restore mpub to be an ALL TABLES publication again!

~~~

I think if you are going to implement a RESET, then you also need a
way to get back to what you had before you did the reset. So you'll
also need to implement the ALTER PUBLICATION mypub SET ALL TABLES;

IMO, supporting "SET ALL TABLES" should be your new 0001 patch
because AFAIK, this situation already exists if the user had created
an "empty" publication:
CREATE PUBLICATION myemptypub;

======
doc/src/sgml/ref/alter_publication.sgml

2.
Probably need to mention ALL SEQUENCES now too?

======
src/backend/commands/publicationcmds.c

3.
+/* CREATE PUBLICATION default values for flags and publication parameters */
+#define PUB_DEFAULT_ACTION_INSERT true
+#define PUB_DEFAULT_ACTION_UPDATE true
+#define PUB_DEFAULT_ACTION_DELETE true
+#define PUB_DEFAULT_ACTION_TRUNCATE true
+#define PUB_DEFAULT_VIA_ROOT false
+#define PUB_DEFAULT_ALL_TABLES false
+#define PUB_DEFAULT_GENCOLS PUBLISH_GENCOLS_NONE
+

Is it better to put all these in the catalog/pg_publication.h where
the catalog was defined?

~~~

AlterPublicationReset:

4.
+ /* Set ALL TABLES flag to false */
+ if (pubform->puballtables)
+ {
+ values[Anum_pg_publication_puballtables - 1] =
BoolGetDatum(PUB_DEFAULT_ALL_TABLES);
+ replaces[Anum_pg_publication_puballtables - 1] = true;
+ CacheInvalidateRelcacheAll();
+ }

Why not just do this anyway without the condition?

======
src/backend/parser/gram.y

6.
It would be nicer if all these grammar productions were coded in the
same order as the comment above them.

======
src/include/nodes/parsenodes.h

7.
AP_AddObjects, /* add objects to publication */
AP_DropObjects, /* remove objects from publication */
AP_SetObjects, /* set list of objects */
+ AP_ResetPublication, /* reset the publication */
} AlterPublicationAction;

It is already called "AlterPublicationAction", so maybe the enum value
only needs to be AP_Reset instead of AP_ResetPublication.

======
src/test/regress/expected/publication.out

8.
Expected output all needs rebasing now that there is a new "All
sequences" column.

======
src/test/regress/sql/publication.sql

9.
+ALTER PUBLICATION testpub_reset ADD TABLE pub_sch1.tbl1;
+
+-- Verify that associated tables are removed from the publication after RESET
+\dRp+ testpub_reset
+ALTER PUBLICATION testpub_reset RESET;
+\dRp+ testpub_reset
+

I felt the ADD TABLE should be after the comment.

And ditto for all the other test cases -- should be that same pattern too.

# comment about test
ALTER .. do something
\dRp+ pub
ALTER .. RESET
\dRp+ pub

~~~

10.
+-- Verify that associated schemas are reomved from the publication after RESET

typo: /reomved/removed/

~~~

11.
+-- Verify that only superuser can reset a publication
+ALTER PUBLICATION testpub_reset OWNER TO regress_publication_user2;
+SET ROLE regress_publication_user2;
+ALTER PUBLICATION testpub_reset RESET; -- fail - must be superuser
+SET ROLE regress_publication_user;
+

Perhaps this should be the first test?

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-10-30 06:04:05
Message-ID: CAHut+PtGu2j72yV_as_TVKfWr3ctd18svReGEx3xa=q5BtKyKA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Vignesh

Here are some review comments for the patch v24-0002.

These comments are just for the SGML docs. The patch needs a rebase so
I was unable to review the code.

======
Commit message

1.
A new column "prexcept" is added to table "pg_publication_rel", to maintain
the relations that the user wants to exclude from the publications.

~

/to maintain/to flag/

======
doc/src/sgml/logical-replication.sgml

2.
<para>
- To add tables to a publication, the user must have ownership rights on the
- table. To add all tables in schema to a publication, the user must be a
- superuser. To create a publication that publishes all tables or
all tables in
- schema automatically, the user must be a superuser.
+ To create a publication using FOR ALL TABLES or FOR ALL TABLES IN SCHEMA,
+ the user must be a superuser. To add ALL TABLES or ALL TABLES IN SCHEMA to a
+ publication, the user must be a superuser. To add tables to a publication,
+ the user must have ownership rights on the table.
</para>

Those "FOR ALL TABLES" etc are missing SGML markup.

======
doc/src/sgml/ref/alter_publication.sgml

3.
+ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
ADD ALL TABLES [ EXCEPT [ TABLE ] <replaceable
class="parameter">exception_object</replaceable> [, ... ] ]

and

+
+<phrase>where <replaceable
class="parameter">exception_object</replaceable> is:</phrase>
+
+ [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
+

It is not clear from the syntax which of these is possible.

... ADD ALL TABLES EXCEPT TABLE t1,t2,t3
... ADD ALL TABLES EXCEPT TABLE t1, TABLE t2, TABLES t3

IMO it is best put the "[TABLE]" within the exception_object:
[ TABLE ] [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]

Then both are possible, which is consistent with how "FOR TABLE" syntax works.

Furthermore, you might want later to say EXCLUDE SEQUENCE, so doing it
this way makes that possible.

~~~

4.
- Adding a table to a publication additionally requires owning that table.
- The <literal>ADD TABLES IN SCHEMA</literal>,
+ Adding a table to or excluding a table from a publication additionally
+ requires owning that table. The <literal>ADD ALL TABLES</literal>,

This wording seems a bit awkward. How are re-phrasing like:

SUGGESTION
Adding or excluding a table from a publication requires ownership of that table.

~~~

5.
- name to explicitly indicate that descendant tables are included.
+ name to explicitly indicate that descendant tables are affected. For
+ partitioned tables, <literal>ONLY</literal> donot have any effect.

typo: /donot/does not/

======
doc/src/sgml/ref/create_publication.sgml

6.
- [ FOR ALL TABLES
+ [ FOR ALL TABLES [ EXCEPT [ TABLE ] <replaceable
class="parameter">exception_object</replaceable> [, ... ] ]
| FOR <replaceable
class="parameter">publication_object</replaceable> [, ... ] ]
[ WITH ( <replaceable
class="parameter">publication_parameter</replaceable> [= <replaceable
class="parameter">value</replaceable>] [, ... ] ) ]

@@ -30,6 +30,10 @@ CREATE PUBLICATION <replaceable
class="parameter">name</replaceable>

TABLE [ ONLY ] <replaceable
class="parameter">table_name</replaceable> [ * ] [ ( <replaceable
class="parameter">column_name</replaceable> [, ... ] ) ] [ WHERE (
<replaceable class="parameter">expression</replaceable> ) ] [, ... ]
TABLES IN SCHEMA { <replaceable
class="parameter">schema_name</replaceable> | CURRENT_SCHEMA } [, ...
]
+
+<phrase>where <replaceable
class="parameter">exception_object</replaceable> is:</phrase>
+
+ [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]

Same review comment as #3 before.

I think it is clearer (and more flexible) to change the
exception_object to include [TABLE].
[ TABLE ] [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]

It also helps pave the way for any future EXCLUDE SEQUENCE feature.

~~~

7.
+ <para>
+ This clause specifies a list of tables to be excluded from the
+ publication. It can only be used with <literal>FOR ALL TABLES</literal>.
+ If <literal>ONLY</literal> is specified before the table name, only
+ that table is excluded from the publication. If
<literal>ONLY</literal> is
+ not specified, the table and all its descendant tables (if any) are
+ excluded. Optionally, <literal>*</literal> can be specified after the
+ table name to explicitly indicate that descendant tables are excluded.
+ This does not apply to a partitioned table, however. The partitioned
+ table or its partitions are excluded from the publication based on the
+ parameter <literal>publish_via_partition_root</literal>.
+ </para>
+ <para>
+ When <literal>publish_via_partition_root</literal> is set to
+ <literal>true</literal>, specifying a root partitioned table in
+ <literal>EXCEPT TABLE</literal> excludes it and all its partitions from
+ replication. Specifying a leaf partition has no effect, as its
changes are
+ still replicated via the root partitioned table. When
+ <literal>publish_via_partition_root</literal> is set to
+ <literal>false</literal>, specifying a partitioned table or non-leaf
+ partition has no effect, as changes are replicated via the leaf
+ partitions. Specifying a leaf partition excludes only that partition from
+ replication.
+ </para>

I felt that the second paragraph should be started with the sentence
"The partitioned table or its partitions are excluded...", so then
everything related to "publish_via_partition_root" is kept together.

~~~

8.
+ <para>
+ Create a publication that publishes all changes in all the tables except for
+ the changes of <structname>users</structname> and
+ <structname>departments</structname>:
+<programlisting>
+CREATE PUBLICATION mypublication FOR ALL TABLES EXCEPT users, departments;
+</programlisting>
+ </para>

The words "the changes of" are not needed, and you did not use that
wording in the ALTER PUBLICATION example.

======
doc/src/sgml/ref/psql-ref.sgml

9.
If <literal>x</literal> is appended to the command name, the results
are displayed in expanded mode.
- If <literal>+</literal> is appended to the command name, the tables and
- schemas associated with each publication are shown as well.
+ If <literal>+</literal> is appended to the command name, the tables,
+ excluded tables and schemas associated with each publication
are shown as
+ well.
</para>

/excluded tables and schemas/excluded tables, and schemas/

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-06 11:16:48
Message-ID: CANhcyEUh9ki36VTXyYf8UqUrfLX9ZhfP_f2LjpvvycgqWLQqqQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 30 Oct 2025 at 11:34, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Vignesh
>
> Here are some review comments for the patch v24-0002.
>
> These comments are just for the SGML docs. The patch needs a rebase so
> I was unable to review the code.
>
> ======
> Commit message
>
> 1.
> A new column "prexcept" is added to table "pg_publication_rel", to maintain
> the relations that the user wants to exclude from the publications.
>
> ~
>
> /to maintain/to flag/
>
> ======
> doc/src/sgml/logical-replication.sgml
>
> 2.
> <para>
> - To add tables to a publication, the user must have ownership rights on the
> - table. To add all tables in schema to a publication, the user must be a
> - superuser. To create a publication that publishes all tables or
> all tables in
> - schema automatically, the user must be a superuser.
> + To create a publication using FOR ALL TABLES or FOR ALL TABLES IN SCHEMA,
> + the user must be a superuser. To add ALL TABLES or ALL TABLES IN SCHEMA to a
> + publication, the user must be a superuser. To add tables to a publication,
> + the user must have ownership rights on the table.
> </para>
>
> Those "FOR ALL TABLES" etc are missing SGML markup.
>
> ======
> doc/src/sgml/ref/alter_publication.sgml
>
> 3.
> +ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
> ADD ALL TABLES [ EXCEPT [ TABLE ] <replaceable
> class="parameter">exception_object</replaceable> [, ... ] ]
>
> and
>
> +
> +<phrase>where <replaceable
> class="parameter">exception_object</replaceable> is:</phrase>
> +
> + [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
> +
>
> It is not clear from the syntax which of these is possible.
>
> ... ADD ALL TABLES EXCEPT TABLE t1,t2,t3
> ... ADD ALL TABLES EXCEPT TABLE t1, TABLE t2, TABLES t3
>
> IMO it is best put the "[TABLE]" within the exception_object:
> [ TABLE ] [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
>
> Then both are possible, which is consistent with how "FOR TABLE" syntax works.
>
> Furthermore, you might want later to say EXCLUDE SEQUENCE, so doing it
> this way makes that possible.
>
> ~~~
>
> 4.
> - Adding a table to a publication additionally requires owning that table.
> - The <literal>ADD TABLES IN SCHEMA</literal>,
> + Adding a table to or excluding a table from a publication additionally
> + requires owning that table. The <literal>ADD ALL TABLES</literal>,
>
> This wording seems a bit awkward. How are re-phrasing like:
>
> SUGGESTION
> Adding or excluding a table from a publication requires ownership of that table.
>
> ~~~
>
> 5.
> - name to explicitly indicate that descendant tables are included.
> + name to explicitly indicate that descendant tables are affected. For
> + partitioned tables, <literal>ONLY</literal> donot have any effect.
>
> typo: /donot/does not/
>
> ======
> doc/src/sgml/ref/create_publication.sgml
>
> 6.
> - [ FOR ALL TABLES
> + [ FOR ALL TABLES [ EXCEPT [ TABLE ] <replaceable
> class="parameter">exception_object</replaceable> [, ... ] ]
> | FOR <replaceable
> class="parameter">publication_object</replaceable> [, ... ] ]
> [ WITH ( <replaceable
> class="parameter">publication_parameter</replaceable> [= <replaceable
> class="parameter">value</replaceable>] [, ... ] ) ]
>
> @@ -30,6 +30,10 @@ CREATE PUBLICATION <replaceable
> class="parameter">name</replaceable>
>
> TABLE [ ONLY ] <replaceable
> class="parameter">table_name</replaceable> [ * ] [ ( <replaceable
> class="parameter">column_name</replaceable> [, ... ] ) ] [ WHERE (
> <replaceable class="parameter">expression</replaceable> ) ] [, ... ]
> TABLES IN SCHEMA { <replaceable
> class="parameter">schema_name</replaceable> | CURRENT_SCHEMA } [, ...
> ]
> +
> +<phrase>where <replaceable
> class="parameter">exception_object</replaceable> is:</phrase>
> +
> + [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
>
> Same review comment as #3 before.
>
> I think it is clearer (and more flexible) to change the
> exception_object to include [TABLE].
> [ TABLE ] [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
>
> It also helps pave the way for any future EXCLUDE SEQUENCE feature.
>
> ~~~
>
> 7.
> + <para>
> + This clause specifies a list of tables to be excluded from the
> + publication. It can only be used with <literal>FOR ALL TABLES</literal>.
> + If <literal>ONLY</literal> is specified before the table name, only
> + that table is excluded from the publication. If
> <literal>ONLY</literal> is
> + not specified, the table and all its descendant tables (if any) are
> + excluded. Optionally, <literal>*</literal> can be specified after the
> + table name to explicitly indicate that descendant tables are excluded.
> + This does not apply to a partitioned table, however. The partitioned
> + table or its partitions are excluded from the publication based on the
> + parameter <literal>publish_via_partition_root</literal>.
> + </para>
> + <para>
> + When <literal>publish_via_partition_root</literal> is set to
> + <literal>true</literal>, specifying a root partitioned table in
> + <literal>EXCEPT TABLE</literal> excludes it and all its partitions from
> + replication. Specifying a leaf partition has no effect, as its
> changes are
> + still replicated via the root partitioned table. When
> + <literal>publish_via_partition_root</literal> is set to
> + <literal>false</literal>, specifying a partitioned table or non-leaf
> + partition has no effect, as changes are replicated via the leaf
> + partitions. Specifying a leaf partition excludes only that partition from
> + replication.
> + </para>
>
> I felt that the second paragraph should be started with the sentence
> "The partitioned table or its partitions are excluded...", so then
> everything related to "publish_via_partition_root" is kept together.
>
> ~~~
>
> 8.
> + <para>
> + Create a publication that publishes all changes in all the tables except for
> + the changes of <structname>users</structname> and
> + <structname>departments</structname>:
> +<programlisting>
> +CREATE PUBLICATION mypublication FOR ALL TABLES EXCEPT users, departments;
> +</programlisting>
> + </para>
>
> The words "the changes of" are not needed, and you did not use that
> wording in the ALTER PUBLICATION example.
>
> ======
> doc/src/sgml/ref/psql-ref.sgml
>
> 9.
> If <literal>x</literal> is appended to the command name, the results
> are displayed in expanded mode.
> - If <literal>+</literal> is appended to the command name, the tables and
> - schemas associated with each publication are shown as well.
> + If <literal>+</literal> is appended to the command name, the tables,
> + excluded tables and schemas associated with each publication
> are shown as
> + well.
> </para>
>
> /excluded tables and schemas/excluded tables, and schemas/
>
Hi Peter, Vignesh

Thanks for reviewing the patches.
I have rebased the patches. I have modified the syntax for EXCEPT
TABLE (002) patch.
For example, now to exclude a table we need to specify like:
CREATE PUBLICATION pub1 FOR ALL TABLE EXCEPT TABLE (t1, t2);
We need to specify '()' around the table list.

This patchset is the only rebased version. I will address all the
comments in the next version of patch.

Thanks,
Shlok Kyal

Attachment Content-Type Size
v25-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 20.7 KB
v25-0003-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 85.5 KB
v25-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 91.0 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-07 03:41:24
Message-ID: CAHut+PsRD8ybC7MDBNBXXs=J2DuGiOc8kSePRyZc0s63U5f7tw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok.

Here are some review comments for the patch v25-0001 (RESET).

I belatedly saw that you said this is a rebase *only*, so does not yet
address any of the earlier review comments [1]. Anyway, below are a
few more comments that I did not report previously.

======
Commit message

1.
This patch adds a new RESET clause to ALTER PUBLICATION which will reset
the publication to the default state which includes resetting the publication
parameters, setting ALL TABLES flag to false and dropping the relations and
schemas that are associated with the publication.

~

1a.
/which includes.../. This includes...

~

1b.
Needs to also mention about ALL SEQUENCES

======
src/backend/commands/publicationcmds.c

AlterPublicationReset:

2.
+ /* Set ALL TABLES flag to false */
+ if (pubform->puballsequences)
+ {
+ values[Anum_pg_publication_puballsequences - 1] =
BoolGetDatum(PUB_DEFAULT_ALL_SEQUENCES);
+ replaces[Anum_pg_publication_puballsequences - 1] = true;
+ }

The comment should say ALL SEQUENCES.

======
[1] my review of v24-0001
https://www.postgresql.org/message-id/CAHut%2BPvoOVo%3D_O-sG8wNaLRBPSD%2B6S%3D4PXOH2r%3DyKTxbpAbHkg%40mail.gmail.com

Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-07 04:04:29
Message-ID: CAHut+Pt+E811KJA=KB3yaA+bc_aopptF-MW6Dx+xOv=hPnT3vA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok.

This is a general comment about the content of these patches.

IIUC, the v25* patches currently are currently arranged like this:

0001
- New command ALTER PUBLICATION pubname RESET;
0002
- Add new command: ALTER PUBLICATION pub_name ADD ALL TABLES;
- Enhance existing CREATE and the new ALTER syntax for EXCEPT tables
0003
- Enhance existing CREATE and ALTER syntax for EXCEPT col_list

~~~

IMO it is a bug that the ALTER PUBLICATION pub_name ADD/SET ALL TABLES
command does not already exist as a supported command. And, that is
independent of anything else you are implementing here like RESET or
EXCEPT.

Therefore, I think that one should be 1st in your patchset; The EXCEPT
stuff then just becomes enhancements to existing syntax, which would
give a cleaner separation of logic.

So, I am suggesting there should be 4 patches instead of 3. e.g.

SUGGESTION
0001 - New command: ALTER PUBLICATION pub_name ADD/SET ALL TABLES;
0002 - New command: ALTER PUBLICATION pubname RESET;
0003 - Enhance existing CREATE/ALTER syntax for EXCEPT tables
0004 - Enhance existing CREATE/ALTER syntax for EXCEPT col_list

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-07 06:06:04
Message-ID: CAHut+Pv96u0VciuSx2B99jDHEvn7svVJynCmw-qYb=z4Kc2knA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok.

Some questions for the patch v25-0002 (EXCEPT tables)

======
doc/src/sgml/ref/alter_publication.sgml

1.
+ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
ADD ALL TABLES [ EXCEPT [ TABLE ] ( <replaceable
class="parameter">exception_object</replaceable> [, ... ] ) ]

You can do both ADD/SET the <publication_object>, so really there
should be an ADD/SET ALL TABLES command as well, right?

~~~

2.
What was your reason for changing the syntax?
AFAICT those added "( )" are not strictly necessary, so I just
wondered your reason.

For example, we do not have any "( )" for <publication_object> [,...].
It is: ALTER PUBLICATION name ADD publication_object [, ...]
Not: ALTER PUBLICATION name ADD (publication_object [, ...])

So in the same way we could have EXCEPT syntax like that:
ALTER PUBLICATION name ADD ALL TABLES [EXCEPT <table_exception_object> [, ...]]
Where table_exception_object is: [ TABLE ] [ ONLY ] table_name [ * ]

Currently, if the user just wants to exclude a single table they must do:
ALTER PUBLICATION name ADD ALL TABLES EXCEPT (t1);
instead of just ALTER PUBLICATION name ADD ALL TABLES EXCEPT t1;

~~~

3.
BTW, I think you may need to consider a <table_exception_object>
instead of a generic name like <exception_object>, because in the
future if we EXCEPT SEQUENCES the <exception_object> name may be not
appropriate because things like [ONLY] and [*] are not applicable for
sequences.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-11 10:20:36
Message-ID: CANhcyEWGiWwGt1-v6d9bCAae9Np7cNPt+iRV9PXBZ0z=75XEVw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 7 Nov 2025 at 11:36, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok.
>
> Some questions for the patch v25-0002 (EXCEPT tables)
>
> ======
> doc/src/sgml/ref/alter_publication.sgml
>
> 1.
> +ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
> ADD ALL TABLES [ EXCEPT [ TABLE ] ( <replaceable
> class="parameter">exception_object</replaceable> [, ... ] ) ]
>
> You can do both ADD/SET the <publication_object>, so really there
> should be an ADD/SET ALL TABLES command as well, right?
>
These patches only added the ADD ALL TABLES command. I think once the
ADD ALL TABLES patch is committed, we can add the syntax SET ALL
TABLES.

> ~~~
>
> 2.
> What was your reason for changing the syntax?
> AFAICT those added "( )" are not strictly necessary, so I just
> wondered your reason.
>
> For example, we do not have any "( )" for <publication_object> [,...].
> It is: ALTER PUBLICATION name ADD publication_object [, ...]
> Not: ALTER PUBLICATION name ADD (publication_object [, ...])
>
> So in the same way we could have EXCEPT syntax like that:
> ALTER PUBLICATION name ADD ALL TABLES [EXCEPT <table_exception_object> [, ...]]
> Where table_exception_object is: [ TABLE ] [ ONLY ] table_name [ * ]
>
> Currently, if the user just wants to exclude a single table they must do:
> ALTER PUBLICATION name ADD ALL TABLES EXCEPT (t1);
> instead of just ALTER PUBLICATION name ADD ALL TABLES EXCEPT t1;
>
With recent commit now we support
CREATE PUBLICATION .. FOR ALL TABLES, ALL SEQUENCES.

Now when I am trying to support "FOR ALL TABLE EXCEPT t1, t2" , I am
getting a conflict when compiling this grammar.
For example
CREATE PUBLICATION .. FOR ALL TABLES EXCEPT t1, ...
After this comma, bison is giving conflict because it is not able to
figure whether to pick
ExceptPublicationObjSpec or a PublicationAllObjSpec.
So to handle this I introduced brackets around the table list.
And to make ALTER PUBLICATION similar to CREATE PUBLICATION, I have
added the same syntax for it.

So current syntax for CREATE/ALTER PUBLICATION is like:
CREATE PUBLICATION ... ALL TABLES EXCEPT TABLE(t1, t2, t3);
ALTER PUBLICATION ... ADD ALL TABLES EXCEPT TABLE(t1, t2, t3);

> ~~~
>
> 3.
> BTW, I think you may need to consider a <table_exception_object>
> instead of a generic name like <exception_object>, because in the
> future if we EXCEPT SEQUENCES the <exception_object> name may be not
> appropriate because things like [ONLY] and [*] are not applicable for
> sequences.
Fixed

I have attached the latest patch here.
I have also addressed the comments for [1], [2].

[1]: https://www.postgresql.org/message-id/CALDaNm0xDv96F%2B5LzcJYV6RC3Jg%2BRtdUqpQ-zoauwq3woTFzmQ%40mail.gmail.com
[2]: https://www.postgresql.org/message-id/CAHut+PsRD8ybC7MDBNBXXs=J2DuGiOc8kSePRyZc0s63U5f7tw@mail.gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v26-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 22.1 KB
v26-0003-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 77.1 KB
v26-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 82.8 KB

From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-11 10:22:01
Message-ID: CANhcyEWwC834Sagf-jQ76_xGZsa+LDiLmQdi5a+8J2tJcD0e9w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 7 Nov 2025 at 09:34, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok.
>
> This is a general comment about the content of these patches.
>
> IIUC, the v25* patches currently are currently arranged like this:
>
> 0001
> - New command ALTER PUBLICATION pubname RESET;
> 0002
> - Add new command: ALTER PUBLICATION pub_name ADD ALL TABLES;
> - Enhance existing CREATE and the new ALTER syntax for EXCEPT tables
> 0003
> - Enhance existing CREATE and ALTER syntax for EXCEPT col_list
>
> ~~~
>
> IMO it is a bug that the ALTER PUBLICATION pub_name ADD/SET ALL TABLES
> command does not already exist as a supported command. And, that is
> independent of anything else you are implementing here like RESET or
> EXCEPT.
>
> Therefore, I think that one should be 1st in your patchset; The EXCEPT
> stuff then just becomes enhancements to existing syntax, which would
> give a cleaner separation of logic.
>
> So, I am suggesting there should be 4 patches instead of 3. e.g.
>
> SUGGESTION
> 0001 - New command: ALTER PUBLICATION pub_name ADD/SET ALL TABLES;
> 0002 - New command: ALTER PUBLICATION pubname RESET;
> 0003 - Enhance existing CREATE/ALTER syntax for EXCEPT tables
> 0004 - Enhance existing CREATE/ALTER syntax for EXCEPT col_list
>
I read the previous conversation in the thread. And got an
understanding that RESET was introduced so that we can have a way to
remove 'EXCEPT TABLE' from a publication and after RESET we can use
'ADD ALL TABLES [EXCEPT]' to alter the list of EXCEPT TABLE. So I
prefer to keep 'ALTER PUBLICATION .. RESET' as the first patch.
I think since 'ADD ALL TABLES' serves our current purpose. We can add
the syntax 'SET ALL TABLES' once 'ADD ALL TABLES' is in committed or
in committable shape.

Thanks,
Shlok Kyal


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-11 10:24:06
Message-ID: CANhcyEUSQDKgu6-8rPZcy5Uzyaqt+0qTyTzp9KiVV=m-2RnVUQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 24 Oct 2025 at 06:41, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Vignesh,
>
> I had a look at patch v24-0001.
>
> FYI -- a rebase is needed
>
> [postgres(at)CentOS7-x64 oss_postgres_misc]$ git apply
> ../patches_misc/v24-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch
> error: patch failed: doc/src/sgml/ref/alter_publication.sgml:69
> error: doc/src/sgml/ref/alter_publication.sgml: patch does not apply
>
> Here are some other review comments:
>
> ======
>
> 1.
> There seems to be some basic omission of the ALTER PUBLICATION in that
> it does not support "ALL TABLES" as a publication_object.
>
> Therefore, if you have:
> CREATE PUBLICATION mypub FOR ALL TABLES;
>
> and then you do:
> ALTER PUBLICATION mypub RESET;
>
> There seems to be no way to restore mpub to be an ALL TABLES publication again!
>
> ~~~
>
> I think if you are going to implement a RESET, then you also need a
> way to get back to what you had before you did the reset. So you'll
> also need to implement the ALTER PUBLICATION mypub SET ALL TABLES;
>
> IMO, supporting "SET ALL TABLES" should be your new 0001 patch
> because AFAIK, this situation already exists if the user had created
> an "empty" publication:
> CREATE PUBLICATION myemptypub;
>
With current patches we can add ALL TABLES to a publication using "ADD
ALL TABLES"
I think once the ADD ALL TABLES patch is committed, we can add SET ALL TABLES.

> ======
> doc/src/sgml/ref/alter_publication.sgml
>
> 2.
> Probably need to mention ALL SEQUENCES now too?
>
> ======
> src/backend/commands/publicationcmds.c
>
> 3.
> +/* CREATE PUBLICATION default values for flags and publication parameters */
> +#define PUB_DEFAULT_ACTION_INSERT true
> +#define PUB_DEFAULT_ACTION_UPDATE true
> +#define PUB_DEFAULT_ACTION_DELETE true
> +#define PUB_DEFAULT_ACTION_TRUNCATE true
> +#define PUB_DEFAULT_VIA_ROOT false
> +#define PUB_DEFAULT_ALL_TABLES false
> +#define PUB_DEFAULT_GENCOLS PUBLISH_GENCOLS_NONE
> +
>
> Is it better to put all these in the catalog/pg_publication.h where
> the catalog was defined?
>
> ~~~
>
> AlterPublicationReset:
>
> 4.
> + /* Set ALL TABLES flag to false */
> + if (pubform->puballtables)
> + {
> + values[Anum_pg_publication_puballtables - 1] =
> BoolGetDatum(PUB_DEFAULT_ALL_TABLES);
> + replaces[Anum_pg_publication_puballtables - 1] = true;
> + CacheInvalidateRelcacheAll();
> + }
>
> Why not just do this anyway without the condition?
>
> ======
> src/backend/parser/gram.y
>
> 6.
> It would be nicer if all these grammar productions were coded in the
> same order as the comment above them.
>
> ======
> src/include/nodes/parsenodes.h
>
> 7.
> AP_AddObjects, /* add objects to publication */
> AP_DropObjects, /* remove objects from publication */
> AP_SetObjects, /* set list of objects */
> + AP_ResetPublication, /* reset the publication */
> } AlterPublicationAction;
>
> It is already called "AlterPublicationAction", so maybe the enum value
> only needs to be AP_Reset instead of AP_ResetPublication.
>
>
> ======
> src/test/regress/expected/publication.out
>
> 8.
> Expected output all needs rebasing now that there is a new "All
> sequences" column.
>
> ======
> src/test/regress/sql/publication.sql
>
> 9.
> +ALTER PUBLICATION testpub_reset ADD TABLE pub_sch1.tbl1;
> +
> +-- Verify that associated tables are removed from the publication after RESET
> +\dRp+ testpub_reset
> +ALTER PUBLICATION testpub_reset RESET;
> +\dRp+ testpub_reset
> +
>
> I felt the ADD TABLE should be after the comment.
>
> And ditto for all the other test cases -- should be that same pattern too.
>
> # comment about test
> ALTER .. do something
> \dRp+ pub
> ALTER .. RESET
> \dRp+ pub
>
> ~~~
>
> 10.
> +-- Verify that associated schemas are reomved from the publication after RESET
>
> typo: /reomved/removed/
>
> ~~~
>
> 11.
> +-- Verify that only superuser can reset a publication
> +ALTER PUBLICATION testpub_reset OWNER TO regress_publication_user2;
> +SET ROLE regress_publication_user2;
> +ALTER PUBLICATION testpub_reset RESET; -- fail - must be superuser
> +SET ROLE regress_publication_user;
> +
>
> Perhaps this should be the first test?
>
> ======

I have addressed the remaining comments in the latest v26 patch [1].
[1]: https://www.postgresql.org/message-id/CANhcyEWGiWwGt1-v6d9bCAae9Np7cNPt%2BiRV9PXBZ0z%3D75XEVw%40mail.gmail.com

Thanks,
Shlok Kyal


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-11 10:24:29
Message-ID: CANhcyEUmEpYXgizXd0BPehPKSzQg3n4zkiy5rbb5+hx4dbjybw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 30 Oct 2025 at 11:34, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Vignesh
>
> Here are some review comments for the patch v24-0002.
>
> These comments are just for the SGML docs. The patch needs a rebase so
> I was unable to review the code.
>
> ======
> Commit message
>
> 1.
> A new column "prexcept" is added to table "pg_publication_rel", to maintain
> the relations that the user wants to exclude from the publications.
>
> ~
>
> /to maintain/to flag/
>
> ======
> doc/src/sgml/logical-replication.sgml
>
> 2.
> <para>
> - To add tables to a publication, the user must have ownership rights on the
> - table. To add all tables in schema to a publication, the user must be a
> - superuser. To create a publication that publishes all tables or
> all tables in
> - schema automatically, the user must be a superuser.
> + To create a publication using FOR ALL TABLES or FOR ALL TABLES IN SCHEMA,
> + the user must be a superuser. To add ALL TABLES or ALL TABLES IN SCHEMA to a
> + publication, the user must be a superuser. To add tables to a publication,
> + the user must have ownership rights on the table.
> </para>
>
> Those "FOR ALL TABLES" etc are missing SGML markup.
>
> ======
> doc/src/sgml/ref/alter_publication.sgml
>
> 3.
> +ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
> ADD ALL TABLES [ EXCEPT [ TABLE ] <replaceable
> class="parameter">exception_object</replaceable> [, ... ] ]
>
> and
>
> +
> +<phrase>where <replaceable
> class="parameter">exception_object</replaceable> is:</phrase>
> +
> + [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
> +
>
> It is not clear from the syntax which of these is possible.
>
> ... ADD ALL TABLES EXCEPT TABLE t1,t2,t3
> ... ADD ALL TABLES EXCEPT TABLE t1, TABLE t2, TABLES t3
>
> IMO it is best put the "[TABLE]" within the exception_object:
> [ TABLE ] [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
>
> Then both are possible, which is consistent with how "FOR TABLE" syntax works.
>
> Furthermore, you might want later to say EXCLUDE SEQUENCE, so doing it
> this way makes that possible.
>
Recently a commit was pushed which allowed use of ALL SEQUENCES
syntax. Due to it, I have updated the syntax to
CREATE PUBLICATION ... ALL TABLES EXCEPT TABLE(t1, t2, t3);

For ALTER PUBLICATION to have a similar syntax. I have updated it to
have syntax like:
ALTER PUBLICATION ... ADD ALL TABLES EXCEPT TABLE(t1, t2, t3);

I think in the future we can extend the syntax for sequences like:
ALL SEQUENCES EXCEPT(s1, s2, s3).

See [1] for more info.

> ~~~
>
> 4.
> - Adding a table to a publication additionally requires owning that table.
> - The <literal>ADD TABLES IN SCHEMA</literal>,
> + Adding a table to or excluding a table from a publication additionally
> + requires owning that table. The <literal>ADD ALL TABLES</literal>,
>
> This wording seems a bit awkward. How are re-phrasing like:
>
> SUGGESTION
> Adding or excluding a table from a publication requires ownership of that table.
>
> ~~~
>
> 5.
> - name to explicitly indicate that descendant tables are included.
> + name to explicitly indicate that descendant tables are affected. For
> + partitioned tables, <literal>ONLY</literal> donot have any effect.
>
> typo: /donot/does not/
>
> ======
> doc/src/sgml/ref/create_publication.sgml
>
> 6.
> - [ FOR ALL TABLES
> + [ FOR ALL TABLES [ EXCEPT [ TABLE ] <replaceable
> class="parameter">exception_object</replaceable> [, ... ] ]
> | FOR <replaceable
> class="parameter">publication_object</replaceable> [, ... ] ]
> [ WITH ( <replaceable
> class="parameter">publication_parameter</replaceable> [= <replaceable
> class="parameter">value</replaceable>] [, ... ] ) ]
>
> @@ -30,6 +30,10 @@ CREATE PUBLICATION <replaceable
> class="parameter">name</replaceable>
>
> TABLE [ ONLY ] <replaceable
> class="parameter">table_name</replaceable> [ * ] [ ( <replaceable
> class="parameter">column_name</replaceable> [, ... ] ) ] [ WHERE (
> <replaceable class="parameter">expression</replaceable> ) ] [, ... ]
> TABLES IN SCHEMA { <replaceable
> class="parameter">schema_name</replaceable> | CURRENT_SCHEMA } [, ...
> ]
> +
> +<phrase>where <replaceable
> class="parameter">exception_object</replaceable> is:</phrase>
> +
> + [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
>
> Same review comment as #3 before.
>
> I think it is clearer (and more flexible) to change the
> exception_object to include [TABLE].
> [ TABLE ] [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
>
> It also helps pave the way for any future EXCLUDE SEQUENCE feature.
>
See #3 before
.
> ~~~
>
> 7.
> + <para>
> + This clause specifies a list of tables to be excluded from the
> + publication. It can only be used with <literal>FOR ALL TABLES</literal>.
> + If <literal>ONLY</literal> is specified before the table name, only
> + that table is excluded from the publication. If
> <literal>ONLY</literal> is
> + not specified, the table and all its descendant tables (if any) are
> + excluded. Optionally, <literal>*</literal> can be specified after the
> + table name to explicitly indicate that descendant tables are excluded.
> + This does not apply to a partitioned table, however. The partitioned
> + table or its partitions are excluded from the publication based on the
> + parameter <literal>publish_via_partition_root</literal>.
> + </para>
> + <para>
> + When <literal>publish_via_partition_root</literal> is set to
> + <literal>true</literal>, specifying a root partitioned table in
> + <literal>EXCEPT TABLE</literal> excludes it and all its partitions from
> + replication. Specifying a leaf partition has no effect, as its
> changes are
> + still replicated via the root partitioned table. When
> + <literal>publish_via_partition_root</literal> is set to
> + <literal>false</literal>, specifying a partitioned table or non-leaf
> + partition has no effect, as changes are replicated via the leaf
> + partitions. Specifying a leaf partition excludes only that partition from
> + replication.
> + </para>
>
> I felt that the second paragraph should be started with the sentence
> "The partitioned table or its partitions are excluded...", so then
> everything related to "publish_via_partition_root" is kept together.
>
> ~~~
>
> 8.
> + <para>
> + Create a publication that publishes all changes in all the tables except for
> + the changes of <structname>users</structname> and
> + <structname>departments</structname>:
> +<programlisting>
> +CREATE PUBLICATION mypublication FOR ALL TABLES EXCEPT users, departments;
> +</programlisting>
> + </para>
>
> The words "the changes of" are not needed, and you did not use that
> wording in the ALTER PUBLICATION example.
>
> ======
> doc/src/sgml/ref/psql-ref.sgml
>
> 9.
> If <literal>x</literal> is appended to the command name, the results
> are displayed in expanded mode.
> - If <literal>+</literal> is appended to the command name, the tables and
> - schemas associated with each publication are shown as well.
> + If <literal>+</literal> is appended to the command name, the tables,
> + excluded tables and schemas associated with each publication
> are shown as
> + well.
> </para>
>
> /excluded tables and schemas/excluded tables, and schemas/
>

I addressed the remaining comments in the latest v26 patch [1].
[1]:https://www.postgresql.org/message-id/CANhcyEWGiWwGt1-v6d9bCAae9Np7cNPt%2BiRV9PXBZ0z%3D75XEVw%40mail.gmail.com

Thanks,
Shlok Kyal


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-13 06:08:17
Message-ID: CANhcyEWAQHtUfgNPA2m-+okEh7pXaK5irBm+yzyNVJXL2LUTXw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, 11 Nov 2025 at 15:50, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> On Fri, 7 Nov 2025 at 11:36, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >
> > Hi Shlok.
> >
> > Some questions for the patch v25-0002 (EXCEPT tables)
> >
> > ======
> > doc/src/sgml/ref/alter_publication.sgml
> >
> > 1.
> > +ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
> > ADD ALL TABLES [ EXCEPT [ TABLE ] ( <replaceable
> > class="parameter">exception_object</replaceable> [, ... ] ) ]
> >
> > You can do both ADD/SET the <publication_object>, so really there
> > should be an ADD/SET ALL TABLES command as well, right?
> >
> These patches only added the ADD ALL TABLES command. I think once the
> ADD ALL TABLES patch is committed, we can add the syntax SET ALL
> TABLES.
>
> > ~~~
> >
> > 2.
> > What was your reason for changing the syntax?
> > AFAICT those added "( )" are not strictly necessary, so I just
> > wondered your reason.
> >
> > For example, we do not have any "( )" for <publication_object> [,...].
> > It is: ALTER PUBLICATION name ADD publication_object [, ...]
> > Not: ALTER PUBLICATION name ADD (publication_object [, ...])
> >
> > So in the same way we could have EXCEPT syntax like that:
> > ALTER PUBLICATION name ADD ALL TABLES [EXCEPT <table_exception_object> [, ...]]
> > Where table_exception_object is: [ TABLE ] [ ONLY ] table_name [ * ]
> >
> > Currently, if the user just wants to exclude a single table they must do:
> > ALTER PUBLICATION name ADD ALL TABLES EXCEPT (t1);
> > instead of just ALTER PUBLICATION name ADD ALL TABLES EXCEPT t1;
> >
> With recent commit now we support
> CREATE PUBLICATION .. FOR ALL TABLES, ALL SEQUENCES.
>
> Now when I am trying to support "FOR ALL TABLE EXCEPT t1, t2" , I am
> getting a conflict when compiling this grammar.
> For example
> CREATE PUBLICATION .. FOR ALL TABLES EXCEPT t1, ...
> After this comma, bison is giving conflict because it is not able to
> figure whether to pick
> ExceptPublicationObjSpec or a PublicationAllObjSpec.
> So to handle this I introduced brackets around the table list.
> And to make ALTER PUBLICATION similar to CREATE PUBLICATION, I have
> added the same syntax for it.
>
> So current syntax for CREATE/ALTER PUBLICATION is like:
> CREATE PUBLICATION ... ALL TABLES EXCEPT TABLE(t1, t2, t3);
> ALTER PUBLICATION ... ADD ALL TABLES EXCEPT TABLE(t1, t2, t3);
>
> > ~~~
> >
> > 3.
> > BTW, I think you may need to consider a <table_exception_object>
> > instead of a generic name like <exception_object>, because in the
> > future if we EXCEPT SEQUENCES the <exception_object> name may be not
> > appropriate because things like [ONLY] and [*] are not applicable for
> > sequences.
> Fixed
>
> I have attached the latest patch here.
> I have also addressed the comments for [1], [2].
>
> [1]: https://www.postgresql.org/message-id/CALDaNm0xDv96F%2B5LzcJYV6RC3Jg%2BRtdUqpQ-zoauwq3woTFzmQ%40mail.gmail.com
> [2]: https://www.postgresql.org/message-id/CAHut+PsRD8ybC7MDBNBXXs=J2DuGiOc8kSePRyZc0s63U5f7tw@mail.gmail.com
>

The patches needed a rebase. Here are the rebased patches.

Thanks,
Shlok Kyal

Attachment Content-Type Size
v27-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 22.1 KB
v27-0003-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 77.1 KB
v27-0002-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 83.0 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-14 06:44:43
Message-ID: CAHut+PuzcKXheZwgNvDJkwK5txd1kzNRxCmcJcbr=_9mGHjKtA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok.

Some review comments for patch v27-0001.

======
doc/src/sgml/ref/alter_publication.sgml

1.
+ <para>
+ The <literal>RESET</literal> clause will reset the publication to
the default
+ state. This includes resetting all publication parameters, setting the
+ <literal>ALL TABLES</literal> and <literal>ALL SEQUENCES</literal> flags to
+ <literal>false</literal>, and removing all associated tables and
schemas from
+ the publication.
</para>

It would be better to give references to the actual
pg_publication.puballtables and .puballsequences flag fields [1]
instead of vaguely calling them the "<literal>ALL TABLES</literal> and
<literal>ALL SEQUENCES</literal> flags".

======
src/backend/commands/publicationcmds.c

AlterPublicationReset:

2.
+ if (pubform->puballtables)
+ CacheInvalidateRelcacheAll();

Does that also need to check ->puballsequences?

======
src/test/regress/sql/publication.sql

3.
If you want to, you can easily combine many of these test cases and
verify them in one go instead of separate ALTER/RESET for every kind
of flag.

~~~

4.
+-- Verify that 'ALL TABLES' flag is reset

Missing test to check the 'ALL SEQUENCES' flag gets reset?

======
[1] https://www.postgresql.org/docs/devel/catalog-pg-publication.html

Kind Regards,
Peter Smith.
Fujitsu Australia.


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-17 06:04:47
Message-ID: CAHut+PvqCxY43-+=ZmYJj_qw7wJMRsrpiEuz6hVvJ3Wz-L+wzg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Nov 11, 2025 at 9:22 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> On Fri, 7 Nov 2025 at 09:34, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >
> > Hi Shlok.
> >
> > This is a general comment about the content of these patches.
> >
> > IIUC, the v25* patches currently are currently arranged like this:
> >
> > 0001
> > - New command ALTER PUBLICATION pubname RESET;
> > 0002
> > - Add new command: ALTER PUBLICATION pub_name ADD ALL TABLES;
> > - Enhance existing CREATE and the new ALTER syntax for EXCEPT tables
> > 0003
> > - Enhance existing CREATE and ALTER syntax for EXCEPT col_list
> >
> > ~~~
> >
> > IMO it is a bug that the ALTER PUBLICATION pub_name ADD/SET ALL TABLES
> > command does not already exist as a supported command. And, that is
> > independent of anything else you are implementing here like RESET or
> > EXCEPT.
> >
> > Therefore, I think that one should be 1st in your patchset; The EXCEPT
> > stuff then just becomes enhancements to existing syntax, which would
> > give a cleaner separation of logic.
> >
> > So, I am suggesting there should be 4 patches instead of 3. e.g.
> >
> > SUGGESTION
> > 0001 - New command: ALTER PUBLICATION pub_name ADD/SET ALL TABLES;
> > 0002 - New command: ALTER PUBLICATION pubname RESET;
> > 0003 - Enhance existing CREATE/ALTER syntax for EXCEPT tables
> > 0004 - Enhance existing CREATE/ALTER syntax for EXCEPT col_list
> >
> I read the previous conversation in the thread. And got an
> understanding that RESET was introduced so that we can have a way to
> remove 'EXCEPT TABLE' from a publication and after RESET we can use
> 'ADD ALL TABLES [EXCEPT]' to alter the list of EXCEPT TABLE. So I
> prefer to keep 'ALTER PUBLICATION .. RESET' as the first patch.
> I think since 'ADD ALL TABLES' serves our current purpose. We can add
> the syntax 'SET ALL TABLES' once 'ADD ALL TABLES' is in committed or
> in committable shape.
>

Sure, you can defer the ALTER PUBLICATION ... SET ALL TABLES.

However, I still think that 'ALTER PUBLICATION ... ADD ALL TABLES' is
a self-contained new command that deserves to have its own *separate*
patch and tests and docs, etc.

IMO, patch 0002 is doing too much at once. It would be tidier (and
smaller and easier to review, etc) if you split 0002 to implement the
new 'ALTER PUBLICATION ... ADD ALL TABLES' separately, before
expanding on that to implement the EXCEPT part: 'ALTER PUBLICATION ...
ADD ALL TABLES [EXCEPT ...]'.

======
Kind Regards,
Peter Smith.
Fujitsu Australia.


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-17 06:12:24
Message-ID: CAHut+PtRzCD4-0894cutkU_h8cPNtosN0_oSHn2iAKEfg2ENOQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok,

Here are a few ad-hoc comments for patch v27-0002.

======
doc/src/sgml/logical-replication.sgml

1.
<para>
- To add tables to a publication, the user must have ownership rights on the
- table. To add all tables in schema to a publication, the user must be a
- superuser. To create a publication that publishes all tables, all tables in
- schema, or all sequences automatically, the user must be a superuser.
+ To create a publication using <literal>FOR ALL TABLES</literal>,
+ <literal>FOR ALL SEQUENCES or <literal>FOR TABLES IN SCHEMA</literal>, the
+ user must be a superuser. To add <literal>ALL TABLES</literal> or
+ <literal>TABLES IN SCHEMA</literal> to a publication, the user must be a
+ superuser. To add tables to a publication, the user must have ownership
+ rights on the table.
</para>

Typo: Mismatched tags. "<literal>FOR ALL SEQUENCES or <literal>FOR
TABLES IN SCHEMA</literal>"

(The docs in v27-0002 cannot build because of this error)

======
src/backend/commands/publicationcmds.c

CheckPublicationDefValues:

2.
+/*
+ * Check if the publication has default values.
+ *
+ * Returns true if the publication satisfies all the following conditions:
+ * a) Publication is not set with "FOR ALL TABLES"
+ * b) Publication is having default publication parameter values
+ * c) Publication is not associated with schemas
+ * d) Publication is not associated with relations
+ */
+static bool
+CheckPublicationDefValues(HeapTuple tup)

Should a) also say "FOR ALL SEQUENCES"?

~~~

3.
What about checking defaults of other publication parameters, e.g.
publish_via_parttion_root and publish_generated_columns?

======
src/backend/parser/gram.y

4.
* TABLE table_name [, ...]
* TABLES IN SCHEMA schema_name [, ...]
*
+ * ALTER PUBLICATION name ADD ALL TABLES EXCEPT [TABLE] (table_name [, ...])
+ *
* ALTER PUBLICATION name RESET

The EXCEPT clause part should be optional.

======
src/bin/pg_dump/t/002_pg_dump.pl

5.
#
# Either "all_runs" should be set or there should be a "like" list,
# even if it is empty. (This makes the test more self-documenting.)
- if (!defined($tests{$test}->{all_runs})
+ if ( !defined($tests{$test}->{all_runs})

Is this just an accidental whitespace change?

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-17 07:51:57
Message-ID: CAHut+PuHn-hohA4OdEJz+Zfukfr41TvMTeTH7NwJ=wg1+94uNA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok,

A comment about patch v27-0003

======
doc/src/sgml/logical-replication.sgml

All references to tables "t1" and "t2" should use the <structname> tag
in the SGML. The current patch has broken this in multiple places:

e.g.
- Create a table <structname>t1</structname> to be used in the
following example.
+ Create tables <literal>t1</literal> and <literal>t2</literal> to be used in
+ the following example.

~~

e.g.
- table <structname>t1</structname> to reduce the number of columns
that will be
- replicated. Notice that the order of column names in the column list does
- not matter.
+ table <literal>t1</literal>, and another column list is defined for table
+ <literal>t2</literal> using the <literal>EXCEPT</literal> clause to reduce
+ the number of columns that will be replicated. Note that the
order of column
+ names in the column lists does not matter.

~~

e.g.
- On the subscriber node, create a table
<structname>t1</structname> which now
- only needs a subset of the columns that were on the publisher table
- <structname>t1</structname>, and also create the subscription
+ On the subscriber node, create tables <literal>t1</literal> and
+ <literal>t2</literal> which now only needs a subset of the columns that
+ were on the publisher tables <literal>t1</literal> and
+ <literal>t2</literal>, and also create the subscription

~~

e.g.
- On the publisher node, insert some rows to table
<structname>t1</structname>.
+ On the publisher node, insert some rows to tables <literal>t1</literal>
+ and <literal>t2</literal>

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-19 10:04:04
Message-ID: CANhcyEXCKPCAdoqBLAhxt64Nwf+7T52dd8daE3qvhBNTvro13Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 14 Nov 2025 at 12:15, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok.
>
> Some review comments for patch v27-0001.
>
> ======
> doc/src/sgml/ref/alter_publication.sgml
>
> 1.
> + <para>
> + The <literal>RESET</literal> clause will reset the publication to
> the default
> + state. This includes resetting all publication parameters, setting the
> + <literal>ALL TABLES</literal> and <literal>ALL SEQUENCES</literal> flags to
> + <literal>false</literal>, and removing all associated tables and
> schemas from
> + the publication.
> </para>
>
> It would be better to give references to the actual
> pg_publication.puballtables and .puballsequences flag fields [1]
> instead of vaguely calling them the "<literal>ALL TABLES</literal> and
> <literal>ALL SEQUENCES</literal> flags".
>
Fixed

> ======
> src/backend/commands/publicationcmds.c
>
> AlterPublicationReset:
>
> 2.
> + if (pubform->puballtables)
> + CacheInvalidateRelcacheAll();
>
> Does that also need to check ->puballsequences?
>
I think we call CacheInvalidateRelcacheAll to invalide the relsync
cache for the case of ALTER Publication. For sequences we do not build
RelSyncEntry.
Also I see there are other similar occurrences (such as
RemovePublicationById, AlterPublicationOptions) where we do not
invalidate cache if we modify all sequence publications.
So, I think we do not require this check for puballsequences.

> ======
> src/test/regress/sql/publication.sql
>
> 3.
> If you want to, you can easily combine many of these test cases and
> verify them in one go instead of separate ALTER/RESET for every kind
> of flag.
>
> ~~~
>
I agree. I have made the changes in the latest patch.

> 4.
> +-- Verify that 'ALL TABLES' flag is reset
>
> Missing test to check the 'ALL SEQUENCES' flag gets reset?
>
Added the test.

> ======
> [1] https://www.postgresql.org/docs/devel/catalog-pg-publication.html
>

I have also addressed the comments in [1], [2].

[1]: https://www.postgresql.org/message-id/CAHut%2BPtRzCD4-0894cutkU_h8cPNtosN0_oSHn2iAKEfg2ENOQ%40mail.gmail.com
[2]: https://www.postgresql.org/message-id/CAHut+PuHn-hohA4OdEJz+Zfukfr41TvMTeTH7NwJ=wg1+94uNA@mail.gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v28-0002-Support-ADD-ALL-TABLES-in-ALTER-PUBLICATION.patch application/octet-stream 16.8 KB
v28-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 17.7 KB
v28-0003-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 70.9 KB
v28-0004-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 77.2 KB

From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-19 10:05:05
Message-ID: CANhcyEU0suO77K1bcetk21iv197oDoB34yHSJB1QL0hApunnOQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 17 Nov 2025 at 11:35, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> On Tue, Nov 11, 2025 at 9:22 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > On Fri, 7 Nov 2025 at 09:34, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> > >
> > > Hi Shlok.
> > >
> > > This is a general comment about the content of these patches.
> > >
> > > IIUC, the v25* patches currently are currently arranged like this:
> > >
> > > 0001
> > > - New command ALTER PUBLICATION pubname RESET;
> > > 0002
> > > - Add new command: ALTER PUBLICATION pub_name ADD ALL TABLES;
> > > - Enhance existing CREATE and the new ALTER syntax for EXCEPT tables
> > > 0003
> > > - Enhance existing CREATE and ALTER syntax for EXCEPT col_list
> > >
> > > ~~~
> > >
> > > IMO it is a bug that the ALTER PUBLICATION pub_name ADD/SET ALL TABLES
> > > command does not already exist as a supported command. And, that is
> > > independent of anything else you are implementing here like RESET or
> > > EXCEPT.
> > >
> > > Therefore, I think that one should be 1st in your patchset; The EXCEPT
> > > stuff then just becomes enhancements to existing syntax, which would
> > > give a cleaner separation of logic.
> > >
> > > So, I am suggesting there should be 4 patches instead of 3. e.g.
> > >
> > > SUGGESTION
> > > 0001 - New command: ALTER PUBLICATION pub_name ADD/SET ALL TABLES;
> > > 0002 - New command: ALTER PUBLICATION pubname RESET;
> > > 0003 - Enhance existing CREATE/ALTER syntax for EXCEPT tables
> > > 0004 - Enhance existing CREATE/ALTER syntax for EXCEPT col_list
> > >
> > I read the previous conversation in the thread. And got an
> > understanding that RESET was introduced so that we can have a way to
> > remove 'EXCEPT TABLE' from a publication and after RESET we can use
> > 'ADD ALL TABLES [EXCEPT]' to alter the list of EXCEPT TABLE. So I
> > prefer to keep 'ALTER PUBLICATION .. RESET' as the first patch.
> > I think since 'ADD ALL TABLES' serves our current purpose. We can add
> > the syntax 'SET ALL TABLES' once 'ADD ALL TABLES' is in committed or
> > in committable shape.
> >
>
> Sure, you can defer the ALTER PUBLICATION ... SET ALL TABLES.
>
> However, I still think that 'ALTER PUBLICATION ... ADD ALL TABLES' is
> a self-contained new command that deserves to have its own *separate*
> patch and tests and docs, etc.
>
> IMO, patch 0002 is doing too much at once. It would be tidier (and
> smaller and easier to review, etc) if you split 0002 to implement the
> new 'ALTER PUBLICATION ... ADD ALL TABLES' separately, before
> expanding on that to implement the EXCEPT part: 'ALTER PUBLICATION ...
> ADD ALL TABLES [EXCEPT ...]'.

I agree with you.
I have split the 0002 patch. Now we have following patches

0001 - Add RESET clause to Alter Publication
0002 - Support ADD ALL TABLES in ALTER PUBLICATION
0003 - Skip publishing the tables specified in EXCEPT TABLE
0004 - Skip publishing the columns specified in FOR TABLE EXCEPT

I have attached the updated patch in [1].
[1]: https://www.postgresql.org/message-id/CANhcyEXCKPCAdoqBLAhxt64Nwf%2B7T52dd8daE3qvhBNTvro13Q%40mail.gmail.com

Thanks,
Shlok Kyal


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-20 01:55:16
Message-ID: CAHut+Pv4d9EAjDQiOHiu2BrYP3ZA-oJgsgGZdygBaZnWDR7sDA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok,

Some review comments for patch v28-0001.

======
src/backend/commands/publicationcmds.c

AlterPublicationReset:
1.
+ values[Anum_pg_publication_puballtables - 1] =
BoolGetDatum(PUB_DEFAULT_ALL_TABLES);
+ replaces[Anum_pg_publication_puballtables - 1] = true;
+
+ values[Anum_pg_publication_puballsequences - 1] =
BoolGetDatum(PUB_DEFAULT_ALL_SEQUENCES);
+ replaces[Anum_pg_publication_puballsequences - 1] = true;

The PUB_DEFAULT_xxx made sense for all the publication parameters, but
these are just flags that say if the ALL TABLES or ALL SEQUENCES
clauses are present in the command, so I'm not sure that "default"
macros are appropriate here.

e.g. it seems better to reset those using hardwired booleans:

values[Anum_pg_publication_puballtables - 1] = BoolGetDatum(false);
values[Anum_pg_publication_puballsequences - 1] = BoolGetDatum(false);

(This would also be consistent with what the function comment is saying)

======
src/include/catalog/pg_publication.h

2.
+/* default values for flags and publication parameters */
+#define PUB_DEFAULT_ACTION_INSERT true
+#define PUB_DEFAULT_ACTION_UPDATE true
+#define PUB_DEFAULT_ACTION_DELETE true
+#define PUB_DEFAULT_ACTION_TRUNCATE true
+#define PUB_DEFAULT_VIA_ROOT false
+#define PUB_DEFAULT_ALL_TABLES false
+#define PUB_DEFAULT_ALL_SEQUENCES false
+#define PUB_DEFAULT_GENCOLS PUBLISH_GENCOLS_NONE

As in the previous comment #1, I don't think we should define
PUB_DEFAULT_ALL_TABLES and PUB_DEFAULT_ALL_SEQUENCES. Also, change the
comment to remove the words "flags and".

======
src/test/regress/sql/publication.sql

3.
I don't think the parameter names should be written in uppercase
because that's not how they normally appear in the docs and examples.

~~~

4.
+-- Verify that 'ALL TABLES', 'ALL SEQUENCES' flag is reset

typo: /flag is reset/flags are reset/

~~~

5.
+-- Verify that associated tables, schemas and the publication parameters
+-- 'PUBLISH', 'PUBLISH_VIA_PARTITION_ROOT', and 'PUBLISH_GENERATED_COLUMNS'
+-- are removed from the publication after RESET

The comment makes it sound like parameters are "removed". Maybe some
rewording is needed.

SUGGESTION
Verify that a publication RESET removes the associated tables and
schemas, and sets default values for publication parameters 'publish',
'publish_via_partition_root', and 'publish_generated_columns'.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-20 06:24:12
Message-ID: CAHut+Pu50yWjMR5Mswhi6uVKQmn3hO9o0ocRAgXyUUf4cnVTwg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok.

Thanks for splitting the patches.

Here are some review comments for the new patch v28-0002 (ADD ALL TABLES).

======
Commit Message

1.
This patch adds support for using ADD ALL TABLES in ALTER PUBLICATION,
allowing an existing publication to be changed into an ALL TABLES
publication. This command is permitted only when the publication is
in its default state, meaning it has no tables or schemas added, its
ALL TABLES and ALL SEQUENCES flags are not set, and publication
options such as publish_via_root_partition, publish_generated_columns,
and publish are at their default values.

~

IMO, the restrictions for this new command are too severe:

e.g. If I already have a FOR ALL SEQUENCES publication, then I
expected it should be possible to ADD ALL TABLES to that as well,
right?

Likewise, why are we enforcing that the publication parameters must be
defaults? IOW, why is (i) below disallowed, but (ii) is allowed?

(i)
ALTER PUBLICATION pub SET (publish_generated_columns=stored);
ALTER PUBLICATION pub ADD ALL TABLES;

(ii)
ALTER PUBLICATION pub ADD ALL TABLES;
ALTER PUBLICATION pub SET (publish_generated_columns=stored);

======
doc/src/sgml/ref/alter_publication.sgml

Description:

2.
The "Description" part of this page is confusing because it was
referring to "The first three variants" and later "The fourth
variant". Now that the "ADD ALL TABLES" variant has been added, I
have lost track of what "variants" this description is talking about.
Those words should be replaced by something clearer. This could be an
ongoing issue if it is not worded differently because the same problem
will happen again, e.g. when more syntax gets added for ALL SEQUENCES,
etc.

~~~

3.
Note also that DROP TABLES IN SCHEMA will not drop any schema tables
that were specified using FOR TABLE/ ADD TABLE.

~

That sentence (above) is from the docs. Does that also need updating
now that there is ADD ALL TABLES?

======
src/backend/commands/publicationcmds.c

CheckPublicationDefValues:

4.
Is this function needed?

~~~

AlterPublication:

5.
+ if (stmt->for_all_tables)
+ {
+ bool isdefault = CheckPublicationDefValues(tup);
+
+ if (!isdefault)
+ ereport(ERROR,
+ errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("adding ALL TABLES requires the publication to have default
publication parameter values"),
+ errdetail("ALL TABLES or ALL SEQUENCES flag should not be set and no
tables/schemas should be associated."),
+ errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));
+
+ AlterPublicationSetAllTables(rel, tup);
+ }
+

Why do we need this self-imposed restriction?

======
src/include/nodes/parsenodes.h

6.
List *pubobjects; /* Optional list of publication objects */
+ bool for_all_tables; /* Special publication for all tables in db */
AlterPublicationAction action; /* What action to perform with the given
* objects */
} AlterPublicationStmt;

There is no such "FOR" syntax like ALTER PUBLICATION ... FOR ALL
TABLES, so I felt just 'puballtables' might be a better member name.

======
src/test/regress/sql/publication.sql

7.
Don't uppercase any of the publication parameters because they never
appear in the docs/examples like that.

~

8.
So that the last command is the one being tested, I felt that all the
test cases should be doing RESET *first* instead of last.

~~~

9.
You don't always need to use RESET. There should also be some tests
using an "empty" publication just to be sure it works. e.g

CREATE PUBLICATION pub_empty;
ALTER PUBLICATION pub_empty ADD ALL TABLES;

~~~

10.
As commented earlier, I felt the rules were too restrictive. So I
think some test cases can be removed.

~~~

11.
+-- Tests for ALTER PUBLICATION ... ADD ALL TABLES

~

I noticed there is a "--
======================================================" separator
between the major groups of tests.

11a. Should use this separator in patch 0001 for the RESET group of tests

11b. Should use this separator in patch 0002 for the ADD ALL TABLES
groups of tests

~~~

12.
+-- Can't add ALL TABLES to 'ALL TABLES' publication
+ALTER PUBLICATION testpub_reset ADD ALL TABLES;
+

This test case seems to belong earlier, near the 'FOR TABLE' and the
'TABLES IN SCHEMA' tests.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-21 06:55:37
Message-ID: CAHut+PsqV+dkPyYZ2BxWKBq7+TkrjCwBHBAQ3bHOSEChovD+ZA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok.

Here are some review comments for your patch v28-0003 (EXCEPT TABLE ...).

The review of this patch is a WIP. In this post I only looked at the test code.

======
.../t/037_rep_changes_except_table.pl

1.
+
+# Copyright (c) 2021-2025, PostgreSQL Global Development Group
+
+# Logical replication tests for except table publications

Use uppercase: /except table/EXCEPT TABLE/

~~~

2.
There are lots of test cases dedicated to partiion-table testing. I
felt a bigger comment separating these major groups might be helpful.

Something like:

-- ============================================
-- EXCEPT TABLE test cases for normal tables
-- ============================================

and

-- ============================================
-- EXCEPT TABLE test cases for partition tables
-- ============================================

~~~

3.
+# Initialize publisher node
...
+# Create subscriber node

Those 2 comments should be almost alike -- e.g. both should say
"Initialize" or both should say "Create".

~~~

4.
+# Test replication with publications created using FOR ALL TABLES EXCEPT TABLE
+# clause.
+# Create schemas and tables on publisher
+$node_publisher->safe_psql(
+ 'postgres', qq(
+ CREATE SCHEMA sch1;
+ CREATE TABLE sch1.tab1 AS SELECT generate_series(1,10) AS a;
+ CREATE TABLE public.tab1(a int);
+));
+

That first sentence ("Test replication with ...") is not needed here.
The is just repeating the purpose of the entire file, so that comment
can replace the one at the top of this file.

~~~

5.
+# Insert some data and verify that inserted data is not replicated

Be explicit that we are referring to the excluded table.

SUGGESTION (e.g.)
Verify that data inserted to the excluded table is not replcated.

~~~

6.
+# Alter publication to exclude data changes in public.tab1 and verify that
+# subscriber does not get the changed data for this table.
+$node_publisher->safe_psql(
+ 'postgres', qq(
+ ALTER PUBLICATION tap_pub_schema RESET;
+ ALTER PUBLICATION tap_pub_schema ADD ALL TABLES EXCEPT TABLE
(sch1.tab1, public.tab1);
+ INSERT INTO public.tab1 VALUES(generate_series(1,10));
+));
+$node_publisher->wait_for_catchup('tap_sub_schema');
+

It is not strictly needed for these tests, but do you think it makes
more sense to also do an ALTER SUBSCRIPTION ... REFRESH PUBLICATION;
whenever you change the publications?

~~~

7.
+# cleanup
+$node_publisher->safe_psql('postgres', "DROP PUBLICATION tap_pub_schema");
+$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION tap_sub_schema");
+
+

double-blank lines.

~~~

8.
I think it would be more helpful if the partition table test cases say
(in their comments) a lot more about the steps they are doing, and
what they expect the result to be. Sure, I can read all the code to
figure it out for each case, but it is better to know the test
intentions/expectations then verify they are doing the right thing.

~~~

9.
+ CREATE TABLE sch1.t1(a int) PARTITION BY RANGE(a);
+ CREATE TABLE sch1.part1 PARTITION OF sch1.t1 FOR VALUES FROM (0) TO (5);

Maybe create this table to have *multiple* partitions. It might be
interesting later to see what happens when you try to EXCEPT only one
of the partitions.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-24 07:32:39
Message-ID: CAHut+Pudi+9ssBR_Q_Fd29aGEu8s18OyKUGo5w5aKJK-2_c+8g@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Nov 21, 2025 at 5:55 PM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok.
>
> Here are some review comments for your patch v28-0003 (EXCEPT TABLE ...).
>
> The review of this patch is a WIP. In this post I only looked at the test code.
>

Here are my remaining review comments for patch v28-0003 (EXCEPT TABLE ...).

======
doc/src/sgml/ref/create_publication.sgml

1.
-ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
ADD ALL TABLES
+ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
ADD ALL TABLES [ EXCEPT [ TABLE ] ( <replaceable
class="parameter">table_exception_object</replaceable> [, ... ] ) ]

Why is that optional [TABLE] keyword needed?

I know PostGres commands sometimes have "noise" words in the syntax so
the command can be more English-like, but in this case, the
publication is a FOR ALL *TABLES* anyway, so I am not sure what the
benefit is of the user being able to say TABLE a 2nd time?

======
src/backend/catalog/pg_publication.c

2.
+ /*
+ * Check for partitions of partitioned table which are specified with
+ * EXCEPT clause and partitioned table is published with
+ * publish_via_partition_root = true.
+ */

I think you can just say "partitions" or "table partitions", but
"partitions of [a] partitioned table" seems overkill.

Also, "... and partitioned table is published with
publish_via_partition_root = true." seems too wordy. Isn't that just
the same as "... and publish_via_partition_root = true"

SUGGESTION
Check for when the publication says "EXCEPT TABLE (partition)" but
publish_via_partition_root = true.

~~~

3.
-/* Gets list of publication oids for a relation */
+/* Gets list of publication oids for a relation that matches the except_flag */
List *
-GetRelationPublications(Oid relid)
+GetRelationPublications(Oid relid, bool except_flag)
{
List *result = NIL;
CatCList *pubrellist;
@@ -765,7 +791,8 @@ GetRelationPublications(Oid relid)
HeapTuple tup = &pubrellist->members[i]->tuple;
Oid pubid = ((Form_pg_publication_rel) GETSTRUCT(tup))->prpubid;

- result = lappend_oid(result, pubid);
+ if (except_flag == ((Form_pg_publication_rel) GETSTRUCT(tup))->prexcept)
+ result = lappend_oid(result, pubid);
}

I was wondering if it might be better to return 2 lists from this
function (e.g. an included-list, and an excluded-list) instead of
passing the 'except_flag' like the current code. IIUC, you are mostly
calling this function twice to get 2 lists anyway, but returning 2
lists instead of 1, this function might be more efficient since it
will only process the publication loop once.

~~~

4.
/*
* Gets list of relation oids for a publication that matches the except_flag.
*
* This should only be used FOR TABLE publications, the FOR ALL TABLES/SEQUENCES
* should use GetAllPublicationRelations().
*/
List *
GetPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt,
bool except_flag)
Something doesn't seem right -- the function comment says we shouldn't
be calling the function for FOR ALL TABLES, but meanwhile, EXCEPT
TABLE is currently only implemented via FOR ALL TABLES. So it feels
contradictory. Maybe it is just the comment that needs updating?

~~~

5.
/*
* Gets list of relation oids for a publication that matches the except_flag.
*
* This should only be used FOR TABLE publications, the FOR ALL TABLES/SEQUENCES
* should use GetAllPublicationRelations().
*/
List *
GetPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt,
bool except_flag)
{
List *result;
Relation pubrelsrel;
ScanKeyData scankey;
SysScanDesc scan;
HeapTuple tup;

/* Find all publications associated with the relation. */
pubrelsrel = table_open(PublicationRelRelationId, AccessShareLock);

Existing bug? Isn't this a bogus comment?
/* Find all publications associated with the relation. */

Was that meant to be the other way around? -- e.g. Find all the
relations associated with the specified publication.

======
src/backend/commands/publicationcmds.c

6.
+ default:
+ /* shouldn't happen */
+ elog(ERROR, "invalid publication object type %d",
+ puballobj->pubobjtype);
+ break;

I think the ERROR is enough of a clue that it shouldn't happen. I felt
the comment was redundant.

~~~

ObjectsInPublicationToOids:

7.
case PUBLICATIONOBJ_TABLE:
+ pubobj->pubtable->except = false;
+ *rels = lappend(*rels, pubobj->pubtable);
+ break;
+ case PUBLICATIONOBJ_EXCEPT_TABLE:
+ pubobj->pubtable->except = true;
*rels = lappend(*rels, pubobj->pubtable);
break;
Those are very similar. How about combining like below?

case PUBLICATIONOBJ_TABLE:
case PUBLICATIONOBJ_EXCEPT_TABLE:
pubobj->pubtable->except = (pubobj->pubobjtype ==
PUBLICATIONOBJ_EXCEPT_TABLE);
*rels = lappend(*rels, pubobj->pubtable);
break;

~~

pub_contains_invalid_column:

8.
pub_contains_invalid_column(Oid pubid, Relation relation, List *ancestors,
bool pubviaroot, char pubgencols_type,
- bool *invalid_column_list,
+ bool puballtables, bool *invalid_column_list,
bool *invalid_gen_col)

The 'pub_via_root' and 'pubgencols_type' are parameters. Somehow it
seems more natural for the 'puballtables' to be passed before those,
because FOR ALL TABLES comes before WITH in the syntax.

~~~

CreatePublication:

9.
else if (!stmt->for_all_sequences)
- {
ObjectsInPublicationToOids(stmt->pubobjects, pstate, &relations,
&schemaidlist);

AFAICT, this function is refactored a lot because of the removal of
that '{'. It looks like mostly whitespace, but really, I think the
logic is quite different. I wasn't sure what that was about. Is it
related to this patch, or some other bugfix in passing or what?

======
src/backend/commands/tablecmds.c

ATPrepChangePersistence:

10.
- GetRelationPublications(RelationGetRelid(rel)) != NIL)
+ list_length(GetRelationPublications(RelationGetRelid(rel), false)) > 0)

Isn't an empty List the same as a NIL list? Maybe that list_length()
change was not really needed.

======
src/backend/parser/gram.y

11.
drop_option_list pub_obj_list pub_all_obj_type_list
+ except_pub_obj_list opt_except_clause

Is this name consistent with the others? Should it be pub_except_obj_list?

~~~

12.
%type <publicationobjectspec> PublicationObjSpec
+%type <publicationobjectspec> ExceptPublicationObjSpec
%type <publicationallobjectspec> PublicationAllObjSpec

Is this name consistent with the others? Should it be PublicationExceptObjSpec?

~~~

CreatePublicationStmt:

13.
n->pubname = $3;
+ n->pubobjects = $5;

I noticed that sometimes there is a cast (List *) and other times
there is not. e.g. none here, but cast in AlterPublicationStmt. Why
the differences?

~~~

PublicationObjSpec:

14.
The comment for 'PublicationObjSpec' says "FOR TABLE and FOR TABLES IN
SCHEMA specifications". If that comment is correct, then why is this
patch changing this code? OTOH, if the code is correct, then does the
comment need updating?

======
src/bin/pg_dump/pg_dump.c

15.
Shouldn't there have already been some ALTER ... ADD ALL TABLE dump
code and test code implemented back in patch 0002?

~~~

dumpPublication:

16.
else if (pubinfo->puballtables)
+ {
+ SimplePtrListCell *cell;
+
appendPQExpBufferStr(query, " FOR ALL TABLES");
+
+ /* Include exception tables if the publication has except tables */
+ for (cell = exceptinfo.head; cell; cell = cell->next)
+ {
+ PublicationRelInfo *pubrinfo = (PublicationRelInfo *) cell->ptr;
+ TableInfo *tbinfo;
+
+ if (pubinfo == pubrinfo->publication)
+ {
+ tbinfo = pubrinfo->pubtable;
+
+ if (first)
+ {
+ appendPQExpBufferStr(query, " EXCEPT TABLE (");
+ first = false;
+ }
+ else
+ appendPQExpBufferStr(query, ", ");
+ appendPQExpBuffer(query, "ONLY %s", fmtQualifiedDumpable(tbinfo));
+ }
+ }
+ if (!first)
+ appendPQExpBufferStr(query, ")");
+ }

16a.
SimplePtrListCell *cell can be declared as a for-loop variable.

~

16b.
The comment should say "EXCEPT TABLES" in uppercase.

~

16c.
I am not convinced you can use that 'first' flag like you are doing.
Isn't that interfering with the existing usage of that flag? Perhaps
another boolean just for this EXCEPT loop is needed.

~~~

getPublicationTables:

17.
+ if (strcmp(prexcept, "f") == 0)
+ pubrinfo[j].dobj.objType = DO_PUBLICATION_REL;
+ else
+ pubrinfo[j].dobj.objType = DO_PUBLICATION_EXCEPT_REL;
+

...

+ if (strcmp(prexcept, "t") == 0)
+ simple_ptr_list_append(&exceptinfo, &pubrinfo[j]);
+

Here you are comparing the same 'prexcept' flag for both "f" and "t".

I felt it was better if both comparisons are the same (e.g. both "t").

Or better still, assign a new boolean and avoid that 2nd strcmp
entirely -- e.g. except_flag = (strcmp(prexcept, "t") == 0);

======
src/bin/pg_dump/pg_dump_sort.c

DOTypeNameCompare:

18.
+ else if (obj1->objType == DO_PUBLICATION_EXCEPT_REL)
+ {
+ PublicationRelInfo *probj1 = *(PublicationRelInfo *const *) p1;
+ PublicationRelInfo *probj2 = *(PublicationRelInfo *const *) p2;
+
+ /* Sort by publication name, since (namespace, name) match the rel */
+ cmpval = strcmp(probj1->publication->dobj.name,
+ probj2->publication->dobj.name);
+ if (cmpval != 0)
+ return cmpval;
+ }

Isn't this identical to the previous code block? So can't you just add
DO_PUBLICATION_EXCEPT_REL to that condition?

======
src/bin/pg_dump/t/002_pg_dump.pl

19.
Missing test cases for ALTER? But also.

~~~

20.
Missing test cases for EXCEPT for INHERITED tables?

======
src/bin/psql/describe.c

describeOneTableDetails:

21.
I was wondering if the "describe" for tables (e.g. \d+) should also
show the publications where the table is an ECEPT TABLE? How else is
the user going to know it has been excluded by some publication?

======
src/bin/psql/tab-complete.in.c

ALTER PUBLICATION:

22.
The tab completion does not seem as good as it could be. e.g, there is
missing '(' and the for EXCEPT TABLE

~~~

CREATE PUBLICATION:

23.
The tab completion does not seem as good as it could be. e.g, there is
missing '(' and the for EXCEPT TABLE

======
src/test/regress/sql/publication.sql

24.
+\dRp+ testpub_foralltables_excepttable
+\dRp+ testpub_foralltables_excepttable1

As well as doing the "describes" for the publication, I think we need
to see the test cases for the describes of those excluded tables. e.g.
I imagine that they should also list the publications that they are
*excluded* from, right?

~~~

25.
+CREATE PUBLICATION testpub5 FOR ALL TABLES EXCEPT TABLE (testpub_tbl3);
+CREATE PUBLICATION testpub6 FOR ALL TABLES EXCEPT TABLE (ONLY testpub_tbl3);

25a.
Needs some explanatory comments here saying these are for testing the
EXCEPT with inherited tables (e.g. ONLY versus not).

~

25b.
I think you should be testing the '*' syntax here too.

~~~

26.
+CREATE TABLE pub_sch1.tbl2 (a int);
SET client_min_messages = 'ERROR';
CREATE PUBLICATION testpub_reset FOR ALL TABLES, ALL SEQUENCES;
RESET client_min_messages;
@@ -1344,9 +1358,15 @@ ALTER PUBLICATION testpub_reset ADD ALL TABLES;

-- Can't add ALL TABLES to 'ALL TABLES' publication
ALTER PUBLICATION testpub_reset ADD ALL TABLES;
+ALTER PUBLICATION testpub_reset RESET;
+
+-- Verify adding EXCEPT TABLE
+ALTER PUBLICATION testpub_reset ADD ALL TABLES EXCEPT TABLE
(pub_sch1.tbl1, pub_sch1.tbl2);
+\dRp+ testpub_reset

DROP PUBLICATION testpub_reset;
DROP TABLE pub_sch1.tbl1;
+DROP TABLE pub_sch1.tbl2;
DROP SCHEMA pub_sch1;

It looks like that added CREATE TABLE (and RESET?) belongs more
appropriately within the scope of the new test "Verify adding EXCEPT
TABLE".

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-11-24 21:41:05
Message-ID: CAHut+PtJopyr3nVH_3aRKhueg5M8GdSOiWn=9OCcbT52rENyAg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok.

I checked the latest v28-0004 "EXCEPT (col-list)" patch. I have no
code review comments, but I do have one syntax question.

======

The result of the current patch proposed syntax is like:

CREATE PUBLICATION pubname FOR TABLE tabname EXCEPT (col1, col2, col3)
ALTER PUBLICATION pubname ADD TABLE tabname EXCEPT (col1, col2, col3)

~~

In the previous patch v28-0003 (FOR ALL TABLES EXCEPT [TABLE]), I
thought the optional noise-word TABLE did not have any user benefit
because TABLE was already obvious.

OTOH, here in patch v28-0004, it might be helpful to have an
*optional* [COLUMN] part. e.g., I felt "EXCEPT [COLUMN]" would
improve the readability of these commands.

Compare:
CREATE PUBLICATION pubname FOR TABLE tabname EXCEPT (col1, col2, col3)
CREATE PUBLICATION pubname FOR TABLE tabname EXCEPT COLUMN (col1, col2, col3)

Compare:
ALTER PUBLICATION pubname ADD TABLE tabname EXCEPT (col1, col2, col3)
ALTER PUBLICATION pubname ADD TABLE tabname EXCEPT COLUMN (col1, col2, col3)

This is similar to the optional "[COLUMN]" keyword used here [1].

Thoughts?

======
[1] https://www.postgresql.org/docs/devel/sql-altertable.html

Kind Regards,
Peter Smith.
Fujitsu Australia


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-03 03:26:01
Message-ID: CAJpy0uC2SNVoJ3qxygF7t-1Ghk18msRCvTjiUncD261aFDnKXA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Nov 19, 2025 at 3:34 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
>
> I have also addressed the comments in [1], [2].
>
> [1]: https://www.postgresql.org/message-id/CAHut%2BPtRzCD4-0894cutkU_h8cPNtosN0_oSHn2iAKEfg2ENOQ%40mail.gmail.com
> [2]: https://www.postgresql.org/message-id/CAHut+PuHn-hohA4OdEJz+Zfukfr41TvMTeTH7NwJ=wg1+94uNA@mail.gmail.com
>

Thanks for the patch. Please find a few comments on 001:

1)
+ bool nulls[Natts_pg_publication];
+ bool replaces[Natts_pg_publication];
+ Datum values[Natts_pg_publication];

+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));

Can we initialize all 3 like below? Then we do not need memset.
bool nulls[Natts_pg_publication] = {0};

2)
AlterPublicationReset():
Can we reset the columns in same sequence as they are originally
defined (see pg_publication_d.h), it makes it easy to map when
comparing/reviewing that we do not have missed any.

3)
+/* default values for flags and publication parameters */
...
+#define PUB_DEFAULT_VIA_ROOT false
+#define PUB_DEFAULT_ALL_TABLES false
+#define PUB_DEFAULT_ALL_SEQUENCES false
+#define PUB_DEFAULT_GENCOLS PUBLISH_GENCOLS_NONE

These too we can rearrange as per order in pg_publication_d.h

4)
+ COMPLETE_WITH("ADD", "DROP", "OWNER TO", "RENAME TO", "RESET", "SET");

Is it supposed to be in alphabetical order? Looking at others, I do
not think so. If not, then I feel 'SET' first followed by 'RESET'
seems a more obvious choice to me. See similar (ENABLE followed by
DISABLE):
COMPLETE_WITH("CONNECTION", "ENABLE", "DISABLE", "OWNER TO",

5)
+DROP TABLE pub_sch1.tbl1;
+DROP SCHEMA pub_sch1;

We can use 'DROP SCHEMA pub_sch1 CASCADE'. Then we need not to worry
about dropping the associated table(s) (even if we create more in
future in this schema).

thanks
Shveta


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-04 04:41:44
Message-ID: CAJpy0uDBconP5cmBskrbEtitZTCME9nOsYU6001_6NKADdfudQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Dec 3, 2025 at 8:56 AM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Wed, Nov 19, 2025 at 3:34 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> >
> > I have also addressed the comments in [1], [2].
> >
> > [1]: https://www.postgresql.org/message-id/CAHut%2BPtRzCD4-0894cutkU_h8cPNtosN0_oSHn2iAKEfg2ENOQ%40mail.gmail.com
> > [2]: https://www.postgresql.org/message-id/CAHut+PuHn-hohA4OdEJz+Zfukfr41TvMTeTH7NwJ=wg1+94uNA@mail.gmail.com
> >
>
> Thanks for the patch. Please find a few comments on 001:
>
> 1)
> + bool nulls[Natts_pg_publication];
> + bool replaces[Natts_pg_publication];
> + Datum values[Natts_pg_publication];
>
> + memset(values, 0, sizeof(values));
> + memset(nulls, false, sizeof(nulls));
> + memset(replaces, false, sizeof(replaces));
>
> Can we initialize all 3 like below? Then we do not need memset.
> bool nulls[Natts_pg_publication] = {0};
>
> 2)
> AlterPublicationReset():
> Can we reset the columns in same sequence as they are originally
> defined (see pg_publication_d.h), it makes it easy to map when
> comparing/reviewing that we do not have missed any.
>
> 3)
> +/* default values for flags and publication parameters */
> ...
> +#define PUB_DEFAULT_VIA_ROOT false
> +#define PUB_DEFAULT_ALL_TABLES false
> +#define PUB_DEFAULT_ALL_SEQUENCES false
> +#define PUB_DEFAULT_GENCOLS PUBLISH_GENCOLS_NONE
>
> These too we can rearrange as per order in pg_publication_d.h
>
> 4)
> + COMPLETE_WITH("ADD", "DROP", "OWNER TO", "RENAME TO", "RESET", "SET");
>
> Is it supposed to be in alphabetical order? Looking at others, I do
> not think so. If not, then I feel 'SET' first followed by 'RESET'
> seems a more obvious choice to me. See similar (ENABLE followed by
> DISABLE):
> COMPLETE_WITH("CONNECTION", "ENABLE", "DISABLE", "OWNER TO",
>
> 5)
> +DROP TABLE pub_sch1.tbl1;
> +DROP SCHEMA pub_sch1;
>
> We can use 'DROP SCHEMA pub_sch1 CASCADE'. Then we need not to worry
> about dropping the associated table(s) (even if we create more in
> future in this schema).
>

6)
Just before AlterPublicationReset-->LockSchemaList does
SearchSysCacheExists1(), I dropped the schema concurrently, which
resulted in below error:

postgres=# alter publication pub1 reset;
ERROR: schema with OID 16393 does not exist

I do not think the user should be seeing this error. For
CreatePublication and AlterPublicationSchemas, it makes sense to give
an error when it calls LockSchemaList as user has given the schema
names himself. But here since schemas are internally fetched, I think
it will be logical to skip the
error if it gets dropped concurrently. Thoughts?

If we plan to skip error, we can do so by passing the flag
missing_okay=true. See RangeVarGetRelid and other such functions using
such a flag.

thanks
Shveta


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-04 11:50:54
Message-ID: CANhcyEV7ewT+nfLM2owquxW-_6m8Ju+P93y=acoS=JCBHoT-MQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 20 Nov 2025 at 11:54, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok.
>
> Thanks for splitting the patches.
>
> Here are some review comments for the new patch v28-0002 (ADD ALL TABLES).
>
> ======
> Commit Message
>
> 1.
> This patch adds support for using ADD ALL TABLES in ALTER PUBLICATION,
> allowing an existing publication to be changed into an ALL TABLES
> publication. This command is permitted only when the publication is
> in its default state, meaning it has no tables or schemas added, its
> ALL TABLES and ALL SEQUENCES flags are not set, and publication
> options such as publish_via_root_partition, publish_generated_columns,
> and publish are at their default values.
>
> ~
>
> IMO, the restrictions for this new command are too severe:
>
> e.g. If I already have a FOR ALL SEQUENCES publication, then I
> expected it should be possible to ADD ALL TABLES to that as well,
> right?
>
> Likewise, why are we enforcing that the publication parameters must be
> defaults? IOW, why is (i) below disallowed, but (ii) is allowed?
>
> (i)
> ALTER PUBLICATION pub SET (publish_generated_columns=stored);
> ALTER PUBLICATION pub ADD ALL TABLES;
>
> (ii)
> ALTER PUBLICATION pub ADD ALL TABLES;
> ALTER PUBLICATION pub SET (publish_generated_columns=stored);
>
I agree that the current restrictions were too strict. With the latest
patch we avoid adding ALL TABLES only when we have an existing list of
tables or schemas in a publication.

> ======
> doc/src/sgml/ref/alter_publication.sgml
>
> Description:
>
> 2.
> The "Description" part of this page is confusing because it was
> referring to "The first three variants" and later "The fourth
> variant". Now that the "ADD ALL TABLES" variant has been added, I
> have lost track of what "variants" this description is talking about.
> Those words should be replaced by something clearer. This could be an
> ongoing issue if it is not worded differently because the same problem
> will happen again, e.g. when more syntax gets added for ALL SEQUENCES,
> etc.
>
> ~~~
>
I have updated the description to avoid the wording "The first three
variants". Instead I have added a list to describe each command
separately. Similar to ALTER TABLE [1].

> 3.
> Note also that DROP TABLES IN SCHEMA will not drop any schema tables
> that were specified using FOR TABLE/ ADD TABLE.
>
> ~
>
> That sentence (above) is from the docs. Does that also need updating
> now that there is ADD ALL TABLES?
>
When we create a publication on a schema, we can also add specific
tables using FOR TABLE/ADD TABLE.
But in case of ALL TABLES publication we are not allowed to include
tables using FOR TABLE/ADD TABLE.

So for ALL TABLES case this wording is not required.

> ======
> src/backend/commands/publicationcmds.c
>
> CheckPublicationDefValues:
>
> 4.
> Is this function needed?
>
It is not needed. Modified the function to give proper error messages
for each case.

> ~~~
>
> AlterPublication:
>
> 5.
> + if (stmt->for_all_tables)
> + {
> + bool isdefault = CheckPublicationDefValues(tup);
> +
> + if (!isdefault)
> + ereport(ERROR,
> + errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
> + errmsg("adding ALL TABLES requires the publication to have default
> publication parameter values"),
> + errdetail("ALL TABLES or ALL SEQUENCES flag should not be set and no
> tables/schemas should be associated."),
> + errhint("Use ALTER PUBLICATION ... RESET to reset the publication"));
> +
> + AlterPublicationSetAllTables(rel, tup);
> + }
> +
>
> Why do we need this self-imposed restriction?
>
See reply to comment 1.

> ======
> src/include/nodes/parsenodes.h
>
> 6.
> List *pubobjects; /* Optional list of publication objects */
> + bool for_all_tables; /* Special publication for all tables in db */
> AlterPublicationAction action; /* What action to perform with the given
> * objects */
> } AlterPublicationStmt;
>
>
> There is no such "FOR" syntax like ALTER PUBLICATION ... FOR ALL
> TABLES, so I felt just 'puballtables' might be a better member name.
>
We have the same variable name in CreatePublicationStmt. I feel
keeping the name as 'for_all_tables' will keep it consistent and
easier to understand.

> ======
> src/test/regress/sql/publication.sql
>
> 7.
> Don't uppercase any of the publication parameters because they never
> appear in the docs/examples like that.
>
> ~
>
> 8.
> So that the last command is the one being tested, I felt that all the
> test cases should be doing RESET *first* instead of last.
>
> ~~~
>
> 9.
> You don't always need to use RESET. There should also be some tests
> using an "empty" publication just to be sure it works. e.g
>
> CREATE PUBLICATION pub_empty;
> ALTER PUBLICATION pub_empty ADD ALL TABLES;
>
> ~~~
>
> 10.
> As commented earlier, I felt the rules were too restrictive. So I
> think some test cases can be removed.
>
> ~~~
>
> 11.
> +-- Tests for ALTER PUBLICATION ... ADD ALL TABLES
>
> ~
>
> I noticed there is a "--
> ======================================================" separator
> between the major groups of tests.
>
> 11a. Should use this separator in patch 0001 for the RESET group of tests
>
> 11b. Should use this separator in patch 0002 for the ADD ALL TABLES
> groups of tests
>
> ~~~
>
> 12.
> +-- Can't add ALL TABLES to 'ALL TABLES' publication
> +ALTER PUBLICATION testpub_reset ADD ALL TABLES;
> +
>
> This test case seems to belong earlier, near the 'FOR TABLE' and the
> 'TABLES IN SCHEMA' tests.
>
I saw the patch needed a rebase. I have rebased it.
I have also addressed the remaining comments in this email and
comments in the email [2].

While addressing the comments I saw there were a couple of race
conditions when we run 'ALTER PUBLICATION ... RESET and ALTER
PUBLICATION ... ADD TABLE concurrently' and
'ALTER PUBLICATION ... ADD ALL TABLES and ALTER PUBLICATION ... ADD
TABLE concurrently'
I have addressed these in the v29 patch.
Will address comments for 0003 and 0004 patch by Peter and comments by
Shveta in next version.

[1]: https://www.postgresql.org/docs/current/sql-altertable.html
[2]: https://www.postgresql.org/message-id/CAHut%2BPv4d9EAjDQiOHiu2BrYP3ZA-oJgsgGZdygBaZnWDR7sDA%40mail.gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v29-0001-Add-RESET-clause-to-Alter-Publication-which-will.patch application/octet-stream 25.0 KB
v29-0003-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 71.1 KB
v29-0002-Support-ADD-ALL-TABLES-in-ALTER-PUBLICATION.patch application/octet-stream 17.6 KB
v29-0004-Skip-publishing-the-columns-specified-in-FOR-TAB.patch application/octet-stream 77.0 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-08 05:46:56
Message-ID: CAHut+PuJYW-Si1aM-VkKmgvnYdYPNHmiL0T=Q49YpDsj19T84g@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok. Some review comments for v29-0001 (ALTER PUBLICATION RESET)

======
doc/src/sgml/ref/alter_publication.sgml

Description:

1.
<para>
The command <command>ALTER PUBLICATION</command> can change the attributes
- of a publication.
- </para>
+ of a publication. There are several subforms described below.

IMO, you don't need to say that sentence "There are several subforms
described below," because it is obvious from the context.

(I guess you copied it from ALTER TABLE, but that doesn't change my opinion)

~~~

<General>

2.
The new description list entries all say:

"This form adds..."
"This form replaces..."
"This for removes..."
etc.

IMO, the words "This form" are all unnecessary here. Instead, just say
"Adds...", "Replaces...", "Removes...", etc.

(I guess you copied it from ALTER TABLE, but that doesn't change my opinion)

~~~

DROP:

3.
+ <varlistentry>
+ <term><literal>DROP <replaceable
class="parameter">publication_object</replaceable> [,
...]</literal></term>
+ <listitem>

The replacement name here should be "publication_drop_object".

~~~

SET:

4.
+ <para>
+ This form can change all of the publication properties specified in
+ <xref linkend="sql-createpublication"/>. Properties not mentioned in the
+ command retain their previous settings. It is not applicable to
+ sequences.
+ </para>

For "can change all of"; maybe that should be "can change any of".
Also, for "It is not applicable." -- saying "it" seemed awkward.

IMO the current master text (shown below) seemed OK as-is; At least I
thought it was better than the patch replacement text:
This clause alters publication parameters originally set by CREATE
PUBLICATION. See there for more information. This clause is not
applicable to sequences.

~~~

5.
+ <para>
+ This problem can be avoided by refraining from modifying partition leaf
+ tables after the <command>ALTER PUBLICATION ... SET</command> until the
+ <link linkend="sql-altersubscription"><command>ALTER
SUBSCRIPTION ... REFRESH PUBLICATION</command></link>
+ is executed and by only refreshing using the
<literal>copy_data = off</literal>
+ option.
+ </para>

This link would be better if it referenced the actual REFRESH
PUBLICATION. Currently, it just goes to the top of the ALTER
SUBSCRIPTION page.

~~~

6.
<para>
You must own the publication to use <command>ALTER PUBLICATION</command>.
Adding a table to a publication additionally requires owning that table.
- The <literal>ADD TABLES IN SCHEMA</literal> and
- <literal>SET TABLES IN SCHEMA</literal> to a publication requires the
- invoking user to be a superuser.
- To alter the owner, you must be able to <literal>SET ROLE</literal> to the
- new owning role, and that role must have <literal>CREATE</literal>
- privilege on the database.
+ The <literal>ADD TABLES IN SCHEMA</literal>,
+ <literal>SET TABLES IN SCHEMA</literal> to a publication and
+ <literal>RESET</literal> of publication requires the invoking user to be a
+ superuser. To alter the owner, you must be able to
+ <literal>SET ROLE</literal> to the new owning role, and that role must have
+ <literal>CREATE</literal> privilege on the database.
Also, the new owner of a
<link linkend="sql-createpublication-params-for-tables-in-schema"><literal>FOR
TABLES IN SCHEMA</literal></link>
or <link linkend="sql-createpublication-params-for-all-tables"><literal>FOR
ALL TABLES</literal></link>

I felt that those sentences:
"To alter the owner, you must ...", and
"Also, the new owner of a ..."
really belonged in the ALTER OWNER TO description part.

src/test/regress/sql/publication.sql
======

7.
+ALTER PUBLICATION testpub_reset SET (publish_via_partition_root = 'true');

It's a bit strange to say 'true' in quotes. Indeed, you shouldn't need
to give any value here -- just say "SET (publish_via_partition_root)"

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-08 11:57:27
Message-ID: CAJpy0uDdQH7b=LRn_HevbmFACpvq9=c32Vb3tRvjSOnDsQd74w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Dec 4, 2025 at 5:21 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> I have addressed these in the v29 patch.
> Will address comments for 0003 and 0004 patch by Peter and comments by
> Shveta in next version.
>

Thanks for the patch.

I believe patch 003 (EXCEPT table) and 004 (EXCEPT column_list) should
be the primary focus. The other patches, RESET and ADD ALL tables are
additional features and may or may not be necessary depending on
further input.

I suggest making 003 and 004 as 001 and 002 respectively, and
prioritizing these first. The RESET and ADD ALL tables patches can
become 003 and 004, and we can review them after the first 2 patches
are fully evaluated. The documentation formatting changes for ALTER
PUBLICATION are not required in this patch and, if needed, can be
handled separately.

thanks
Shveta


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-08 12:14:19
Message-ID: CAA4eK1KZ1Sb0soHp3HH2htwJ3=qka-eQjW35vOW3+4VeWw4VoQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Dec 8, 2025 at 5:27 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Thu, Dec 4, 2025 at 5:21 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > I have addressed these in the v29 patch.
> > Will address comments for 0003 and 0004 patch by Peter and comments by
> > Shveta in next version.
> >
>
> Thanks for the patch.
>
> I believe patch 003 (EXCEPT table) and 004 (EXCEPT column_list) should
> be the primary focus.
>

+1. We should first try to make 0003 RFC before going further.

--
With Regards,
Amit Kapila.


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-09 17:46:59
Message-ID: CANhcyEXwLrQsec6g+1dqWTKyJQMQMh=getj28C+zLL14BjuumA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 8 Dec 2025 at 17:44, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Mon, Dec 8, 2025 at 5:27 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > On Thu, Dec 4, 2025 at 5:21 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > >
> > > I have addressed these in the v29 patch.
> > > Will address comments for 0003 and 0004 patch by Peter and comments by
> > > Shveta in next version.
> > >
> >
> > Thanks for the patch.
> >
> > I believe patch 003 (EXCEPT table) and 004 (EXCEPT column_list) should
> > be the primary focus.
> >
>
> +1. We should first try to make 0003 RFC before going further.
>
I have removed the 0001 0002 and 0004 patches for now. Will post them
once 0003 patch is RFC.
Here is the update patch for "EXCEPT TABLE".

Thanks,
Shlok Kyal

Attachment Content-Type Size
v30-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 65.0 KB

From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-09 17:48:48
Message-ID: CANhcyEWt0h-tqDZzQOhHXiS+fo2Wn9NomtvXq8oy=JG3nVTM2g@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 24 Nov 2025 at 13:03, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> On Fri, Nov 21, 2025 at 5:55 PM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >
> > Hi Shlok.
> >
> > Here are some review comments for your patch v28-0003 (EXCEPT TABLE ...).
> >
> > The review of this patch is a WIP. In this post I only looked at the test code.
> >
>
> Here are my remaining review comments for patch v28-0003 (EXCEPT TABLE ...).
>
> ======
> doc/src/sgml/ref/create_publication.sgml
>
> 1.
> -ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
> ADD ALL TABLES
> +ALTER PUBLICATION <replaceable class="parameter">name</replaceable>
> ADD ALL TABLES [ EXCEPT [ TABLE ] ( <replaceable
> class="parameter">table_exception_object</replaceable> [, ... ] ) ]
>
> Why is that optional [TABLE] keyword needed?
>
> I know PostGres commands sometimes have "noise" words in the syntax so
> the command can be more English-like, but in this case, the
> publication is a FOR ALL *TABLES* anyway, so I am not sure what the
> benefit is of the user being able to say TABLE a 2nd time?
>
I think this feature can be extended to EXCEPT SCHEMA etc. So I think
it is necessary for clarity.
There is already a discussion [1].

> ======
> src/backend/catalog/pg_publication.c
>
> 2.
> + /*
> + * Check for partitions of partitioned table which are specified with
> + * EXCEPT clause and partitioned table is published with
> + * publish_via_partition_root = true.
> + */
>
> I think you can just say "partitions" or "table partitions", but
> "partitions of [a] partitioned table" seems overkill.
>
> Also, "... and partitioned table is published with
> publish_via_partition_root = true." seems too wordy. Isn't that just
> the same as "... and publish_via_partition_root = true"
>
> SUGGESTION
> Check for when the publication says "EXCEPT TABLE (partition)" but
> publish_via_partition_root = true.
>
> ~~~
>
Modified

> 3.
> -/* Gets list of publication oids for a relation */
> +/* Gets list of publication oids for a relation that matches the except_flag */
> List *
> -GetRelationPublications(Oid relid)
> +GetRelationPublications(Oid relid, bool except_flag)
> {
> List *result = NIL;
> CatCList *pubrellist;
> @@ -765,7 +791,8 @@ GetRelationPublications(Oid relid)
> HeapTuple tup = &pubrellist->members[i]->tuple;
> Oid pubid = ((Form_pg_publication_rel) GETSTRUCT(tup))->prpubid;
>
> - result = lappend_oid(result, pubid);
> + if (except_flag == ((Form_pg_publication_rel) GETSTRUCT(tup))->prexcept)
> + result = lappend_oid(result, pubid);
> }
>
> I was wondering if it might be better to return 2 lists from this
> function (e.g. an included-list, and an excluded-list) instead of
> passing the 'except_flag' like the current code. IIUC, you are mostly
> calling this function twice to get 2 lists anyway, but returning 2
> lists instead of 1, this function might be more efficient since it
> will only process the publication loop once.
>
Modified

> ~~~
>
> 4.
> /*
> * Gets list of relation oids for a publication that matches the except_flag.
> *
> * This should only be used FOR TABLE publications, the FOR ALL TABLES/SEQUENCES
> * should use GetAllPublicationRelations().
> */
> List *
> GetPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt,
> bool except_flag)
> Something doesn't seem right -- the function comment says we shouldn't
> be calling the function for FOR ALL TABLES, but meanwhile, EXCEPT
> TABLE is currently only implemented via FOR ALL TABLES. So it feels
> contradictory. Maybe it is just the comment that needs updating?
>
I thought more about this function and found that we can remove the
'except_flag' variable.

Since we can only use EXCEPT TABLE clause for ALL TABLES publication
and we cannot use FOR TABLE clause with ALL TABLES.
If for ALL TABLES publication we call this function, we will return an
except table list.
Else we will return a list of table to be included in publication.

I have added a comment to this behaviour.

> ~~~
>
> 5.
> /*
> * Gets list of relation oids for a publication that matches the except_flag.
> *
> * This should only be used FOR TABLE publications, the FOR ALL TABLES/SEQUENCES
> * should use GetAllPublicationRelations().
> */
> List *
> GetPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt,
> bool except_flag)
> {
> List *result;
> Relation pubrelsrel;
> ScanKeyData scankey;
> SysScanDesc scan;
> HeapTuple tup;
>
> /* Find all publications associated with the relation. */
> pubrelsrel = table_open(PublicationRelRelationId, AccessShareLock);
>
> Existing bug? Isn't this a bogus comment?
> /* Find all publications associated with the relation. */
>
> Was that meant to be the other way around? -- e.g. Find all the
> relations associated with the specified publication.
>
I think you are correct. I will create a separate thread for this change.

> ======
> src/backend/commands/publicationcmds.c
>
> 6.
> + default:
> + /* shouldn't happen */
> + elog(ERROR, "invalid publication object type %d",
> + puballobj->pubobjtype);
> + break;
>
> I think the ERROR is enough of a clue that it shouldn't happen. I felt
> the comment was redundant.
>
There are multiple similar occurrences. See functions
'ObjectsInPublicationToOids', in publicationcmds.c.
There are some occurrences in the openssl.c file as well. But I also
think this comment is redundant.
I have removed the comment.

> ~~~
>
> ObjectsInPublicationToOids:
>
> 7.
> case PUBLICATIONOBJ_TABLE:
> + pubobj->pubtable->except = false;
> + *rels = lappend(*rels, pubobj->pubtable);
> + break;
> + case PUBLICATIONOBJ_EXCEPT_TABLE:
> + pubobj->pubtable->except = true;
> *rels = lappend(*rels, pubobj->pubtable);
> break;
> Those are very similar. How about combining like below?
>
> case PUBLICATIONOBJ_TABLE:
> case PUBLICATIONOBJ_EXCEPT_TABLE:
> pubobj->pubtable->except = (pubobj->pubobjtype ==
> PUBLICATIONOBJ_EXCEPT_TABLE);
> *rels = lappend(*rels, pubobj->pubtable);
> break;
>
Modified

> ~~
>
> pub_contains_invalid_column:
>
> 8.
> pub_contains_invalid_column(Oid pubid, Relation relation, List *ancestors,
> bool pubviaroot, char pubgencols_type,
> - bool *invalid_column_list,
> + bool puballtables, bool *invalid_column_list,
> bool *invalid_gen_col)
>
> The 'pub_via_root' and 'pubgencols_type' are parameters. Somehow it
> seems more natural for the 'puballtables' to be passed before those,
> because FOR ALL TABLES comes before WITH in the syntax.
>
Modified

> ~~~
>
> CreatePublication:
>
> 9.
> else if (!stmt->for_all_sequences)
> - {
> ObjectsInPublicationToOids(stmt->pubobjects, pstate, &relations,
> &schemaidlist);
>
> AFAICT, this function is refactored a lot because of the removal of
> that '{'. It looks like mostly whitespace, but really, I think the
> logic is quite different. I wasn't sure what that was about. Is it
> related to this patch, or some other bugfix in passing or what?
>
This change is part of this patch.
This change is required to get a list of tables which are excluded
(for ALL TABLES publication).

I think the code related to schema should be inside the condition
'else if (!stmt->for_all_sequences)'
I have made the change for the same and also added a comment.

> ======
> src/backend/commands/tablecmds.c
>
> ATPrepChangePersistence:
>
> 10.
> - GetRelationPublications(RelationGetRelid(rel)) != NIL)
> + list_length(GetRelationPublications(RelationGetRelid(rel), false)) > 0)
>
> Isn't an empty List the same as a NIL list? Maybe that list_length()
> change was not really needed.
>
Modified

> ======
> src/backend/parser/gram.y
>
> 11.
> drop_option_list pub_obj_list pub_all_obj_type_list
> + except_pub_obj_list opt_except_clause
>
> Is this name consistent with the others? Should it be pub_except_obj_list?
>
I think pub_except_obj_list is consistent with others. Modified.

> ~~~
>
> 12.
> %type <publicationobjectspec> PublicationObjSpec
> +%type <publicationobjectspec> ExceptPublicationObjSpec
> %type <publicationallobjectspec> PublicationAllObjSpec
>
> Is this name consistent with the others? Should it be PublicationExceptObjSpec?
>
I agree. Modified.

> ~~~
>
> CreatePublicationStmt:
>
> 13.
> n->pubname = $3;
> + n->pubobjects = $5;
>
> I noticed that sometimes there is a cast (List *) and other times
> there is not. e.g. none here, but cast in AlterPublicationStmt. Why
> the differences?
>
This change is not required in the latest patch. Due to discussion in [2].

> ~~~
>
> PublicationObjSpec:
>
> 14.
> The comment for 'PublicationObjSpec' says "FOR TABLE and FOR TABLES IN
> SCHEMA specifications". If that comment is correct, then why is this
> patch changing this code? OTOH, if the code is correct, then does the
> comment need updating?
>
We have only added "$$->location = @1;" for PublicationObjSpec.
I define the location of the '^' indicator while throwing an error. I
think we don't need to update comments for it?

> ======
> src/bin/pg_dump/pg_dump.c
>
> 15.
> Shouldn't there have already been some ALTER ... ADD ALL TABLE dump
> code and test code implemented back in patch 0002?
>
This change is not required in the latest patch. Due to discussion in [2].

> ~~~
>
> dumpPublication:
>
> 16.
> else if (pubinfo->puballtables)
> + {
> + SimplePtrListCell *cell;
> +
> appendPQExpBufferStr(query, " FOR ALL TABLES");
> +
> + /* Include exception tables if the publication has except tables */
> + for (cell = exceptinfo.head; cell; cell = cell->next)
> + {
> + PublicationRelInfo *pubrinfo = (PublicationRelInfo *) cell->ptr;
> + TableInfo *tbinfo;
> +
> + if (pubinfo == pubrinfo->publication)
> + {
> + tbinfo = pubrinfo->pubtable;
> +
> + if (first)
> + {
> + appendPQExpBufferStr(query, " EXCEPT TABLE (");
> + first = false;
> + }
> + else
> + appendPQExpBufferStr(query, ", ");
> + appendPQExpBuffer(query, "ONLY %s", fmtQualifiedDumpable(tbinfo));
> + }
> + }
> + if (!first)
> + appendPQExpBufferStr(query, ")");
> + }
>
> 16a.
> SimplePtrListCell *cell can be declared as a for-loop variable.
>
> ~
>
> 16b.
> The comment should say "EXCEPT TABLES" in uppercase.
>
> ~
>
> 16c.
> I am not convinced you can use that 'first' flag like you are doing.
> Isn't that interfering with the existing usage of that flag? Perhaps
> another boolean just for this EXCEPT loop is needed.
>
> ~~~
>
Modified

> getPublicationTables:
>
> 17.
> + if (strcmp(prexcept, "f") == 0)
> + pubrinfo[j].dobj.objType = DO_PUBLICATION_REL;
> + else
> + pubrinfo[j].dobj.objType = DO_PUBLICATION_EXCEPT_REL;
> +
>
> ...
>
> + if (strcmp(prexcept, "t") == 0)
> + simple_ptr_list_append(&exceptinfo, &pubrinfo[j]);
> +
>
> Here you are comparing the same 'prexcept' flag for both "f" and "t".
>
> I felt it was better if both comparisons are the same (e.g. both "t").
>
> Or better still, assign a new boolean and avoid that 2nd strcmp
> entirely -- e.g. except_flag = (strcmp(prexcept, "t") == 0);
>
Modified

> ======
> src/bin/pg_dump/pg_dump_sort.c
>
> DOTypeNameCompare:
>
> 18.
> + else if (obj1->objType == DO_PUBLICATION_EXCEPT_REL)
> + {
> + PublicationRelInfo *probj1 = *(PublicationRelInfo *const *) p1;
> + PublicationRelInfo *probj2 = *(PublicationRelInfo *const *) p2;
> +
> + /* Sort by publication name, since (namespace, name) match the rel */
> + cmpval = strcmp(probj1->publication->dobj.name,
> + probj2->publication->dobj.name);
> + if (cmpval != 0)
> + return cmpval;
> + }
>
> Isn't this identical to the previous code block? So can't you just add
> DO_PUBLICATION_EXCEPT_REL to that condition?
>
Modified

> ======
> src/bin/pg_dump/t/002_pg_dump.pl
>
> 19.
> Missing test cases for ALTER? But also.
>
This change is not required in the latest patch. Due to discussion in [2].

> ~~~
>
> 20.
> Missing test cases for EXCEPT for INHERITED tables?
>
> ======
> src/bin/psql/describe.c
>
> describeOneTableDetails:
>
> 21.
> I was wondering if the "describe" for tables (e.g. \d+) should also
> show the publications where the table is an ECEPT TABLE? How else is
> the user going to know it has been excluded by some publication?
>
I thought it would be sufficient to show only the list of
publications, the table is part of.
Users can check the excluded tables by checking the description of the
publication using \dRp+.
Will it be not sufficient?
I am not sure why we should show a list of publications which it is not part of?
Am I missing something thoughts?

> ======
> src/bin/psql/tab-complete.in.c
>
> ALTER PUBLICATION:
>
> 22.
> The tab completion does not seem as good as it could be. e.g, there is
> missing '(' and the for EXCEPT TABLE
>
> ~~~
>
Modified

> CREATE PUBLICATION:
>
> 23.
> The tab completion does not seem as good as it could be. e.g, there is
> missing '(' and the for EXCEPT TABLE
>
Modified

> ======
> src/test/regress/sql/publication.sql
>
> 24.
> +\dRp+ testpub_foralltables_excepttable
> +\dRp+ testpub_foralltables_excepttable1
>
> As well as doing the "describes" for the publication, I think we need
> to see the test cases for the describes of those excluded tables. e.g.
> I imagine that they should also list the publications that they are
> *excluded* from, right?
>
See Reply to comment 21.

> ~~~
>
> 25.
> +CREATE PUBLICATION testpub5 FOR ALL TABLES EXCEPT TABLE (testpub_tbl3);
> +CREATE PUBLICATION testpub6 FOR ALL TABLES EXCEPT TABLE (ONLY testpub_tbl3);
>
> 25a.
> Needs some explanatory comments here saying these are for testing the
> EXCEPT with inherited tables (e.g. ONLY versus not).
>
> ~
>
> 25b.
> I think you should be testing the '*' syntax here too.
>
> ~~~
>
I agree. Made the changes.

> 26.
> +CREATE TABLE pub_sch1.tbl2 (a int);
> SET client_min_messages = 'ERROR';
> CREATE PUBLICATION testpub_reset FOR ALL TABLES, ALL SEQUENCES;
> RESET client_min_messages;
> @@ -1344,9 +1358,15 @@ ALTER PUBLICATION testpub_reset ADD ALL TABLES;
>
> -- Can't add ALL TABLES to 'ALL TABLES' publication
> ALTER PUBLICATION testpub_reset ADD ALL TABLES;
> +ALTER PUBLICATION testpub_reset RESET;
> +
> +-- Verify adding EXCEPT TABLE
> +ALTER PUBLICATION testpub_reset ADD ALL TABLES EXCEPT TABLE
> (pub_sch1.tbl1, pub_sch1.tbl2);
> +\dRp+ testpub_reset
>
> DROP PUBLICATION testpub_reset;
> DROP TABLE pub_sch1.tbl1;
> +DROP TABLE pub_sch1.tbl2;
> DROP SCHEMA pub_sch1;
>
> It looks like that added CREATE TABLE (and RESET?) belongs more
> appropriately within the scope of the new test "Verify adding EXCEPT
> TABLE".
>
This change is not required in the latest patch. Due to discussion in [2].

I have addressed the comments and attached the latest patch.
As per suggestion by Shveta and Amit, I have omitted the patches 0001,
0002, and 0004 (as per [2]). Will post these patches once 0003 patch
is RFC.

The new 0001 patch is to support EXCEPT TABLE for CREATE PUBLICATION
.. FOR ALL TABLES syntax. I have attached in [3].

[1]: https://www.postgresql.org/message-id/CAA4eK1JEKs8qwwhRb1BCiMNduJ5ePUtFnTscrZt86UKWBkLxwg%40mail.gmail.com
[2]: https://www.postgresql.org/message-id/CAA4eK1KZ1Sb0soHp3HH2htwJ3%3Dqka-eQjW35vOW3%2B4VeWw4VoQ%40mail.gmail.com
[3]: https://www.postgresql.org/message-id/CANhcyEXwLrQsec6g%2B1dqWTKyJQMQMh%3Dgetj28C%2BzLL14BjuumA%40mail.gmail.com

Thanks,
Shlok Kyal


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-09 17:49:26
Message-ID: CANhcyEXT=DPeULFL2udhcyO1340Y1fGqgpmUqpiCh++JnC8caw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 21 Nov 2025 at 12:26, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok.
>
> Here are some review comments for your patch v28-0003 (EXCEPT TABLE ...).
>
> The review of this patch is a WIP. In this post I only looked at the test code.
>
> ======
> .../t/037_rep_changes_except_table.pl
>
> 1.
> +
> +# Copyright (c) 2021-2025, PostgreSQL Global Development Group
> +
> +# Logical replication tests for except table publications
>
> Use uppercase: /except table/EXCEPT TABLE/
>
> ~~~
>
> 2.
> There are lots of test cases dedicated to partiion-table testing. I
> felt a bigger comment separating these major groups might be helpful.
>
> Something like:
>
> -- ============================================
> -- EXCEPT TABLE test cases for normal tables
> -- ============================================
>
> and
>
> -- ============================================
> -- EXCEPT TABLE test cases for partition tables
> -- ============================================
>
> ~~~
>
> 3.
> +# Initialize publisher node
> ...
> +# Create subscriber node
>
> Those 2 comments should be almost alike -- e.g. both should say
> "Initialize" or both should say "Create".
>
> ~~~
>
> 4.
> +# Test replication with publications created using FOR ALL TABLES EXCEPT TABLE
> +# clause.
> +# Create schemas and tables on publisher
> +$node_publisher->safe_psql(
> + 'postgres', qq(
> + CREATE SCHEMA sch1;
> + CREATE TABLE sch1.tab1 AS SELECT generate_series(1,10) AS a;
> + CREATE TABLE public.tab1(a int);
> +));
> +
>
> That first sentence ("Test replication with ...") is not needed here.
> The is just repeating the purpose of the entire file, so that comment
> can replace the one at the top of this file.
>
> ~~~
>
> 5.
> +# Insert some data and verify that inserted data is not replicated
>
> Be explicit that we are referring to the excluded table.
>
> SUGGESTION (e.g.)
> Verify that data inserted to the excluded table is not replcated.
>
> ~~~
>
> 6.
> +# Alter publication to exclude data changes in public.tab1 and verify that
> +# subscriber does not get the changed data for this table.
> +$node_publisher->safe_psql(
> + 'postgres', qq(
> + ALTER PUBLICATION tap_pub_schema RESET;
> + ALTER PUBLICATION tap_pub_schema ADD ALL TABLES EXCEPT TABLE
> (sch1.tab1, public.tab1);
> + INSERT INTO public.tab1 VALUES(generate_series(1,10));
> +));
> +$node_publisher->wait_for_catchup('tap_sub_schema');
> +
>
> It is not strictly needed for these tests, but do you think it makes
> more sense to also do an ALTER SUBSCRIPTION ... REFRESH PUBLICATION;
> whenever you change the publications?
>
> ~~~
>
> 7.
> +# cleanup
> +$node_publisher->safe_psql('postgres', "DROP PUBLICATION tap_pub_schema");
> +$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION tap_sub_schema");
> +
> +
>
> double-blank lines.
>
> ~~~
>
> 8.
> I think it would be more helpful if the partition table test cases say
> (in their comments) a lot more about the steps they are doing, and
> what they expect the result to be. Sure, I can read all the code to
> figure it out for each case, but it is better to know the test
> intentions/expectations then verify they are doing the right thing.
>
> ~~~
>
> 9.
> + CREATE TABLE sch1.t1(a int) PARTITION BY RANGE(a);
> + CREATE TABLE sch1.part1 PARTITION OF sch1.t1 FOR VALUES FROM (0) TO (5);
>
> Maybe create this table to have *multiple* partitions. It might be
> interesting later to see what happens when you try to EXCEPT only one
> of the partitions.
>
I have addressed all the comments
Please find the updated patch in [1].

[1]: https://www.postgresql.org/message-id/CANhcyEXwLrQsec6g%2B1dqWTKyJQMQMh%3Dgetj28C%2BzLL14BjuumA%40mail.gmail.com

Thanks,
Shlok Kyal


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-10 05:50:59
Message-ID: CAJpy0uD35+YmDahVNUm+NZsjisV_k2hUDBkiFOJDwAJ1o1CT9A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Dec 9, 2025 at 11:17 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> >
> I have removed the 0001 0002 and 0004 patches for now. Will post them
> once 0003 patch is RFC.
> Here is the update patch for "EXCEPT TABLE".
>

Thanks, I have not looked at new patch yet, but here are few comments
for v29-003:

1)
create_publication.sgml:
Please add one more example in the example section for EXCEPT using
'all tables, and all sequences' after the last existing one. This is
needed to show that ALL TABLES EXCEPT() and ALL SEQ are still possible
in single command.

2)
+ excluded. Optionally, <literal>*</literal> can be specified after the
+ table name to explicitly indicate that descendant tables are excluded.
+ </para>

We may add: This does not apply to a partitioned table, however.
(this will make it more clear similar to how existing doc has it for
'FOR TABLE' clause ). And then start details on partition.

3)
When
+ <literal>publish_via_partition_root</literal> is set to
+ <literal>false</literal>, specifying a partitioned table or non-leaf
+ partition has no effect

Can we simply say 'specifying a root partitioned table has no effect'.
This will make it consistent as the previous sentence also uses the
same term rather than 'non-leaf'.

4)
tab_root is a partitioned table with tab_part_1 and tab_part_2 as its
partitions.
In the first case, I receive a WARNING because the user excluded
tab_part_2 but its data will still be replicated through the root
table:

postgres=# create publication pub3 for all tables except (tab_part_2)
WITH (publish_via_partition_root=true);
WARNING: partition "tab_part_2" will be replicated as
publish_via_partition_root is "true"

But in the following case, no WARNING is shown:
postgres=# create publication pub4 for all tables except (tab_root)
WITH (publish_via_partition_root=false);
CREATE PUBLICATION

In this scenario, the user has excluded the root table, yet its data
will still be replicated because publish_via_partition_root = false.
Should we emit a warning in this case as well? Thoughts?

5)
publication_add_relation:
+ if (pub->alltables && pri->except && targetrel->rd_rel->relispartition &&
+ pub->pubviaroot)

Can we please bring both the 'pub' conditions together, as that seems
more understandable:
if (pub->alltables && pub->pubviaroot &&...)

6)
We have added pubid as argument to GetAllPublicationRelations to
exclude except-list tables.
We should change comment atop GetAllPublicationRelations() to indicate
the same. We should extend
this existing comment to say about except-list exclusion also.

* If the publication publishes partition changes via their respective root
* partitioned tables, we must exclude partitions in favor of including the
* root partitioned tables.

thanks
Shveta


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-10 10:21:53
Message-ID: CANhcyEV_EVi5cgJ6WPvmeVAqjCS7Of+VAWuRHZtsVf8PQb_z7g@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 10 Dec 2025 at 11:21, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Tue, Dec 9, 2025 at 11:17 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > >
> > I have removed the 0001 0002 and 0004 patches for now. Will post them
> > once 0003 patch is RFC.
> > Here is the update patch for "EXCEPT TABLE".
> >
>
> Thanks, I have not looked at new patch yet, but here are few comments
> for v29-003:
>
> 1)
> create_publication.sgml:
> Please add one more example in the example section for EXCEPT using
> 'all tables, and all sequences' after the last existing one. This is
> needed to show that ALL TABLES EXCEPT() and ALL SEQ are still possible
> in single command.
>
> 2)
> + excluded. Optionally, <literal>*</literal> can be specified after the
> + table name to explicitly indicate that descendant tables are excluded.
> + </para>
>
> We may add: This does not apply to a partitioned table, however.
> (this will make it more clear similar to how existing doc has it for
> 'FOR TABLE' clause ). And then start details on partition.
>
> 3)
> When
> + <literal>publish_via_partition_root</literal> is set to
> + <literal>false</literal>, specifying a partitioned table or non-leaf
> + partition has no effect
>
> Can we simply say 'specifying a root partitioned table has no effect'.
> This will make it consistent as the previous sentence also uses the
> same term rather than 'non-leaf'.
>
> 4)
> tab_root is a partitioned table with tab_part_1 and tab_part_2 as its
> partitions.
> In the first case, I receive a WARNING because the user excluded
> tab_part_2 but its data will still be replicated through the root
> table:
>
> postgres=# create publication pub3 for all tables except (tab_part_2)
> WITH (publish_via_partition_root=true);
> WARNING: partition "tab_part_2" will be replicated as
> publish_via_partition_root is "true"
>
> But in the following case, no WARNING is shown:
> postgres=# create publication pub4 for all tables except (tab_root)
> WITH (publish_via_partition_root=false);
> CREATE PUBLICATION
>
> In this scenario, the user has excluded the root table, yet its data
> will still be replicated because publish_via_partition_root = false.
> Should we emit a warning in this case as well? Thoughts?
>
> 5)
> publication_add_relation:
> + if (pub->alltables && pri->except && targetrel->rd_rel->relispartition &&
> + pub->pubviaroot)
>
> Can we please bring both the 'pub' conditions together, as that seems
> more understandable:
> if (pub->alltables && pub->pubviaroot &&...)
>
> 6)
> We have added pubid as argument to GetAllPublicationRelations to
> exclude except-list tables.
> We should change comment atop GetAllPublicationRelations() to indicate
> the same. We should extend
> this existing comment to say about except-list exclusion also.
>
> * If the publication publishes partition changes via their respective root
> * partitioned tables, we must exclude partitions in favor of including the
> * root partitioned tables.
>
Hi Shveta,

I have addressed the above comments and attached the updated patch.
I have also addressed a comment by Peter (comment no. 20 in [1]) which
I missed in the earlier version.

[1]: https://www.postgresql.org/message-id/CAHut%2BPudi%2B9ssBR_Q_Fd29aGEu8s18OyKUGo5w5aKJK-2_c%2B8g%40mail.gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v31-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 66.4 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-10 22:39:33
Message-ID: CAHut+Pu5Ukuvd_5oK_mTEjSOEAYupbEXzRqXwSPoLe_sDkA_fg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok -

Here are some review comments for v31-0001 (EXCEPT (tablelist))

======
Commit message

1.
The new syntax allows specifying excluded relations when creating or altering
a publication. For example:
CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE (t1,t2);

~

In v30, you removed all the ALTER PUBLICATION changes, so the "or
altering" in the message above also needs to be removed.

======
doc/src/sgml/logical-replication.sgml

2.
<para>
- To add tables to a publication, the user must have ownership rights on the
- table. To add all tables in schema to a publication, the user must be a
- superuser. To create a publication that publishes all tables, all tables in
- schema, or all sequences automatically, the user must be a superuser.
+ To create a publication using <literal>FOR ALL TABLES</literal>,
+ <literal>FOR ALL SEQUENCES</literal> or
+ <literal>FOR TABLES IN SCHEMA</literal>, the user must be a
superuser. To add
+ <literal>ALL TABLES</literal> or <literal>TABLES IN SCHEMA</literal> to a
+ publication, the user must be a superuser. To add tables to a publication,
+ the user must have ownership rights on the table.
</para>

This is a good improvement, but I was not sure why it is in this
patch. Should it be a separate thread for a docs improvement?

======
src/backend/catalog/pg_publication.c

GetTopMostAncestorInPublication:

3.
{
Oid ancestor = lfirst_oid(lc);
- List *apubids = GetRelationPublications(ancestor);
- List *aschemaPubids = NIL;
+ List *apubids = NIL;
+ List *aexceptpubids = NIL;
+ List *aschemapubids = NIL;
+ bool set_top = false;
+
+ GetRelationPublications(ancestor, &apubids, &aexceptpubids);

level++;

- if (list_member_oid(apubids, puboid))
+ /* check if member of table publications */
+ set_top = list_member_oid(apubids, puboid);
+ if (!set_top)
{
- topmost_relid = ancestor;
+ aschemapubids = GetSchemaPublications(get_rel_namespace(ancestor));

- if (ancestor_level)
- *ancestor_level = level;
+ /* check if member of schema publications */
+ set_top = list_member_oid(aschemapubids, puboid);
+
+ /*
+ * If the publication is all tables publication and the table is
+ * not part of exception tables.
+ */
+ if (!set_top && puballtables)
+ set_top = !list_member_oid(aexceptpubids, puboid);
}
- else
+
+ if (set_top)
{
- aschemaPubids = GetSchemaPublications(get_rel_namespace(ancestor));
- if (list_member_oid(aschemaPubids, puboid))
- {
- topmost_relid = ancestor;
+ topmost_relid = ancestor;

- if (ancestor_level)
- *ancestor_level = level;
- }
+ if (ancestor_level)
+ *ancestor_level = level;
}

list_free(apubids);
- list_free(aschemaPubids);
+ list_free(aschemapubids);
+ list_free(aexceptpubids);
}

That 'aschemapubids' can be declared and freed within the if block.

~~~

publication_add_relation:

4.
+ /*
+ * Check when a partition is excluded via EXCEPT TABLE while the
+ * publication has publish_via_partition_root = true.
+ */
+ if (pub->alltables && pub->pubviaroot && pri->except &&
+ targetrel->rd_rel->relispartition)
+ ereport(WARNING,

This comment doesn't sound quite right:

SUGGESTION
Handle the case where a partition is excluded by EXCEPT TABLE while
publish_via_partition_root = true.

~~~

5.
+ /*
+ * Check when a partitioned table is excluded via EXCEPT TABLE while the
+ * publication has publish_via_partition_root = false.
+ */
+ if (pub->alltables && !pub->pubviaroot && pri->except &&
+ targetrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ ereport(WARNING,

Ditto. Reword like suggested in the previous review comment.

~~~

6.
+/*
+ * Get the list of publication oids associated with a specified relation.
+ * pubids is filled with the list of publication oids the relation is part of.
+ * except_pubids is filled with the list of publication oids the relation is
+ * excluded from.
+ *
+ * This function returns true if the relation is part of any publication.
+ */

Maybe putting 'pubids' and 'except_pubids' in single quotes will help
readability of this comment?

Also, these are already Lists, so they are not filled with lists.

SUGGESTION
Parameter 'pubids' returns the OIDs of the publications the relation is part of.
Parameter 'except_pubids' returns the OIDs of publications the
relation is excluded from.

~~~

GetPublicationRelations:

7.
/*
- * Gets list of relation oids for a publication.
+ * Return the list of relation OIDs for a publication.
+ *
+ * For a FOR ALL TABLES publication, this returns the list of tables that were
+ * explicitly excluded via an EXCEPT TABLE clause.
+ *
+ * For a FOR TABLE publication, this returns the list of tables explicitly
+ * included in the publication.
*
- * This should only be used FOR TABLE publications, the FOR ALL
TABLES/SEQUENCES
- * should use GetAllPublicationRelations().
+ * Publications declared with FOR ALL TABLES or FOR ALL SEQUENCES should use
+ * GetAllPublicationRelations() to obtain the complete set of tables covered by
+ * the publication.
*/
List *
GetPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt)

7a.
The function is called 'GetPublicationRelations', so it seems
unintuitive that it sometimes returns the list of all the tables that
are *excluded* from the publication. If you are going to have one
single function that does everything, then IMO it might be better to
hide that behind some wrapper functions like:
GetPublicationMemberRelations
GetPublicationExcludedRelations

Consider also that all these assumptions might be OK today but they
won't be OK in the future. e.g. One day, when named FOR SEQUENCE
sq1,sq2 are supported then you will be alble to write a command like
FOR ALL TABLES EXCEPT (t1), FOR SEQUENCE sq1,sq2. That's going to be a
muddle of some included and some excluded relations. So, it is better
to cater for that scenario now, rather than have to rewrite all of
this function again in the future. e.g. Maybe instead of this function
returning one list it is better to return included/excluded Lists or
relations as output parameters?

~

7b.
Also, comments like "Publications declared with FOR ALL TABLES or FOR
ALL SEQUENCES should use..." seems like too many assumptions are being
made. It would be better to enforce the calling requirements using
parameter checking and Asserts instead instead of hoping that callers
are going to abide by the comments.

~~~

GetAllPublicationRelations:

8.
+ exceptlist = GetPublicationRelations(pubid, pubviaroot ?
+ PUBLICATION_PART_ALL :
+ PUBLICATION_PART_ROOT);

This is similar to the above review comment. I'm not sure how you can
just assume that this must be the "except list" -- AFAICT this assumes
that 'GetAllPublicationRelations' can only be called by FOR ALL TABLES
(???). Seems like a lot of assumptions, that would be much better to
be enforced by Asserts in the code.

======
src/backend/commands/publicationcmds.c

pub_rf_contains_invalid_column:

9.
bool
pub_rf_contains_invalid_column(Oid pubid, Relation relation, List *ancestors,
- bool pubviaroot)
+ bool pubviaroot, bool puballtables)

I felt that 'puballtables' is more "important" than 'pubviaroot' so
maybe it should come earlier in the parameter list. (e.g. make it more
similar to 'pub_contains_invalid_column')

======
src/backend/parser/gram.y

10.
+ pub_except_obj_list opt_except_clause

I felt that 'opt_except_clause' should better be called
'opt_pub_except_clause' or 'pub_opt_except_clause' because without
'pub' it is a bit vague.

~~~

11.
+/*
+ * ALL TABLES EXCEPT ( table_name [, ...] ) specification
+ */

11a
This comment should be up where all the other CREATE PUBLICATION
syntax is commented.

~

11b.
Also, there is a missing optional "[TABLE]" part.

~~~

12.
+pub_except_obj_list: PublicationExceptObjSpec
+ { $$ = list_make1($1); }
+ | pub_except_obj_list ',' PublicationExceptObjSpec
+ { $$ = lappend($1, $3); }
+ ;
+
+opt_except_clause:
+ EXCEPT opt_table '(' pub_except_obj_list ')' { $$ = $4; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;

I felt the clause should be defined before the obj list because that
seems the natural order to read these.

======
src/bin/pg_dump/pg_dump.c

13.
+static SimplePtrList exceptinfo = {NULL, NULL};

Having this as global seems a bit hacky. It has nothing in common with
all the other nearby lists, which are commented as being based on
"patterns given by command-line switches"

~~~

dumpPublication:

14.
+ /* Include exception tables if the publication has EXCEPT TABLEs */
+ for (SimplePtrListCell *cell = exceptinfo.head; cell; cell = cell->next)
+ {
+ PublicationRelInfo *pubrinfo = (PublicationRelInfo *) cell->ptr;
+ TableInfo *tbinfo;
+
+ if (pubinfo == pubrinfo->publication)
+ {
+ tbinfo = pubrinfo->pubtable;

That 'tbinfo' can be declared within the "if".

~~~

15.
+ appendPQExpBuffer(query, "ONLY %s", fmtQualifiedDumpable(tbinfo));

ONLY is not the default. How did you decide that "ONLY" is the correct
thing to do here?

~~~

getPublicationTables:

16.
- pubrinfo[j].dobj.objType = DO_PUBLICATION_REL;
+ if (prexcept)
+ pubrinfo[j].dobj.objType = DO_PUBLICATION_EXCEPT_REL;
+ else
+ pubrinfo[j].dobj.objType = DO_PUBLICATION_REL;
+

Would a single assignment (ternary) make this code simpler and easier to read?

SUGGESTION
pubrinfo[j].dobj.objType = prexcept ?
DO_PUBLICATION_EXCEPT_REL :
DO_PUBLICATION_REL;

======
src/bin/pg_dump/t/002_pg_dump.pl

17.
+ 'CREATE PUBLICATION pub10' => {
+ create_order => 50,
+ create_sql =>
+ 'CREATE PUBLICATION pub10 FOR ALL TABLES EXCEPT TABLE
(dump_test.test_table_generated);',
+ regexp => qr/^
+ \QCREATE PUBLICATION pub10 FOR ALL TABLES EXCEPT TABLE (ONLY
dump_test.test_table_generated, ONLY
dump_test.test_table_generated_child2, ONLY
dump_test.test_table_generated_child1) WITH (publish = 'insert,
update, delete, truncate');\E
+ /xm,
+ like => { %full_runs, section_post_data => 1, },
+ },
+

These "generated" names seem unusual. I saw there are some other
tables like 'dump_test.test_inheritance_child' and
'dump_test.test_inheritance_parent'. Can you use those more normal
table names instead?

Also curious - does the order of the tests matter? I saw that the
CREATE TABLE tests seem to be coming after the CREATE PUBLICATION
tests that are using them.

~~~
18.
- if (!defined($tests{$test}->{all_runs})
+ if ( !defined($tests{$test}->{all_runs})

Why add this whitespace?

======
src/include/nodes/parsenodes.h

19.
AP_SetObjects, /* set list of objects */
+ AP_Reset, /* reset the publication */
} AlterPublicationAction;

AFAIK, you removed all ALTER command changes from v30-0001. So this
should not be here.

~~~

20.
+ bool for_all_tables; /* Special publication for all tables in db */
AlterPublicationAction action; /* What action to perform with the given
* objects */
} AlterPublicationStmt;

AFAIK, you removed all ALTER command changes from v30-0001. So this
should not be here.

======
src/test/regress/sql/publication.sql

21.
+SET client_min_messages = 'ERROR';
+CREATE PUBLICATION testpub_foralltables_excepttable FOR ALL TABLES
EXCEPT TABLE (testpub_tbl1, testpub_tbl2);
+-- specify EXCEPT without TABLE
+CREATE PUBLICATION testpub_foralltables_excepttable1 FOR ALL TABLES
EXCEPT (testpub_tbl1);

Should be 2 comments here for the 2x CREATE:

# Exclude tables using FOR ALL TABLES EXCEPT TABLE (tablelist)

# Exclude tables using FOR ALL TABLES EXCEPT (tablelist)

~~~

22.
CREATE TABLE testpub_tbl3 (a int);
CREATE TABLE testpub_tbl3a (b text) INHERITS (testpub_tbl3);

If you rename these tables like 'testpub_tbl_parent' and
'testpub_tbl_child', it will be much easier to see what is going on.

~~~

23.
+CREATE PUBLICATION testpub5 FOR ALL TABLES EXCEPT TABLE (testpub_tbl3);

Missing comment -- something like:
# Exclude parent table, omitting both of 'ONLY' and '*'

~~~

24.
+-- EXCEPT with wildcard: exclude table and all descendants
+CREATE PUBLICATION testpub6 FOR ALL TABLES EXCEPT TABLE (testpub_tbl3*);

24a.
TBH, I don't think this is a "wildcard" -- it is not doing any pattern
matching. IMO just call it an "asterisk" or a "star".

~

24b.
And put a space before the '*' here.

======
.../t/037_rep_changes_except_table.pl

25.
+# ============================================
+# EXCEPT TABLE test cases for partition tables
+# ============================================
+# Check behavior of EXCEPT TABLE together with publish_via_partition_root
+# when applied to a partitioned table and its partitions.

Really, that "Check behavior" sentence is generic for all of the
following tests, so it should also be (within the "=======" of the
previous comment)

~~~

26.
+$node_publisher->safe_psql(
+ 'postgres', qq(
+ CREATE TABLE sch1.t1(a int) PARTITION BY RANGE(a);
+ CREATE TABLE sch1.part1 PARTITION OF sch1.t1 FOR VALUES FROM (0) TO (5);
+ CREATE TABLE sch1.part2 PARTITION OF sch1.t1 FOR VALUES FROM (6) TO (10);
+ INSERT INTO sch1.t1 VALUES (1), (6);
+));
+
+$node_subscriber->safe_psql(
+ 'postgres', qq(
+ CREATE TABLE sch1.t1(a int);
+ CREATE TABLE sch1.part1(a int);
+ CREATE TABLE sch1.part2(a int);
+));

26a.
There should be a comment for this part that just says something like
"Setup partition table and partitions on the publisher that map to
normal tables on the subscriber"

~

26b.
The INSERT should be done later, after the CREATE PUBLICATION but
before the CREATE SUBSCRIPTION. The pattern will be the same for all
the test cases.

~~~

27.
+$node_publisher->safe_psql('postgres',
+ "CREATE PUBLICATION tap_pub_part FOR ALL TABLES EXCEPT TABLE (sch1.part1)"
+);

Even though the publish_via_partition_root is 'false' by default, I
think you should spell it out explicitly here for clarity.

~~~

28.
+# EXCEPT TABLE (sch1.t1) with publish_via_partition_root = false
+# Excluding the partitioned table while publish_via_partition_root = false
+# still allows rows inserted into its partitions to be replicated.

I felt you should word this differently. I don't think you should say
"inserted into its partitions" because actually, you inserted into the
partition table, and the data just ends up in the partitions.

~~~

29.
+$node_publisher->safe_psql(
+ 'postgres', qq(
+ CREATE PUBLICATION tap_pub_part FOR ALL TABLES EXCEPT TABLE (sch1.t1);
+ INSERT INTO sch1.t1 VALUES (1), (6);
+));

Ditto earlier comment. Better to explicitly say
"publish_via_partition_root=false".

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-10 23:01:13
Message-ID: CAHut+PvGpMRQ4crU5PN-zSO6iUg5B-3wzB0_h9=fPdQ-5-S9Pg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Dec 10, 2025 at 4:49 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> On Mon, 24 Nov 2025 at 13:03, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >
...
> > 21.
> > I was wondering if the "describe" for tables (e.g. \d+) should also
> > show the publications where the table is an ECEPT TABLE? How else is
> > the user going to know it has been excluded by some publication?
> >
> I thought it would be sufficient to show only the list of
> publications, the table is part of.
> Users can check the excluded tables by checking the description of the
> publication using \dRp+.
> Will it be not sufficient?
> I am not sure why we should show a list of publications which it is not part of?
> Am I missing something thoughts?

For this comment, I was imagining a scenario where there are dozens of
publications, and the user is wondering why their table is not being
replicated to the subscriber like they expected it would be.

Yes, they could use \dRs+ to identify the publications excluding it,
but that will be quite painful if there are very many publications
they have to check. IIUC, there is no other way to check it without
digging into System Catalogs.

That's why I thought it might be useful if the \d+ could also show
publications where the table was named in an EXCEPT TABLE clause.

======
Kind Regards,
Peter Smith.
Fujitsu Australia.


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-16 09:20:41
Message-ID: CANhcyEWg2WbEW_fFwk0D3J2KBrUF7th6VrE+gvESgkUKP9VpZg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 11 Dec 2025 at 04:10, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok -
>
> Here are some review comments for v31-0001 (EXCEPT (tablelist))
>
> ======
> Commit message
>
> 1.
> The new syntax allows specifying excluded relations when creating or altering
> a publication. For example:
> CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE (t1,t2);
>
> ~
>
> In v30, you removed all the ALTER PUBLICATION changes, so the "or
> altering" in the message above also needs to be removed.
>
> ======
> doc/src/sgml/logical-replication.sgml
>
> 2.
> <para>
> - To add tables to a publication, the user must have ownership rights on the
> - table. To add all tables in schema to a publication, the user must be a
> - superuser. To create a publication that publishes all tables, all tables in
> - schema, or all sequences automatically, the user must be a superuser.
> + To create a publication using <literal>FOR ALL TABLES</literal>,
> + <literal>FOR ALL SEQUENCES</literal> or
> + <literal>FOR TABLES IN SCHEMA</literal>, the user must be a
> superuser. To add
> + <literal>ALL TABLES</literal> or <literal>TABLES IN SCHEMA</literal> to a
> + publication, the user must be a superuser. To add tables to a publication,
> + the user must have ownership rights on the table.
> </para>
>
> This is a good improvement, but I was not sure why it is in this
> patch. Should it be a separate thread for a docs improvement?
>
> ======
> src/backend/catalog/pg_publication.c
>
> GetTopMostAncestorInPublication:
>
> 3.
> {
> Oid ancestor = lfirst_oid(lc);
> - List *apubids = GetRelationPublications(ancestor);
> - List *aschemaPubids = NIL;
> + List *apubids = NIL;
> + List *aexceptpubids = NIL;
> + List *aschemapubids = NIL;
> + bool set_top = false;
> +
> + GetRelationPublications(ancestor, &apubids, &aexceptpubids);
>
> level++;
>
> - if (list_member_oid(apubids, puboid))
> + /* check if member of table publications */
> + set_top = list_member_oid(apubids, puboid);
> + if (!set_top)
> {
> - topmost_relid = ancestor;
> + aschemapubids = GetSchemaPublications(get_rel_namespace(ancestor));
>
> - if (ancestor_level)
> - *ancestor_level = level;
> + /* check if member of schema publications */
> + set_top = list_member_oid(aschemapubids, puboid);
> +
> + /*
> + * If the publication is all tables publication and the table is
> + * not part of exception tables.
> + */
> + if (!set_top && puballtables)
> + set_top = !list_member_oid(aexceptpubids, puboid);
> }
> - else
> +
> + if (set_top)
> {
> - aschemaPubids = GetSchemaPublications(get_rel_namespace(ancestor));
> - if (list_member_oid(aschemaPubids, puboid))
> - {
> - topmost_relid = ancestor;
> + topmost_relid = ancestor;
>
> - if (ancestor_level)
> - *ancestor_level = level;
> - }
> + if (ancestor_level)
> + *ancestor_level = level;
> }
>
> list_free(apubids);
> - list_free(aschemaPubids);
> + list_free(aschemapubids);
> + list_free(aexceptpubids);
> }
>
> That 'aschemapubids' can be declared and freed within the if block.
>
> ~~~
>
> publication_add_relation:
>
> 4.
> + /*
> + * Check when a partition is excluded via EXCEPT TABLE while the
> + * publication has publish_via_partition_root = true.
> + */
> + if (pub->alltables && pub->pubviaroot && pri->except &&
> + targetrel->rd_rel->relispartition)
> + ereport(WARNING,
>
>
> This comment doesn't sound quite right:
>
> SUGGESTION
> Handle the case where a partition is excluded by EXCEPT TABLE while
> publish_via_partition_root = true.
>
> ~~~
>
> 5.
> + /*
> + * Check when a partitioned table is excluded via EXCEPT TABLE while the
> + * publication has publish_via_partition_root = false.
> + */
> + if (pub->alltables && !pub->pubviaroot && pri->except &&
> + targetrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
> + ereport(WARNING,
>
> Ditto. Reword like suggested in the previous review comment.
>
> ~~~
>
> 6.
> +/*
> + * Get the list of publication oids associated with a specified relation.
> + * pubids is filled with the list of publication oids the relation is part of.
> + * except_pubids is filled with the list of publication oids the relation is
> + * excluded from.
> + *
> + * This function returns true if the relation is part of any publication.
> + */
>
> Maybe putting 'pubids' and 'except_pubids' in single quotes will help
> readability of this comment?
>
> Also, these are already Lists, so they are not filled with lists.
>
> SUGGESTION
> Parameter 'pubids' returns the OIDs of the publications the relation is part of.
> Parameter 'except_pubids' returns the OIDs of publications the
> relation is excluded from.
>
> ~~~
>
> GetPublicationRelations:
>
> 7.
> /*
> - * Gets list of relation oids for a publication.
> + * Return the list of relation OIDs for a publication.
> + *
> + * For a FOR ALL TABLES publication, this returns the list of tables that were
> + * explicitly excluded via an EXCEPT TABLE clause.
> + *
> + * For a FOR TABLE publication, this returns the list of tables explicitly
> + * included in the publication.
> *
> - * This should only be used FOR TABLE publications, the FOR ALL
> TABLES/SEQUENCES
> - * should use GetAllPublicationRelations().
> + * Publications declared with FOR ALL TABLES or FOR ALL SEQUENCES should use
> + * GetAllPublicationRelations() to obtain the complete set of tables covered by
> + * the publication.
> */
> List *
> GetPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt)
>
> 7a.
> The function is called 'GetPublicationRelations', so it seems
> unintuitive that it sometimes returns the list of all the tables that
> are *excluded* from the publication. If you are going to have one
> single function that does everything, then IMO it might be better to
> hide that behind some wrapper functions like:
> GetPublicationMemberRelations
> GetPublicationExcludedRelations
>
> Consider also that all these assumptions might be OK today but they
> won't be OK in the future. e.g. One day, when named FOR SEQUENCE
> sq1,sq2 are supported then you will be alble to write a command like
> FOR ALL TABLES EXCEPT (t1), FOR SEQUENCE sq1,sq2. That's going to be a
> muddle of some included and some excluded relations. So, it is better
> to cater for that scenario now, rather than have to rewrite all of
> this function again in the future. e.g. Maybe instead of this function
> returning one list it is better to return included/excluded Lists or
> relations as output parameters?
>
> ~
>
> 7b.
> Also, comments like "Publications declared with FOR ALL TABLES or FOR
> ALL SEQUENCES should use..." seems like too many assumptions are being
> made. It would be better to enforce the calling requirements using
> parameter checking and Asserts instead instead of hoping that callers
> are going to abide by the comments.
>
> ~~~
>
> GetAllPublicationRelations:
>
> 8.
> + exceptlist = GetPublicationRelations(pubid, pubviaroot ?
> + PUBLICATION_PART_ALL :
> + PUBLICATION_PART_ROOT);
>
> This is similar to the above review comment. I'm not sure how you can
> just assume that this must be the "except list" -- AFAICT this assumes
> that 'GetAllPublicationRelations' can only be called by FOR ALL TABLES
> (???). Seems like a lot of assumptions, that would be much better to
> be enforced by Asserts in the code.
>
I agree with comments 7 and 8. I have added two functions
'GetPublicationIncludedRelations' and
'GetPublicationExcludedRelations'. To get Relations which are included
or excluded in a publication.
Both functions will call 'GetPublicationRelationsInternal' function. I
have also reintroduced the 'except_flag' variable

> ======
> src/backend/commands/publicationcmds.c
>
> pub_rf_contains_invalid_column:
>
> 9.
> bool
> pub_rf_contains_invalid_column(Oid pubid, Relation relation, List *ancestors,
> - bool pubviaroot)
> + bool pubviaroot, bool puballtables)
>
> I felt that 'puballtables' is more "important" than 'pubviaroot' so
> maybe it should come earlier in the parameter list. (e.g. make it more
> similar to 'pub_contains_invalid_column')
>
> ======
> src/backend/parser/gram.y
>
> 10.
> + pub_except_obj_list opt_except_clause
>
> I felt that 'opt_except_clause' should better be called
> 'opt_pub_except_clause' or 'pub_opt_except_clause' because without
> 'pub' it is a bit vague.
>
I agree. I prefer 'opt_pub_except_clause'. By looking at other
variables it better make sense to start the variable name with 'opt_'
as it indicates that it is optional.
Made changes for the same.

> ~~~
>
> 11.
> +/*
> + * ALL TABLES EXCEPT ( table_name [, ...] ) specification
> + */
>
> 11a
> This comment should be up where all the other CREATE PUBLICATION
> syntax is commented.
>
> ~
>
> 11b.
> Also, there is a missing optional "[TABLE]" part.
>
> ~~~
>
> 12.
> +pub_except_obj_list: PublicationExceptObjSpec
> + { $$ = list_make1($1); }
> + | pub_except_obj_list ',' PublicationExceptObjSpec
> + { $$ = lappend($1, $3); }
> + ;
> +
> +opt_except_clause:
> + EXCEPT opt_table '(' pub_except_obj_list ')' { $$ = $4; }
> + | /*EMPTY*/ { $$ = NIL; }
> + ;
>
> I felt the clause should be defined before the obj list because that
> seems the natural order to read these.
>
> ======
> src/bin/pg_dump/pg_dump.c
>
> 13.
> +static SimplePtrList exceptinfo = {NULL, NULL};
>
> Having this as global seems a bit hacky. It has nothing in common with
> all the other nearby lists, which are commented as being based on
> "patterns given by command-line switches"
>
I agree, I have added it in the PublicationInfo struct and made the
corresponding code changes.

> ~~~
>
> dumpPublication:
>
> 14.
> + /* Include exception tables if the publication has EXCEPT TABLEs */
> + for (SimplePtrListCell *cell = exceptinfo.head; cell; cell = cell->next)
> + {
> + PublicationRelInfo *pubrinfo = (PublicationRelInfo *) cell->ptr;
> + TableInfo *tbinfo;
> +
> + if (pubinfo == pubrinfo->publication)
> + {
> + tbinfo = pubrinfo->pubtable;
>
> That 'tbinfo' can be declared within the "if".
>
> ~~~
>
> 15.
> + appendPQExpBuffer(query, "ONLY %s", fmtQualifiedDumpable(tbinfo));
>
> ONLY is not the default. How did you decide that "ONLY" is the correct
> thing to do here?
>
For pg_dump for publication we use "ONLY" by default while specifying the table

For Alter publication we use similar thing:
```
appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD TABLE ONLY",
fmtId(pubinfo->dobj.name));
```

Also if we specify a parent table in a publication(without ONLY) all
its child tables are also added to the pg_publication_rel table.
So when we dump such a publication we get something like:
.... EXCEPT TABLE(ONLY parent_table, ONLY child_table)...

> ~~~
>
> getPublicationTables:
>
> 16.
> - pubrinfo[j].dobj.objType = DO_PUBLICATION_REL;
> + if (prexcept)
> + pubrinfo[j].dobj.objType = DO_PUBLICATION_EXCEPT_REL;
> + else
> + pubrinfo[j].dobj.objType = DO_PUBLICATION_REL;
> +
>
> Would a single assignment (ternary) make this code simpler and easier to read?
>
> SUGGESTION
> pubrinfo[j].dobj.objType = prexcept ?
> DO_PUBLICATION_EXCEPT_REL :
> DO_PUBLICATION_REL;
>
> ======
> src/bin/pg_dump/t/002_pg_dump.pl
>
> 17.
> + 'CREATE PUBLICATION pub10' => {
> + create_order => 50,
> + create_sql =>
> + 'CREATE PUBLICATION pub10 FOR ALL TABLES EXCEPT TABLE
> (dump_test.test_table_generated);',
> + regexp => qr/^
> + \QCREATE PUBLICATION pub10 FOR ALL TABLES EXCEPT TABLE (ONLY
> dump_test.test_table_generated, ONLY
> dump_test.test_table_generated_child2, ONLY
> dump_test.test_table_generated_child1) WITH (publish = 'insert,
> update, delete, truncate');\E
> + /xm,
> + like => { %full_runs, section_post_data => 1, },
> + },
> +
>
> These "generated" names seem unusual. I saw there are some other
> tables like 'dump_test.test_inheritance_child' and
> 'dump_test.test_inheritance_parent'. Can you use those more normal
> table names instead?
>
> Also curious - does the order of the tests matter? I saw that the
> CREATE TABLE tests seem to be coming after the CREATE PUBLICATION
> tests that are using them.
>
I looked into it and came to the conclusion that this is controlled
using 'create_order' while specifying the tests.
Tests with a lower create_order value are executed earlier.
So to ensure 'CREATE PUBLICATION' runs correctly we have to make sure
the 'create_order' of these statements is higher than that of the
respective 'CREATE TABLE' statement.

> ~~~
> 18.
> - if (!defined($tests{$test}->{all_runs})
> + if ( !defined($tests{$test}->{all_runs})
>
> Why add this whitespace?
>
pg_perltidy makes this change. I have reverted it.

> ======
> src/include/nodes/parsenodes.h
>
> 19.
> AP_SetObjects, /* set list of objects */
> + AP_Reset, /* reset the publication */
> } AlterPublicationAction;
>
> AFAIK, you removed all ALTER command changes from v30-0001. So this
> should not be here.
>
> ~~~
>
> 20.
> + bool for_all_tables; /* Special publication for all tables in db */
> AlterPublicationAction action; /* What action to perform with the given
> * objects */
> } AlterPublicationStmt;
>
> AFAIK, you removed all ALTER command changes from v30-0001. So this
> should not be here.
>
> ======
> src/test/regress/sql/publication.sql
>
> 21.
> +SET client_min_messages = 'ERROR';
> +CREATE PUBLICATION testpub_foralltables_excepttable FOR ALL TABLES
> EXCEPT TABLE (testpub_tbl1, testpub_tbl2);
> +-- specify EXCEPT without TABLE
> +CREATE PUBLICATION testpub_foralltables_excepttable1 FOR ALL TABLES
> EXCEPT (testpub_tbl1);
>
> Should be 2 comments here for the 2x CREATE:
>
> # Exclude tables using FOR ALL TABLES EXCEPT TABLE (tablelist)
>
> # Exclude tables using FOR ALL TABLES EXCEPT (tablelist)
>
> ~~~
>
> 22.
> CREATE TABLE testpub_tbl3 (a int);
> CREATE TABLE testpub_tbl3a (b text) INHERITS (testpub_tbl3);
>
> If you rename these tables like 'testpub_tbl_parent' and
> 'testpub_tbl_child', it will be much easier to see what is going on.
>
> ~~~
>
> 23.
> +CREATE PUBLICATION testpub5 FOR ALL TABLES EXCEPT TABLE (testpub_tbl3);
>
> Missing comment -- something like:
> # Exclude parent table, omitting both of 'ONLY' and '*'
>
> ~~~
>
> 24.
> +-- EXCEPT with wildcard: exclude table and all descendants
> +CREATE PUBLICATION testpub6 FOR ALL TABLES EXCEPT TABLE (testpub_tbl3*);
>
> 24a.
> TBH, I don't think this is a "wildcard" -- it is not doing any pattern
> matching. IMO just call it an "asterisk" or a "star".
>
> ~
>
> 24b.
> And put a space before the '*' here.
>
> ======
> .../t/037_rep_changes_except_table.pl
>
> 25.
> +# ============================================
> +# EXCEPT TABLE test cases for partition tables
> +# ============================================
> +# Check behavior of EXCEPT TABLE together with publish_via_partition_root
> +# when applied to a partitioned table and its partitions.
>
>
> Really, that "Check behavior" sentence is generic for all of the
> following tests, so it should also be (within the "=======" of the
> previous comment)
>
> ~~~
>
> 26.
> +$node_publisher->safe_psql(
> + 'postgres', qq(
> + CREATE TABLE sch1.t1(a int) PARTITION BY RANGE(a);
> + CREATE TABLE sch1.part1 PARTITION OF sch1.t1 FOR VALUES FROM (0) TO (5);
> + CREATE TABLE sch1.part2 PARTITION OF sch1.t1 FOR VALUES FROM (6) TO (10);
> + INSERT INTO sch1.t1 VALUES (1), (6);
> +));
> +
> +$node_subscriber->safe_psql(
> + 'postgres', qq(
> + CREATE TABLE sch1.t1(a int);
> + CREATE TABLE sch1.part1(a int);
> + CREATE TABLE sch1.part2(a int);
> +));
>
> 26a.
> There should be a comment for this part that just says something like
> "Setup partition table and partitions on the publisher that map to
> normal tables on the subscriber"
>
> ~
>
> 26b.
> The INSERT should be done later, after the CREATE PUBLICATION but
> before the CREATE SUBSCRIPTION. The pattern will be the same for all
> the test cases.
>
> ~~~
>
> 27.
> +$node_publisher->safe_psql('postgres',
> + "CREATE PUBLICATION tap_pub_part FOR ALL TABLES EXCEPT TABLE (sch1.part1)"
> +);
>
> Even though the publish_via_partition_root is 'false' by default, I
> think you should spell it out explicitly here for clarity.
>
> ~~~
>
> 28.
> +# EXCEPT TABLE (sch1.t1) with publish_via_partition_root = false
> +# Excluding the partitioned table while publish_via_partition_root = false
> +# still allows rows inserted into its partitions to be replicated.
>
> I felt you should word this differently. I don't think you should say
> "inserted into its partitions" because actually, you inserted into the
> partition table, and the data just ends up in the partitions.
>
> ~~~
>
> 29.
> +$node_publisher->safe_psql(
> + 'postgres', qq(
> + CREATE PUBLICATION tap_pub_part FOR ALL TABLES EXCEPT TABLE (sch1.t1);
> + INSERT INTO sch1.t1 VALUES (1), (6);
> +));
>
> Ditto earlier comment. Better to explicitly say
> "publish_via_partition_root=false".
>
I have also addressed the remaining comments and attached the latest patch.

Thanks,
Shlok Kyal

Attachment Content-Type Size
v32-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 71.4 KB

From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-16 09:21:18
Message-ID: CANhcyEXp_AH-oms=psQ3jkMdvd9kp57d-6f7=8yuz_EX0VTa7g@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 11 Dec 2025 at 04:31, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> On Wed, Dec 10, 2025 at 4:49 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > On Mon, 24 Nov 2025 at 13:03, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> > >
> ...
> > > 21.
> > > I was wondering if the "describe" for tables (e.g. \d+) should also
> > > show the publications where the table is an ECEPT TABLE? How else is
> > > the user going to know it has been excluded by some publication?
> > >
> > I thought it would be sufficient to show only the list of
> > publications, the table is part of.
> > Users can check the excluded tables by checking the description of the
> > publication using \dRp+.
> > Will it be not sufficient?
> > I am not sure why we should show a list of publications which it is not part of?
> > Am I missing something thoughts?
>
> For this comment, I was imagining a scenario where there are dozens of
> publications, and the user is wondering why their table is not being
> replicated to the subscriber like they expected it would be.
>
> Yes, they could use \dRs+ to identify the publications excluding it,
> but that will be quite painful if there are very many publications
> they have to check. IIUC, there is no other way to check it without
> digging into System Catalogs.
>
> That's why I thought it might be useful if the \d+ could also show
> publications where the table was named in an EXCEPT TABLE clause.
>
I thought more about this point and it can be useful. I have added the
changes for the same in the latest patch in [1].

[1]: https://www.postgresql.org/message-id/CANhcyEWg2WbEW_fFwk0D3J2KBrUF7th6VrE%2BgvESgkUKP9VpZg%40mail.gmail.com

Thanks,
Shlok Kyal


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-17 05:54:23
Message-ID: CAJpy0uBegaytfG=AS5VUb-6jAEDzC374-1icn-hP5AnRoMJ+Lg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Dec 16, 2025 at 2:50 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> I have also addressed the remaining comments and attached the latest patch.
>

Thanks. A few comments:

1)
+ if (!set_top && puballtables)
+ set_top = !list_member_oid(aexceptpubids, puboid);

In GetTopMostAncestorInPublication(), we have made the above change
which will now get ancestor from all-tables publication as well,
provided table is not part of 'except' List. Earlier this function was
only checking pg_subscription_rel and pg_publication_namespace which
does not include all-tables publication. Won't it change the
result-set for callers?

2)
+ * Publications declared with FOR ALL TABLES or FOR ALL SEQUENCES should use
+ * GetAllPublicationRelations() to obtain the complete set of tables covered by
+ * the publication.
+ */
+List *
+GetPublicationIncludedRelations(Oid pubid, PublicationPartOpt pub_partopt)
+{
+ return GetPublicationRelationsInternal(pubid, pub_partopt, false);
+}

We can have an Assert here that pubid passed is not for ALL-Tables or
ALL-sequences

3)
GetAllPublicationRelations:
* If the publication publishes partition changes via their respective root
* partitioned tables, we must exclude partitions in favor of including the
* root partitioned tables. This is not applicable to FOR ALL SEQUENCES
* publication.

+ * The list does not include relations that are explicitly excluded via the
+ * EXCEPT TABLE clause of the publication specified by pubid.

Suggestion:
/*
* If the publication publishes partition changes via their respective root
* partitioned tables, we must exclude partitions in favor of including the
* root partitioned tables. The list also excludes tables that are
* explicitly excluded via the EXCEPT TABLE clause of the publication
* identified by pubid. Neither of these rules applies to FOR ALL SEQUENCES
* publications.
*/

4)
GetAllPublicationRelations:
+ if (relkind == RELKIND_RELATION)
+ exceptlist = GetPublicationExcludedRelations(pubid, pubviaroot ?
+ PUBLICATION_PART_ALL :
+ PUBLICATION_PART_ROOT);

Assert(!(relkind == RELKIND_SEQUENCE && pubviaroot));

Generally we keep such parameters' sanity checks as the first step. We
can add new code after Assert.

5)
ObjectsInAllPublicationToOids() only has one caller which calls it
under check: 'if (stmt->for_all_tables)'

Thus IMO, we do not need a switch-case in
ObjectsInAllPublicationToOids(). We can simply have a sanity check to
see it is 'PUBLICATION_ALL_TABLES' and then do the needed operation
for this pub-type.

6)
CreatePublication():
/*
* If publication is for ALL TABLES and relations is not empty, it means
* that there are some relations to be excluded from the publication.
* Else, relations is the list of relations to be added to the
* publication.
*/

Shall we rephrase slightly to:

/*
* If the publication is for ALL TABLES and 'relations' is not empty,
* it indicates that some relations should be excluded from the publication.
* Add those excluded relations to the publication with 'prexcept' set to true.
* Otherwise, 'relations' contains the list of relations to be explicitly
* included in the publication.
*/

7)
+ /* Associate objects with the publication. */
+ if (stmt->for_all_tables)
+ {
+ /* Invalidate relcache so that publication info is rebuilt. */
+ CacheInvalidateRelcacheAll();
+ }

I think this comment is misplaced. We shall have it at previous place, atop:
if (stmt->for_all_tables)
This is because here we are just trying to invalidate cache while at
previous place we are trying to associate.

thanks
Shveta


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-18 06:00:30
Message-ID: CAJpy0uD+orAxUWKq9Ogf5FEWtXcwkQXb_YZOvXqDc8b15nJe9A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Dec 17, 2025 at 11:24 AM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Tue, Dec 16, 2025 at 2:50 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > I have also addressed the remaining comments and attached the latest patch.
> >
>
> Thanks. A few comments:
>
> 1)
> + if (!set_top && puballtables)
> + set_top = !list_member_oid(aexceptpubids, puboid);
>
> In GetTopMostAncestorInPublication(), we have made the above change
> which will now get ancestor from all-tables publication as well,
> provided table is not part of 'except' List. Earlier this function was
> only checking pg_subscription_rel and pg_publication_namespace which
> does not include all-tables publication. Won't it change the
> result-set for callers?
>
> 2)
> + * Publications declared with FOR ALL TABLES or FOR ALL SEQUENCES should use
> + * GetAllPublicationRelations() to obtain the complete set of tables covered by
> + * the publication.
> + */
> +List *
> +GetPublicationIncludedRelations(Oid pubid, PublicationPartOpt pub_partopt)
> +{
> + return GetPublicationRelationsInternal(pubid, pub_partopt, false);
> +}
>
> We can have an Assert here that pubid passed is not for ALL-Tables or
> ALL-sequences
>
> 3)
> GetAllPublicationRelations:
> * If the publication publishes partition changes via their respective root
> * partitioned tables, we must exclude partitions in favor of including the
> * root partitioned tables. This is not applicable to FOR ALL SEQUENCES
> * publication.
>
> + * The list does not include relations that are explicitly excluded via the
> + * EXCEPT TABLE clause of the publication specified by pubid.
>
> Suggestion:
> /*
> * If the publication publishes partition changes via their respective root
> * partitioned tables, we must exclude partitions in favor of including the
> * root partitioned tables. The list also excludes tables that are
> * explicitly excluded via the EXCEPT TABLE clause of the publication
> * identified by pubid. Neither of these rules applies to FOR ALL SEQUENCES
> * publications.
> */
>
> 4)
> GetAllPublicationRelations:
> + if (relkind == RELKIND_RELATION)
> + exceptlist = GetPublicationExcludedRelations(pubid, pubviaroot ?
> + PUBLICATION_PART_ALL :
> + PUBLICATION_PART_ROOT);
>
> Assert(!(relkind == RELKIND_SEQUENCE && pubviaroot));
>
> Generally we keep such parameters' sanity checks as the first step. We
> can add new code after Assert.
>
> 5)
> ObjectsInAllPublicationToOids() only has one caller which calls it
> under check: 'if (stmt->for_all_tables)'
>
> Thus IMO, we do not need a switch-case in
> ObjectsInAllPublicationToOids(). We can simply have a sanity check to
> see it is 'PUBLICATION_ALL_TABLES' and then do the needed operation
> for this pub-type.
>
> 6)
> CreatePublication():
> /*
> * If publication is for ALL TABLES and relations is not empty, it means
> * that there are some relations to be excluded from the publication.
> * Else, relations is the list of relations to be added to the
> * publication.
> */
>
> Shall we rephrase slightly to:
>
> /*
> * If the publication is for ALL TABLES and 'relations' is not empty,
> * it indicates that some relations should be excluded from the publication.
> * Add those excluded relations to the publication with 'prexcept' set to true.
> * Otherwise, 'relations' contains the list of relations to be explicitly
> * included in the publication.
> */
>
> 7)
> + /* Associate objects with the publication. */
> + if (stmt->for_all_tables)
> + {
> + /* Invalidate relcache so that publication info is rebuilt. */
> + CacheInvalidateRelcacheAll();
> + }
>
> I think this comment is misplaced. We shall have it at previous place, atop:
> if (stmt->for_all_tables)
> This is because here we are just trying to invalidate cache while at
> previous place we are trying to associate.
>

Few more:

8)
get_rel_sync_entry()
+ List *exceptTablePubids = NIL;

At all other places, we are using exceptpubids, shall we use the same here?

9)
ObjectsInPublicationToOids()

case PUBLICATIONOBJ_TABLE:
+ case PUBLICATIONOBJ_EXCEPT_TABLE:
+ pubobj->pubtable->except = (pubobj->pubobjtype ==
PUBLICATIONOBJ_EXCEPT_TABLE);
*rels = lappend(*rels, pubobj->pubtable);
break;

It looks slightly odd that for pubobjtype case
'PUBLICATIONOBJ_EXCEPT_TABLE', we have to check pubobjtype against
PUBLICATIONOBJ_EXCEPT_TABLE itself.

Shall we make it:
case PUBLICATIONOBJ_EXCEPT_TABLE:
pubobj->pubtable->except = true;
/* fall through */
case PUBLICATIONOBJ_TABLE:
*rels = lappend(*rels, pubobj->pubtable);
break;

10)
I want to understand the usage of DO_PUBLICATION_EXCEPT_REL. Can you
give a scenario where its usage in DOTypeNameCompare() will be hit?
Its all other usages too need some analysis and validation.

11)
+ List *except_objects; /* List of publication object to be excluded */

object --> objects
Currently since we exclude only tables, does it make sense to name it
as except_tables?

thanks
Shveta


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-18 11:45:06
Message-ID: CANhcyEVDTPVRWDm-BdJe0yaWFuz1ozTUFNHKvzX2YuiUHh=ArA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 18 Dec 2025 at 11:30, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Wed, Dec 17, 2025 at 11:24 AM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > On Tue, Dec 16, 2025 at 2:50 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > >
> > > I have also addressed the remaining comments and attached the latest patch.
> > >
> >
> > Thanks. A few comments:
> >
> > 1)
> > + if (!set_top && puballtables)
> > + set_top = !list_member_oid(aexceptpubids, puboid);
> >
> > In GetTopMostAncestorInPublication(), we have made the above change
> > which will now get ancestor from all-tables publication as well,
> > provided table is not part of 'except' List. Earlier this function was
> > only checking pg_subscription_rel and pg_publication_namespace which
> > does not include all-tables publication. Won't it change the
> > result-set for callers?
> >
It can change the result set of callers. I analysed more and saw that
GetTopMostAncestorInPublication is called from 3 places.
1. pub_rf_contains_invalid_column: it is called when publication is
not ALL TABLES. It will have no impact with the change.
2. pub_contains_invalid_column : it is called for all type of
publication. it calls GetTopMostAncestorInPublication like:
```
if (pubviaroot && relation->rd_rel->relispartition)
{
publish_as_relid = GetTopMostAncestorInPublication(pubid, ancestors,
NULL, puballtables);

if (!OidIsValid(publish_as_relid))
publish_as_relid = relid;
}
```
In HEAD for ALL TABLES publication GetTopMostAncestorInPublication
will always return InvalidOid. With this patch it can have some value.
So there is a difference in behaviour.

3. get_rel_sync_entry
in HEAD we had
```
if (pub->alltables)
{
publish = true;
if (pub->pubviaroot && am_partition)
{
List *ancestors = get_partition_ancestors(relid);

pub_relid = llast_oid(ancestors);
ancestor_level = list_length(ancestors);
}
}
```
With patch this condition is not valid because we cannot set
'pub_relid = llast_oid(ancestors);' directly as the table can be
excluded.
So, the change in GetTopMostAncestorInPublication will even handle the
case of "ALL TABLES" publication.

Since we have a behaviour difference for the 2nd function, I have
removed the changes for 'ALL TABLES' from
GetTopMostAncestorInPublication and added it separately
'get_rel_sync_entry'. Thoughts?

> > 2)
> > + * Publications declared with FOR ALL TABLES or FOR ALL SEQUENCES should use
> > + * GetAllPublicationRelations() to obtain the complete set of tables covered by
> > + * the publication.
> > + */
> > +List *
> > +GetPublicationIncludedRelations(Oid pubid, PublicationPartOpt pub_partopt)
> > +{
> > + return GetPublicationRelationsInternal(pubid, pub_partopt, false);
> > +}
> >
> > We can have an Assert here that pubid passed is not for ALL-Tables or
> > ALL-sequences
> >
Added assert for all tables. I found during testing that this function
can be called for ALL SEQUENCES in HEAD. So I have not added an
assertion for it.
I think it is a bug and shared the same in [1]. Will add assert for
all sequences as well once the bug is fixed.

> > 3)
> > GetAllPublicationRelations:
> > * If the publication publishes partition changes via their respective root
> > * partitioned tables, we must exclude partitions in favor of including the
> > * root partitioned tables. This is not applicable to FOR ALL SEQUENCES
> > * publication.
> >
> > + * The list does not include relations that are explicitly excluded via the
> > + * EXCEPT TABLE clause of the publication specified by pubid.
> >
> > Suggestion:
> > /*
> > * If the publication publishes partition changes via their respective root
> > * partitioned tables, we must exclude partitions in favor of including the
> > * root partitioned tables. The list also excludes tables that are
> > * explicitly excluded via the EXCEPT TABLE clause of the publication
> > * identified by pubid. Neither of these rules applies to FOR ALL SEQUENCES
> > * publications.
> > */
> >
> > 4)
> > GetAllPublicationRelations:
> > + if (relkind == RELKIND_RELATION)
> > + exceptlist = GetPublicationExcludedRelations(pubid, pubviaroot ?
> > + PUBLICATION_PART_ALL :
> > + PUBLICATION_PART_ROOT);
> >
> > Assert(!(relkind == RELKIND_SEQUENCE && pubviaroot));
> >
> > Generally we keep such parameters' sanity checks as the first step. We
> > can add new code after Assert.
> >
> > 5)
> > ObjectsInAllPublicationToOids() only has one caller which calls it
> > under check: 'if (stmt->for_all_tables)'
> >
> > Thus IMO, we do not need a switch-case in
> > ObjectsInAllPublicationToOids(). We can simply have a sanity check to
> > see it is 'PUBLICATION_ALL_TABLES' and then do the needed operation
> > for this pub-type.
> >
> > 6)
> > CreatePublication():
> > /*
> > * If publication is for ALL TABLES and relations is not empty, it means
> > * that there are some relations to be excluded from the publication.
> > * Else, relations is the list of relations to be added to the
> > * publication.
> > */
> >
> > Shall we rephrase slightly to:
> >
> > /*
> > * If the publication is for ALL TABLES and 'relations' is not empty,
> > * it indicates that some relations should be excluded from the publication.
> > * Add those excluded relations to the publication with 'prexcept' set to true.
> > * Otherwise, 'relations' contains the list of relations to be explicitly
> > * included in the publication.
> > */
> >
> > 7)
> > + /* Associate objects with the publication. */
> > + if (stmt->for_all_tables)
> > + {
> > + /* Invalidate relcache so that publication info is rebuilt. */
> > + CacheInvalidateRelcacheAll();
> > + }
> >
> > I think this comment is misplaced. We shall have it at previous place, atop:
> > if (stmt->for_all_tables)
> > This is because here we are just trying to invalidate cache while at
> > previous place we are trying to associate.
> >
>
> Few more:
>
> 8)
> get_rel_sync_entry()
> + List *exceptTablePubids = NIL;
>
> At all other places, we are using exceptpubids, shall we use the same here?
>
> 9)
> ObjectsInPublicationToOids()
>
> case PUBLICATIONOBJ_TABLE:
> + case PUBLICATIONOBJ_EXCEPT_TABLE:
> + pubobj->pubtable->except = (pubobj->pubobjtype ==
> PUBLICATIONOBJ_EXCEPT_TABLE);
> *rels = lappend(*rels, pubobj->pubtable);
> break;
>
> It looks slightly odd that for pubobjtype case
> 'PUBLICATIONOBJ_EXCEPT_TABLE', we have to check pubobjtype against
> PUBLICATIONOBJ_EXCEPT_TABLE itself.
>
> Shall we make it:
> case PUBLICATIONOBJ_EXCEPT_TABLE:
> pubobj->pubtable->except = true;
> /* fall through */
> case PUBLICATIONOBJ_TABLE:
> *rels = lappend(*rels, pubobj->pubtable);
> break;
>
We should also make pubobj->pubtable->except = false for PUBLICATIONOBJ_TABLE?
Updated the condition like:
case PUBLICATIONOBJ_EXCEPT_TABLE:
pubobj->pubtable->except = true;
*rels = lappend(*rels, pubobj->pubtable);
break;
case PUBLICATIONOBJ_TABLE:
pubobj->pubtable->except = false;
*rels = lappend(*rels, pubobj->pubtable);
break;

> 10)
> I want to understand the usage of DO_PUBLICATION_EXCEPT_REL. Can you
> give a scenario where its usage in DOTypeNameCompare() will be hit?
> Its all other usages too need some analysis and validation.
>
In the current patch we are not setting an objecttype to
DO_PUBLICATION_EXCEPT_REL.
We are storing the list of except tables in 'pubinfo[i].excepttbls'
list in function getPublications and "pubinfo[i].dobj.objType =
DO_PUBLICATION". So, I don't see any requirement of
DO_PUBLICATION_EXCEPT_REL now. I have removed it.

> 11)
> + List *except_objects; /* List of publication object to be excluded */
>
> object --> objects
> Currently since we exclude only tables, does it make sense to name it
> as except_tables?
>
I have also addressed the remaining comments and attached the updated v33 patch.
[1]: https://www.postgresql.org/message-id/CALDaNm0qoNtsX%2B9KPug6qb%3DuC-H2iPMYW%2BgL%3DHehx%2BNgOxga6w%40mail.gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v33-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 64.1 KB

From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-22 05:12:33
Message-ID: CAJpy0uCf5tXvqyVS3GQzU9J5HdSLAxX6Lxt1UKY4HJ8qnimCAw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Dec 18, 2025 at 5:15 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> On Thu, 18 Dec 2025 at 11:30, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > On Wed, Dec 17, 2025 at 11:24 AM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> > >
> > > On Tue, Dec 16, 2025 at 2:50 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > > >
> > > > I have also addressed the remaining comments and attached the latest patch.
> > > >
> > >
> > > Thanks. A few comments:
> > >
> > > 1)
> > > + if (!set_top && puballtables)
> > > + set_top = !list_member_oid(aexceptpubids, puboid);
> > >
> > > In GetTopMostAncestorInPublication(), we have made the above change
> > > which will now get ancestor from all-tables publication as well,
> > > provided table is not part of 'except' List. Earlier this function was
> > > only checking pg_subscription_rel and pg_publication_namespace which
> > > does not include all-tables publication. Won't it change the
> > > result-set for callers?
> > >
> It can change the result set of callers. I analysed more and saw that
> GetTopMostAncestorInPublication is called from 3 places.
> 1. pub_rf_contains_invalid_column: it is called when publication is
> not ALL TABLES. It will have no impact with the change.
> 2. pub_contains_invalid_column : it is called for all type of
> publication. it calls GetTopMostAncestorInPublication like:
> ```
> if (pubviaroot && relation->rd_rel->relispartition)
> {
> publish_as_relid = GetTopMostAncestorInPublication(pubid, ancestors,
> NULL, puballtables);
>
> if (!OidIsValid(publish_as_relid))
> publish_as_relid = relid;
> }
> ```
> In HEAD for ALL TABLES publication GetTopMostAncestorInPublication
> will always return InvalidOid. With this patch it can have some value.
> So there is a difference in behaviour.
>
> 3. get_rel_sync_entry
> in HEAD we had
> ```
> if (pub->alltables)
> {
> publish = true;
> if (pub->pubviaroot && am_partition)
> {
> List *ancestors = get_partition_ancestors(relid);
>
> pub_relid = llast_oid(ancestors);
> ancestor_level = list_length(ancestors);
> }
> }
> ```
> With patch this condition is not valid because we cannot set
> 'pub_relid = llast_oid(ancestors);' directly as the table can be
> excluded.
> So, the change in GetTopMostAncestorInPublication will even handle the
> case of "ALL TABLES" publication.
>
> Since we have a behaviour difference for the 2nd function, I have
> removed the changes for 'ALL TABLES' from
> GetTopMostAncestorInPublication and added it separately
> 'get_rel_sync_entry'. Thoughts?

I find the current implementation better, the previous one was
impacting the results of different paths.

Regarding:
+ if (list_member_oid(aexceptpubids, puboid))
+ {
+ list_free(aexceptpubids);
+ continue;
+ }

IMO, if puboid is part of apubids, that check is enough. This is
because aexceptpubids and apubids are mutually exclusive lists for a
particular 'ancestor'. But if we want to have it to avoid
schma-mapping check later, we should add a comment. How about:

This step isn’t strictly necessary, but we keep it so we can skip the
table if it appears in the EXCEPT list, avoiding an expensive
schema-mapping check later.

>
> > > 2)
> > > + * Publications declared with FOR ALL TABLES or FOR ALL SEQUENCES should use
> > > + * GetAllPublicationRelations() to obtain the complete set of tables covered by
> > > + * the publication.
> > > + */
> > > +List *
> > > +GetPublicationIncludedRelations(Oid pubid, PublicationPartOpt pub_partopt)
> > > +{
> > > + return GetPublicationRelationsInternal(pubid, pub_partopt, false);
> > > +}
> > >
> > > We can have an Assert here that pubid passed is not for ALL-Tables or
> > > ALL-sequences
> > >
> Added assert for all tables. I found during testing that this function
> can be called for ALL SEQUENCES in HEAD. So I have not added an
> assertion for it.
> I think it is a bug and shared the same in [1]. Will add assert for
> all sequences as well once the bug is fixed.
>

Okay.

> > > 3)
> > > GetAllPublicationRelations:
> > > * If the publication publishes partition changes via their respective root
> > > * partitioned tables, we must exclude partitions in favor of including the
> > > * root partitioned tables. This is not applicable to FOR ALL SEQUENCES
> > > * publication.
> > >
> > > + * The list does not include relations that are explicitly excluded via the
> > > + * EXCEPT TABLE clause of the publication specified by pubid.
> > >
> > > Suggestion:
> > > /*
> > > * If the publication publishes partition changes via their respective root
> > > * partitioned tables, we must exclude partitions in favor of including the
> > > * root partitioned tables. The list also excludes tables that are
> > > * explicitly excluded via the EXCEPT TABLE clause of the publication
> > > * identified by pubid. Neither of these rules applies to FOR ALL SEQUENCES
> > > * publications.
> > > */
> > >
> > > 4)
> > > GetAllPublicationRelations:
> > > + if (relkind == RELKIND_RELATION)
> > > + exceptlist = GetPublicationExcludedRelations(pubid, pubviaroot ?
> > > + PUBLICATION_PART_ALL :
> > > + PUBLICATION_PART_ROOT);
> > >
> > > Assert(!(relkind == RELKIND_SEQUENCE && pubviaroot));
> > >
> > > Generally we keep such parameters' sanity checks as the first step. We
> > > can add new code after Assert.
> > >
> > > 5)
> > > ObjectsInAllPublicationToOids() only has one caller which calls it
> > > under check: 'if (stmt->for_all_tables)'
> > >
> > > Thus IMO, we do not need a switch-case in
> > > ObjectsInAllPublicationToOids(). We can simply have a sanity check to
> > > see it is 'PUBLICATION_ALL_TABLES' and then do the needed operation
> > > for this pub-type.
> > >
> > > 6)
> > > CreatePublication():
> > > /*
> > > * If publication is for ALL TABLES and relations is not empty, it means
> > > * that there are some relations to be excluded from the publication.
> > > * Else, relations is the list of relations to be added to the
> > > * publication.
> > > */
> > >
> > > Shall we rephrase slightly to:
> > >
> > > /*
> > > * If the publication is for ALL TABLES and 'relations' is not empty,
> > > * it indicates that some relations should be excluded from the publication.
> > > * Add those excluded relations to the publication with 'prexcept' set to true.
> > > * Otherwise, 'relations' contains the list of relations to be explicitly
> > > * included in the publication.
> > > */
> > >
> > > 7)
> > > + /* Associate objects with the publication. */
> > > + if (stmt->for_all_tables)
> > > + {
> > > + /* Invalidate relcache so that publication info is rebuilt. */
> > > + CacheInvalidateRelcacheAll();
> > > + }
> > >
> > > I think this comment is misplaced. We shall have it at previous place, atop:
> > > if (stmt->for_all_tables)
> > > This is because here we are just trying to invalidate cache while at
> > > previous place we are trying to associate.
> > >
> >
> > Few more:
> >
> > 8)
> > get_rel_sync_entry()
> > + List *exceptTablePubids = NIL;
> >
> > At all other places, we are using exceptpubids, shall we use the same here?
> >
> > 9)
> > ObjectsInPublicationToOids()
> >
> > case PUBLICATIONOBJ_TABLE:
> > + case PUBLICATIONOBJ_EXCEPT_TABLE:
> > + pubobj->pubtable->except = (pubobj->pubobjtype ==
> > PUBLICATIONOBJ_EXCEPT_TABLE);
> > *rels = lappend(*rels, pubobj->pubtable);
> > break;
> >
> > It looks slightly odd that for pubobjtype case
> > 'PUBLICATIONOBJ_EXCEPT_TABLE', we have to check pubobjtype against
> > PUBLICATIONOBJ_EXCEPT_TABLE itself.
> >
> > Shall we make it:
> > case PUBLICATIONOBJ_EXCEPT_TABLE:
> > pubobj->pubtable->except = true;
> > /* fall through */
> > case PUBLICATIONOBJ_TABLE:
> > *rels = lappend(*rels, pubobj->pubtable);
> > break;
> >
> We should also make pubobj->pubtable->except = false for PUBLICATIONOBJ_TABLE?

yes, right.

> Updated the condition like:
> case PUBLICATIONOBJ_EXCEPT_TABLE:
> pubobj->pubtable->except = true;
> *rels = lappend(*rels, pubobj->pubtable);
> break;
> case PUBLICATIONOBJ_TABLE:
> pubobj->pubtable->except = false;
> *rels = lappend(*rels, pubobj->pubtable);
> break;
>

Looks good.

> > 10)
> > I want to understand the usage of DO_PUBLICATION_EXCEPT_REL. Can you
> > give a scenario where its usage in DOTypeNameCompare() will be hit?
> > Its all other usages too need some analysis and validation.
> >
> In the current patch we are not setting an objecttype to
> DO_PUBLICATION_EXCEPT_REL.
> We are storing the list of except tables in 'pubinfo[i].excepttbls'
> list in function getPublications and "pubinfo[i].dobj.objType =
> DO_PUBLICATION". So, I don't see any requirement of
> DO_PUBLICATION_EXCEPT_REL now. I have removed it.
>

Yes, that was my initial thought as well, that we might not need it.
But I’ll review it further and let you know.

> > 11)
> > + List *except_objects; /* List of publication object to be excluded */
> >
> > object --> objects
> > Currently since we exclude only tables, does it make sense to name it
> > as except_tables?
> >
> I have also addressed the remaining comments and attached the updated v33 patch.
> [1]: https://www.postgresql.org/message-id/CALDaNm0qoNtsX%2B9KPug6qb%3DuC-H2iPMYW%2BgL%3DHehx%2BNgOxga6w%40mail.gmail.com
>

Thanks, will review.

thanks
Shveta


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-22 06:07:27
Message-ID: CAHut+Pu6ameXD4YwbhMXf8kHBhPJXGpOmc21R5o7Lo18hkSKMQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok.

Some review comments for patch v33-0001 (code part)

======
src/backend/catalog/pg_publication.c

GetPublicationRelationsInternal:

1.
Static function names should be snake_case.

~~~

GetPublicationIncludedRelations:

2.
+/*
+ * Return the list of relation OIDs for a publication.
+ *
+ * For a FOR TABLE publication, this returns the list of relations explicitly
+ * included in the publication.
+ *
+ * Publications declared with FOR ALL TABLES or FOR ALL SEQUENCES should use
+ * GetAllPublicationRelations() to obtain the complete set of tables covered by
+ * the publication.
+ */
+List *
+GetPublicationIncludedRelations(Oid pubid, PublicationPartOpt pub_partopt)
+{
+ Assert(!GetPublication(pubid)->alltables);
+
+ return GetPublicationRelationsInternal(pubid, pub_partopt, false);
+}

Why isn't the Assert also saying something about puballsequences, as
mentioned in the function comment?

~~~

GetAllPublicationRelations:

3.
+ * root partitioned tables. The list also excludes tables that are
+ * explicitly excluded via the EXCEPT TABLE clause of the publication
+ * identified by pubid. Neither of these rules applies to FOR ALL SEQUENCES
+ * publications.

3.
It seems wrong to say "FOR ALL SEQUENCES" ... that seems to assume the
"FOR ALL SEQUENCES" and "FOR ALL TABLES" cannot co-exist. Did you mean
"Neither of ... to published sequences"?

~

4.
-GetAllPublicationRelations(char relkind, bool pubviaroot)
+GetAllPublicationRelations(Oid pubid, char relkind, bool pubviaroot)

There are tricky rules about relation vs sequences and the
publish_via_partition_root parameter value. It would be better if you
encapsulate all this within this function. Specifically, it would be
simpler if you passed the 'Publication' arg instead of the pubid. Then
you can get the pubviaroot value from that (within the function)
instead of passing around "fake" values of false when you are looking
at RELKIND_SEQUENCE.
======
src/backend/commands/publicationcmds.c

ObjectsInAllPublicationToOids:

5.
+ foreach_ptr(PublicationAllObjSpec, puballobj, puballobjspec_list)
+ {
+ if (puballobj->pubobjtype != PUBLICATION_ALL_TABLES)
+ continue;
+
+ foreach_ptr(PublicationObjSpec, pubobj, puballobj->except_tables)
+ {
+ pubobj->pubtable->except = true;
+ *rels = lappend(*rels, pubobj->pubtable);
+ }
+ }

I think it's tidier to code this like below:

if (puballobj->pubobjtype == PUBLICATION_ALL_TABLES)
{
foreach_ptr...
}

~~~

pub_contains_invalid_column:

6.
bool
pub_contains_invalid_column(Oid pubid, Relation relation, List *ancestors,
bool pubviaroot, char pubgencols_type,
- bool *invalid_column_list,
- bool *invalid_gen_col)
+ bool *invalid_column_list, bool *invalid_gen_col)

Why does this change even exist at all in this patch?

~~~

CreatePublication:

7.
+ /*
+ * If the publication is for ALL TABLES and 'relations' is not empty, it
+ * indicates that some relations should be excluded from the publication.
+ * Add those excluded relations to the publication with 'prexcept' set to
+ * true. Otherwise, 'relations' contains the list of relations to be
+ * explicitly included in the publication.
+ */
+ if (relations != NIL)
+ {
+ List *rels;
+
+ rels = OpenTableList(relations);
+ TransformPubWhereClauses(rels, pstate->p_sourcetext,
+ publish_via_partition_root);
+
+ CheckPubRelationColumnList(stmt->pubname, rels,
+ schemaidlist != NIL,
+ publish_via_partition_root);
+
+ PublicationAddTables(puboid, rels, true, NULL);
+ CloseTableList(rels);
+ }
+

The comment and the code don't match. The comment is talking about
rules for FOR ALL TABLES, but puballtables is not part of any
condition here (??). Was all this supposed to be within the "if
(stmt->for_all_tables)" code block?

======
src/bin/pg_dump/pg_dump.c

8.
- "SELECT tableoid, oid, prpubid, prrelid, "
+ "SELECT tableoid, oid, prpubid, prrelid,\n"
"pg_catalog.pg_get_expr(prqual, prrelid) AS prrelqual, "
"(CASE\n"
" WHEN pr.prattrs IS NOT NULL THEN\n"
@@ -4868,6 +4929,9 @@ getPublicationTables(Archive *fout, TableInfo
tblinfo[], int numTables)
" WHERE attrelid = pr.prrelid AND attnum = prattrs[s])\n"
" ELSE NULL END) prattrs "
"FROM pg_catalog.pg_publication_rel pr");
+ if (fout->remoteVersion >= 190000)
+ appendPQExpBufferStr(query, " WHERE prexcept = false");

8a
Isn't it better to qualify everything here with the alias 'pr'?

~

8b.
Also "WHERE NOT pr.prexcept;" might be more conssitent with other code
I saw in describe.c

======
src/bin/pg_dump/pg_dump.h

9.
PublishGencolsType pubgencols_type;
+ SimplePtrList excepttbls;
} PublicationInfo;

How about "tables instead of "tbls" (e.g. "excepttables" or
"except_tables") here? That would also be more consistent with the
other puballtables member.

======
src/test/regress/sql/publication.sql

10.
RESET client_min_messages;
\dRp+ testpub3
\dRp+ testpub4
+\dRp+ testpub5
+\dRp+ testpub6
+\dRp+ testpub7

I feel it would be better to keep each \dRp+ together with the test it
belongs to, rather than have a bunch of different tests which are then
followed by a bunch of different \dRp+. Note: this same comment
applies to other place of places -- not just here. Check everywhere
you do \dRp+

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-23 06:32:49
Message-ID: CANhcyEUiwF9w2U6CzkuOsXkLYMOjPs=6O8QyjU_5fDfYWyMswg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 22 Dec 2025 at 11:37, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok.
>
> Some review comments for patch v33-0001 (code part)
>
> ======
> src/backend/catalog/pg_publication.c
>
> GetPublicationRelationsInternal:
>
> 1.
> Static function names should be snake_case.
>
> ~~~
>
> GetPublicationIncludedRelations:
>
> 2.
> +/*
> + * Return the list of relation OIDs for a publication.
> + *
> + * For a FOR TABLE publication, this returns the list of relations explicitly
> + * included in the publication.
> + *
> + * Publications declared with FOR ALL TABLES or FOR ALL SEQUENCES should use
> + * GetAllPublicationRelations() to obtain the complete set of tables covered by
> + * the publication.
> + */
> +List *
> +GetPublicationIncludedRelations(Oid pubid, PublicationPartOpt pub_partopt)
> +{
> + Assert(!GetPublication(pubid)->alltables);
> +
> + return GetPublicationRelationsInternal(pubid, pub_partopt, false);
> +}
>
> Why isn't the Assert also saying something about puballsequences, as
> mentioned in the function comment?
>
I reported a similar kind of issue in HEAD in [1].
As per the latest discussion, I understood that it is ok to call this
function for ALL SEQUENCES.
I have updated the comment.

> ~~~
>
> GetAllPublicationRelations:
>
> 3.
> + * root partitioned tables. The list also excludes tables that are
> + * explicitly excluded via the EXCEPT TABLE clause of the publication
> + * identified by pubid. Neither of these rules applies to FOR ALL SEQUENCES
> + * publications.
>
> 3.
> It seems wrong to say "FOR ALL SEQUENCES" ... that seems to assume the
> "FOR ALL SEQUENCES" and "FOR ALL TABLES" cannot co-exist. Did you mean
> "Neither of ... to published sequences"?
>
I have modified the comment.

> ~
>
> 4.
> -GetAllPublicationRelations(char relkind, bool pubviaroot)
> +GetAllPublicationRelations(Oid pubid, char relkind, bool pubviaroot)
>
> There are tricky rules about relation vs sequences and the
> publish_via_partition_root parameter value. It would be better if you
> encapsulate all this within this function. Specifically, it would be
> simpler if you passed the 'Publication' arg instead of the pubid. Then
> you can get the pubviaroot value from that (within the function)
> instead of passing around "fake" values of false when you are looking
> at RELKIND_SEQUENCE.
> ======
> src/backend/commands/publicationcmds.c
>
> ObjectsInAllPublicationToOids:
>
> 5.
> + foreach_ptr(PublicationAllObjSpec, puballobj, puballobjspec_list)
> + {
> + if (puballobj->pubobjtype != PUBLICATION_ALL_TABLES)
> + continue;
> +
> + foreach_ptr(PublicationObjSpec, pubobj, puballobj->except_tables)
> + {
> + pubobj->pubtable->except = true;
> + *rels = lappend(*rels, pubobj->pubtable);
> + }
> + }
>
> I think it's tidier to code this like below:
>
> if (puballobj->pubobjtype == PUBLICATION_ALL_TABLES)
> {
> foreach_ptr...
> }
>
> ~~~
>
> pub_contains_invalid_column:
>
> 6.
> bool
> pub_contains_invalid_column(Oid pubid, Relation relation, List *ancestors,
> bool pubviaroot, char pubgencols_type,
> - bool *invalid_column_list,
> - bool *invalid_gen_col)
> + bool *invalid_column_list, bool *invalid_gen_col)
>
> Why does this change even exist at all in this patch?
This change is not required. I have reverted it.

>
> ~~~
>
> CreatePublication:
>
> 7.
> + /*
> + * If the publication is for ALL TABLES and 'relations' is not empty, it
> + * indicates that some relations should be excluded from the publication.
> + * Add those excluded relations to the publication with 'prexcept' set to
> + * true. Otherwise, 'relations' contains the list of relations to be
> + * explicitly included in the publication.
> + */
> + if (relations != NIL)
> + {
> + List *rels;
> +
> + rels = OpenTableList(relations);
> + TransformPubWhereClauses(rels, pstate->p_sourcetext,
> + publish_via_partition_root);
> +
> + CheckPubRelationColumnList(stmt->pubname, rels,
> + schemaidlist != NIL,
> + publish_via_partition_root);
> +
> + PublicationAddTables(puboid, rels, true, NULL);
> + CloseTableList(rels);
> + }
> +
>
> The comment and the code don't match. The comment is talking about
> rules for FOR ALL TABLES, but puballtables is not part of any
> condition here (??). Was all this supposed to be within the "if
> (stmt->for_all_tables)" code block?
>
For both ALL TABLES publication and non-ALL TABLES publication we need
the same code block.
Setting of prexcept flag will be handled in PublicationAddTables.
This comment clarifies what the list 'relations' would mean for ALL
TABLES publication and non-ALL TABLES publication

> ======
> src/bin/pg_dump/pg_dump.c
>
> 8.
> - "SELECT tableoid, oid, prpubid, prrelid, "
> + "SELECT tableoid, oid, prpubid, prrelid,\n"
> "pg_catalog.pg_get_expr(prqual, prrelid) AS prrelqual, "
> "(CASE\n"
> " WHEN pr.prattrs IS NOT NULL THEN\n"
> @@ -4868,6 +4929,9 @@ getPublicationTables(Archive *fout, TableInfo
> tblinfo[], int numTables)
> " WHERE attrelid = pr.prrelid AND attnum = prattrs[s])\n"
> " ELSE NULL END) prattrs "
> "FROM pg_catalog.pg_publication_rel pr");
> + if (fout->remoteVersion >= 190000)
> + appendPQExpBufferStr(query, " WHERE prexcept = false");
>
> 8a
> Isn't it better to qualify everything here with the alias 'pr'?
>
It is an existing code. So I prefer not to modify it in this patch. I
have added the alias for the column added by this patch.

> ~
>
> 8b.
> Also "WHERE NOT pr.prexcept;" might be more conssitent with other code
> I saw in describe.c
>
> ======
> src/bin/pg_dump/pg_dump.h
>
> 9.
> PublishGencolsType pubgencols_type;
> + SimplePtrList excepttbls;
> } PublicationInfo;
>
> How about "tables instead of "tbls" (e.g. "excepttables" or
> "except_tables") here? That would also be more consistent with the
> other puballtables member.
>
> ======
> src/test/regress/sql/publication.sql
>
> 10.
> RESET client_min_messages;
> \dRp+ testpub3
> \dRp+ testpub4
> +\dRp+ testpub5
> +\dRp+ testpub6
> +\dRp+ testpub7
>
>
> I feel it would be better to keep each \dRp+ together with the test it
> belongs to, rather than have a bunch of different tests which are then
> followed by a bunch of different \dRp+. Note: this same comment
> applies to other place of places -- not just here. Check everywhere
> you do \dRp+
>

I have addressed the remaining comments, did some cosmetic changes and
addressed the comment shared by Shveta in [2].
[1]: https://www.postgresql.org/message-id/CAA4eK1+rnjBOvkiQC2r4LuTwuje653iVPPAXcmJZXPpKvsNbOQ@mail.gmail.com
[2]: https://www.postgresql.org/message-id/CAJpy0uCf5tXvqyVS3GQzU9J5HdSLAxX6Lxt1UKY4HJ8qnimCAw%40mail.gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v34-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 64.4 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-24 03:12:31
Message-ID: CAHut+PuZX_7Ot-oh5iqGLBRrZBS5ewDnHa91mJi2Y09uCRfixg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok

Some review comments for patch v34-0001 (code)

======
src/backend/catalog/pg_publication.c

1.
+static List *
+get_publication_relations_internal(Oid pubid, PublicationPartOpt pub_partopt,
+ bool except_flag)

No need to name this function as "_internal"; the snake_case name and
static already indicate it is internal.

======
src/bin/pg_dump/pg_dump.c

getPublications:

2.
+ if (fout->remoteVersion >= 190000)
+ {
+ int ntbls;
+ PGresult *res_tbls;
+
+ resetPQExpBuffer(query);
+ appendPQExpBuffer(query,
+ "SELECT prrelid\n"
+ "FROM pg_catalog.pg_publication_rel\n"
+ "WHERE prpubid = %u and prexcept = true",
+ pubinfo[i].dobj.catId.oid);
+
+ res_tbls = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+
+ ntbls = PQntuples(res_tbls);
+ if (ntbls == 0)
+ continue;
+
+ for (int j = 0; j < ntbls; j++)
+ {
+ Oid prrelid;
+ TableInfo *tbinfo;
+
+ prrelid = atooid(PQgetvalue(res_tbls, j, 0));
+
+ tbinfo = findTableByOid(prrelid);
+ if (tbinfo == NULL)
+ continue;
+
+ simple_ptr_list_append(&pubinfo[i].except_tables, tbinfo);
+ }
+
+ PQclear(res_tbls);
+ }

2a.
I suppose this code is for populating the list of all tables except
those excluded, but there is no explanatory comment stating the
purpose of all this.

~

2b.
BEFORE
"WHERE prpubid = %u and prexcept = true"

SUGGESTION
"WHERE prpubid = %u AND prexcept"

~~~

dumpPublication:

3.
+ {
+ bool first_tbl = true;
+
appendPQExpBufferStr(query, " FOR ALL TABLES");
+
+ /* Include exception tables if the publication has EXCEPT TABLEs */
+ for (SimplePtrListCell *cell = pubinfo->except_tables.head; cell;
cell = cell->next)
+ {
+ TableInfo *tbinfo = (TableInfo *) cell->ptr;
+
+ if (first_tbl)
+ {
+ appendPQExpBufferStr(query, " EXCEPT TABLE (");
+ first_tbl = false;
+ }
+ else
+ appendPQExpBufferStr(query, ", ");
+ appendPQExpBuffer(query, "ONLY %s", fmtQualifiedDumpable(tbinfo));
+ }
+ if (!first_tbl)
+ appendPQExpBufferStr(query, ")");
+ }

3a.
That code comment seems backwards.

BEFORE
/* Include exception tables if the publication has EXCEPT TABLEs */

SUGGESTION
/* Include EXCEPT TABLE clause if there are except_tables. */

~~~

3b.
Although it works OK, I felt the following looked strange:
+ if (!first_tbl)
+ appendPQExpBufferStr(query, ")");

IMO it would be better implemented as a counter:

Replace
bool first_tbl = true;
with
int n_excluded = 0;

Then,
+ if (first_tbl)
+ {
+ appendPQExpBufferStr(query, " EXCEPT TABLE (");
+ first_tbl = false;
+ }
becomes
+ if (++n_excluded == 1)
+ appendPQExpBufferStr(query, " EXCEPT TABLE (");

And,
+ if (!first_tbl)
+ appendPQExpBufferStr(query, ")");
becomes
+ if (n_excluded > 0)
+ appendPQExpBufferStr(query, ")");

======
src/bin/psql/describe.c

describeOneTableDetails:

4.
+ /* Print publication the relation is excluded explicitly */
+ if (pset.sversion >= 190000)

The comment doesn't seem right:

SUGGESTION
Print publications that the table is explicitly excluded from

======
src/test/regress/sql/publication.sql

5.
Missing tests.

There are no test cases to show that \d is working for printing the
"Except Publications:".

======
Kind Regards,
Peter Smith.
Fujitsu Australia.


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2025-12-26 09:57:22
Message-ID: CAJpy0uCnK7A8HE_mjWaVHDn9Q=CNJQM_mB=QTtseh=GQ4aGumQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Dec 23, 2025 at 12:03 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
>
> I have addressed the remaining comments, did some cosmetic changes and
> addressed the comment shared by Shveta in [2].
> [1]: https://www.postgresql.org/message-id/CAA4eK1+rnjBOvkiQC2r4LuTwuje653iVPPAXcmJZXPpKvsNbOQ@mail.gmail.com
> [2]: https://www.postgresql.org/message-id/CAJpy0uCf5tXvqyVS3GQzU9J5HdSLAxX6Lxt1UKY4HJ8qnimCAw%40mail.gmail.com
>

Thank You for the patch. Please find a few comments:

1)
GetTopMostAncestorInPublication():

+ if (list_member_oid(aexceptpubids, puboid))
+ {
+ list_free(aexceptpubids);
+ continue;
+ }

We need to do 'list_free(apubids)' as well here.

2)
GetTopMostAncestorInPublication(). Currently it has:

if (list_member_oid(aexceptpubids, puboid))
...
if (list_member_oid(apubids, puboid))
...
else
...schema mapping check

IMO more natural order of checks will be

if (list_member_oid(apubids, puboid))
..
else if (list_member_oid(aexceptpubids, puboid))
...
else
...schema mapping check

3)
+/*
+ * Return the list of relation OIDs excluded from a publication.
+ * This is only applicable for FOR ALL TABLES publications.
+ */
+List *
+GetPublicationExcludedRelations(Oid pubid, PublicationPartOpt pub_partopt)

a) Since now 'Relations' term means both tables and sequences, but
here we mean only Tables, we can rename it to have 'Tables' rather
than 'Relations'

b) Similar to GetAllPublicationRelations which is for 'ALL Tables'
pub, we can rename it to have 'All'

So the name can be 'GetAllPublicationExcludedTables' to be more clear.

Also we can move this function close to GetAllPublicationRelations as
it is more related to that.

4)
ObjectsInPublicationToOids()
+ case PUBLICATIONOBJ_EXCEPT_TABLE:
+ pubobj->pubtable->except = true;
+ *rels = lappend(*rels, pubobj->pubtable);
+ break;

Let me know when this will be hit when we already have
'ObjectsInAllPublicationToOids' in place?

5)
get_rel_sync_entry():
+ level++;
+ GetRelationPublications(ancestor, NULL, &aexceptpubids);
+
+ if (!list_member_oid(aexceptpubids, pub->oid))
+ {
+ pub_relid = ancestor;
+ ancestor_level = level;
+ }
+ }

Consider the following table structure:
t1 has a partition p1, which in turn has a child partition
child_part1. When publish_via_partition_root is set to true, any
changes made to child_part1 are replicated through t1. If we add t1 to
the EXCEPT list, get_rel_sync_entry() still marks p1 as an ancestor to
publish changes or child_part1. Is it correct?

6)
RelationBuildPublicationDesc() also needs some more analysis about
getting and setting ancestor part for above case.

7)
Currently the way we deal with the except table in pg_dump.c differs
from how we deal with included-table. To explain the same, how about
adding below comment in getPublications() just before we fetch
except-list:

We process EXCEPT TABLES here instead of in getPublicationTables(),
and output them directly in dumpPublication(). This differs from the
approach used in dumpPublicationTable() and
dumpPublicationNamespace(). Following that approach would require
dumping table additions later as ALTER PUBLICATION … ADD EXCEPT, which
is currently not supported.

thanks
Shveta


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-06 12:43:17
Message-ID: CANhcyEWewbuqrwLTuwZUSGRGmLSmRadiNKyDB1yt0Sm+JTMHZA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 26 Dec 2025 at 15:27, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Tue, Dec 23, 2025 at 12:03 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> >
> > I have addressed the remaining comments, did some cosmetic changes and
> > addressed the comment shared by Shveta in [2].
> > [1]: https://www.postgresql.org/message-id/CAA4eK1+rnjBOvkiQC2r4LuTwuje653iVPPAXcmJZXPpKvsNbOQ@mail.gmail.com
> > [2]: https://www.postgresql.org/message-id/CAJpy0uCf5tXvqyVS3GQzU9J5HdSLAxX6Lxt1UKY4HJ8qnimCAw%40mail.gmail.com
> >
>
> Thank You for the patch. Please find a few comments:
>
> 1)
> GetTopMostAncestorInPublication():
>
> + if (list_member_oid(aexceptpubids, puboid))
> + {
> + list_free(aexceptpubids);
> + continue;
> + }
>
> We need to do 'list_free(apubids)' as well here.
>
> 2)
> GetTopMostAncestorInPublication(). Currently it has:
>
> if (list_member_oid(aexceptpubids, puboid))
> ...
> if (list_member_oid(apubids, puboid))
> ...
> else
> ...schema mapping check
>
> IMO more natural order of checks will be
>
> if (list_member_oid(apubids, puboid))
> ..
> else if (list_member_oid(aexceptpubids, puboid))
> ...
> else
> ...schema mapping check
>
While analyzing this behavior, I noticed that changes to tables listed
in the EXCEPT clause were still being published. However, those
changes were not replicated, because pg_get_publication_tables()
correctly excluded those tables, and consequently pg_subscription_rel
was populated correctly on the subscriber side.
Even though replication was prevented downstream, we should not
publish changes for tables in the EXCEPT list in the first place.
Publishing them is unnecessary and inconsistent with the publication
definition. This issue has been addressed in the latest version of the
patch
And the above two changes are not required.

> 3)
> +/*
> + * Return the list of relation OIDs excluded from a publication.
> + * This is only applicable for FOR ALL TABLES publications.
> + */
> +List *
> +GetPublicationExcludedRelations(Oid pubid, PublicationPartOpt pub_partopt)
>
> a) Since now 'Relations' term means both tables and sequences, but
> here we mean only Tables, we can rename it to have 'Tables' rather
> than 'Relations'
>
> b) Similar to GetAllPublicationRelations which is for 'ALL Tables'
> pub, we can rename it to have 'All'
>
> So the name can be 'GetAllPublicationExcludedTables' to be more clear.
>
> Also we can move this function close to GetAllPublicationRelations as
> it is more related to that.
>
> 4)
> ObjectsInPublicationToOids()
> + case PUBLICATIONOBJ_EXCEPT_TABLE:
> + pubobj->pubtable->except = true;
> + *rels = lappend(*rels, pubobj->pubtable);
> + break;
>
> Let me know when this will be hit when we already have
> 'ObjectsInAllPublicationToOids' in place?
I analysed it and found that we can eliminate the use of
'ObjectsInAllPublicationToOids'. This requires a change in gram.y.
Made the changes in the latest patch.

>
> 5)
> get_rel_sync_entry():
> + level++;
> + GetRelationPublications(ancestor, NULL, &aexceptpubids);
> +
> + if (!list_member_oid(aexceptpubids, pub->oid))
> + {
> + pub_relid = ancestor;
> + ancestor_level = level;
> + }
> + }
>
> Consider the following table structure:
> t1 has a partition p1, which in turn has a child partition
> child_part1. When publish_via_partition_root is set to true, any
> changes made to child_part1 are replicated through t1. If we add t1 to
> the EXCEPT list, get_rel_sync_entry() still marks p1 as an ancestor to
> publish changes or child_part1. Is it correct?
>
This change is not required. See reply to comment 1 and 2.

> 6)
> RelationBuildPublicationDesc() also needs some more analysis about
> getting and setting ancestor part for above case.
>
The case for partition tables can be tricky. Currently I am analysing
the behaviour of partitioned tables with the EXCEPT TABLE option in
general.
Will address it in the next version upon further analysing.

> 7)
> Currently the way we deal with the except table in pg_dump.c differs
> from how we deal with included-table. To explain the same, how about
> adding below comment in getPublications() just before we fetch
> except-list:
>
> We process EXCEPT TABLES here instead of in getPublicationTables(),
> and output them directly in dumpPublication(). This differs from the
> approach used in dumpPublicationTable() and
> dumpPublicationNamespace(). Following that approach would require
> dumping table additions later as ALTER PUBLICATION … ADD EXCEPT, which
> is currently not supported.

Also addressed the remaining comments. I have also addressed the
comments by Peter in [1]. I have also done some minor cosmetic
changes.
[1]: https://www.postgresql.org/message-id/CAHut+PuZX_7Ot-oh5iqGLBRrZBS5ewDnHa91mJi2Y09uCRfixg@mail.gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v35-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 68.7 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-08 04:20:51
Message-ID: CAHut+PvmCPdbScDoGV3jX42STm2F3DUWbj7nnbn5Y_zs6w8XWA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok.

Some review comments for the v35-0001 patch (code)

======
src/backend/replication/pgoutput/pgoutput.c

get_rel_sync_entry:

1.
/*
* If this is a FOR ALL TABLES publication, pick the partition
* root and set the ancestor level accordingly.
+ *
+ * If this is a FOR ALL TABLES publication and it has an EXCEPT
+ * TABLE list:
+ *
+ * 1. If pubviaroot is set and the relation is a partition, check
+ * whether the partition root is included in the EXCEPT TABLE
+ * list. If so, do not publish the change.
+ *
+ * 2. If pubviaroot is not set, check whether the relation itself
+ * is included in the EXCEPT TABLE list. If so, do not publish the
+ * change.
+ *
+ * This is achieved by keeping the variable "publish" set to
+ * false. And eventually, entry->pubactions will remain all false
+ * for this publication.
*/

For that last para ("This is achieved by..."), it is unclear what
"This" is referring to. I think you mean like below:

SUGGESTION
Note - "do not publish the change" is achieved by...

======
src/bin/pg_dump/pg_dump.c

getPublications:

2.
+ ntbls = PQntuples(res_tbls);
+ if (ntbls == 0)
+ continue;
+
+ for (int j = 0; j < ntbls; j++)
+ {
+ Oid prrelid;
+ TableInfo *tbinfo;
+
+ prrelid = atooid(PQgetvalue(res_tbls, j, 0));
+
+ tbinfo = findTableByOid(prrelid);
+ if (tbinfo == NULL)
+ continue;
+
+ simple_ptr_list_append(&pubinfo[i].except_tables, tbinfo);
+ }
+
+ PQclear(res_tbls);

2a.
That first condition with 'continue' looks like it would be better
just to remove it. Otherwise, the PQclear(res_tbls) may leak. Anyway,
the loop will never iterate if ntbls is 0, so where is the harm in
removing this?

~

2b.
Also, that "if (tbinfo == NULL)" seems overkill because it is only
avoiding the final statement of the loop. It might be better to
replace this like below:

if (tblinfo != NULL)
simple_ptr_list_append(...);

~~~

dumpPublication:

3.
+ appendPQExpBuffer(query, "ONLY %s", fmtQualifiedDumpable(tbinfo));

I think that unconditionally choosing "ONLY" here may not be the right
thing to do, particularly when the excluded table is a partitioned
table. (e.g. this is related to off-list discussions about how to
EXCEPT partition tables).

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-16 11:29:08
Message-ID: CAA4eK1KFdzZD3JvjfajhbHYYU9DErNcDVQZxfvGKv9npNfO5fQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Jan 6, 2026 at 6:13 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> Also addressed the remaining comments. I have also addressed the
> comments by Peter in [1]. I have also done some minor cosmetic
> changes.
>

CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE (t1,t2);

Did we consider using EXCLUDE instead of EXCEPT? In another similar
feature being discussed, the community is proposing to use EXCLUDE to
SQL Standard, so won't it be better to use EXCLUDE here as well?

[1] - https://www.postgresql.org/message-id/63e1587b-4258-41de-b823-948f8cc692d9%40eisentraut.org

--
With Regards,
Amit Kapila.


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-19 09:38:17
Message-ID: CAJpy0uD81HRrMYr7S-6AV4W2PtbGKM-nf2D89zsoMHJ9jZssUg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Approaches for Supporting EXCEPT in Partitioned Tables
------------------------------------------------------------------------

In an offline discussion with Peter Smith, Amit, and Shlok, we
identified several approaches for supporting EXCEPT with partitioned
tables and their partitions. I’d like to hear others’ opinions on
these approaches.

Consider the following partition hierarchy:
tab_root
├─ tab_part_1
│ ├─ tab_part_1_p1
│ └─ tab_part_1_p2
└─ tab_part_2
├─ tab_part_2_p1
└─ tab_part_2_p2

Approach 1:
---------------------------------
If we exclude a table, then the data in that table and all of its
partitions (i.e., the entire subtree under that table) should not be
replicated.

For example EXCEPT (tab_part_1) skips replication of tab_part_1 and
all of its partitions.

This behaviour remains the same with or without
publish_via_partition_root. The publish_via_partition_root flag only
affects publish_via_relid, i.e., the relation through which data is
published.

This approach involves certain implementation challenges. For brevity,
these are documented in the attached 'Approach1_challenges' document.

Approach 2:
---------------------------------------------------
Assign meaning to ONLY and '*' for partition tables in the EXCEPT
list. In HEAD, ONLY and '*' do not have any meaning for partitioned
tables or partitions, and these keywords are currently ignored.

Examples:
1. EXCEPT (ONLY tab_part_1) skips replication of only the table
tab_part_1. Changes for tab_root, tab_part_1_p1, and tab_part_1_p2 are
still replicated.

ii. EXCEPT (tab_part_1*) skips replication of tables tab_part_1,
tab_part_1_p1, and tab_part_1_p2

The challenges described in Approach 1, particularly around tablesync
handling and COPY behaviour, would still need to be addressed under
this approach as well. ONLY or '*' with partitioned tables is not
supported in HEAD, supporting it specifically for ALL TABLES EXCEPT
may introduce additional confusion for users.

Approach 3:
----------------
Do not allow partitions to be specified in the EXCEPT clause.

Only EXCEPT (tab_root) is supported, which excludes tab_root and all
of its partitions. Specifying EXCEPT (tab_part_1) or EXCEPT
(tab_part_1_p1) will result in an error.

~~

While Approach 1 and Approach 2 offer more flexibility to the user
compared to Approach 3, they also introduce additional design
complexity which does not seem simpler to address.

Approach 3, OTOH, provides a simpler solution and removes ambiguity
around the meaning of EXCEPT. It also aligns, to some extent, with the
behavior of ALTER PUBLICATION … DROP TABLE. For example, when a
publication is created explicitly for a ROOT partitioned table,
ALTER PUBLICATION DROP TABLE is not allowed for a partition,
regardless of the publish_via_partition_root setting. This behavior is
demonstrated in the attached AlterPubDropTable file.

That said, the behaviors of DROP TABLE and EXCEPT (table) are not
directly comparable. EXCEPT (table) is supported only for ALL TABLES
publications, whereas DROP TABLE is not supported in that context.
Similarly, when a publication is created explicitly for a partition,
ALTER PUBLICATION does allow dropping that partition.

The key point here is that 'publish_via_partition_root' does not
influence what can or cannot be dropped using ALTER PUBLICATION … DROP
TABLE. This approach follows the same principle.

OTOH when we see row-filter behaviour, publish_via_partition_root
plays a role in determining whether a row filter can be created
itself. This is demonstrated in the attached RowFilterBehaviour
experiment.

This leads us to Approach 4.

Approach 4:
----------------
Do not allow partitions to be specified in the EXCEPT clause when
publish_via_partition_root is true, but allow them when
publish_via_partition_root is false.

When publish_via_partition_root = true:
EXCEPT (tab_part_1_p1) results in an error.
EXCEPT (tab_part_1) results in an error.
EXCEPT (tab_root) excludes the entire hierarchy under the root table.

When publish_via_partition_root = false:
EXCEPT (tab_part_1_p1) skips replication of that partition.
EXCEPT (tab_part_1) skips replication of that partition and all of its
child partitions.
EXCEPT (tab_root) skips replication of the partitioned table and all
partitions beneath it.

This design is guided by the way row filters behave. It offers more
flexibility than Approach 3 while avoiding the complexity of
Approaches 1 and 2. However, it may cause some user confusion since
EXCEPT behavior depends on publish_via_partition_root.

Given this, the current plan is to implement Approach 3 as the initial
patch, and then implement the changes required for Approach 4 in a
top-up patch. This will allow us to evaluate if at all Approach 4
causes any implementation complexities.

Please share your thoughts on the approaches described.

thanks
Shveta

Attachment Content-Type Size
Approach1_challenges.txt text/plain 2.4 KB
RowFilterBehaviour.txt text/plain 3.8 KB
AlterPubDropTable.txt text/plain 5.1 KB

From: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-21 06:05:18
Message-ID: CAFiTN-sbpXXbU=u0U7SWjjouScAddZq+xb2FP8zfyVZZZt8z7w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Jan 19, 2026 at 3:08 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> Approaches for Supporting EXCEPT in Partitioned Tables
> ------------------------------------------------------------------------
>
> In an offline discussion with Peter Smith, Amit, and Shlok, we
> identified several approaches for supporting EXCEPT with partitioned
> tables and their partitions. I’d like to hear others’ opinions on
> these approaches.
>
> Consider the following partition hierarchy:
> tab_root
> ├─ tab_part_1
> │ ├─ tab_part_1_p1
> │ └─ tab_part_1_p2
> └─ tab_part_2
> ├─ tab_part_2_p1
> └─ tab_part_2_p2
>
>
> Approach 1:
> ---------------------------------
> If we exclude a table, then the data in that table and all of its
> partitions (i.e., the entire subtree under that table) should not be
> replicated.
>
> For example EXCEPT (tab_part_1) skips replication of tab_part_1 and
> all of its partitions.
>
> This behaviour remains the same with or without
> publish_via_partition_root. The publish_via_partition_root flag only
> affects publish_via_relid, i.e., the relation through which data is
> published.
>
> This approach involves certain implementation challenges. For brevity,
> these are documented in the attached 'Approach1_challenges' document.
>
> Approach 2:
> ---------------------------------------------------
> Assign meaning to ONLY and '*' for partition tables in the EXCEPT
> list. In HEAD, ONLY and '*' do not have any meaning for partitioned
> tables or partitions, and these keywords are currently ignored.
>
> Examples:
> 1. EXCEPT (ONLY tab_part_1) skips replication of only the table
> tab_part_1. Changes for tab_root, tab_part_1_p1, and tab_part_1_p2 are
> still replicated.
>
> ii. EXCEPT (tab_part_1*) skips replication of tables tab_part_1,
> tab_part_1_p1, and tab_part_1_p2
>
> The challenges described in Approach 1, particularly around tablesync
> handling and COPY behaviour, would still need to be addressed under
> this approach as well. ONLY or '*' with partitioned tables is not
> supported in HEAD, supporting it specifically for ALL TABLES EXCEPT
> may introduce additional confusion for users.
>
> Approach 3:
> ----------------
> Do not allow partitions to be specified in the EXCEPT clause.
>
> Only EXCEPT (tab_root) is supported, which excludes tab_root and all
> of its partitions. Specifying EXCEPT (tab_part_1) or EXCEPT
> (tab_part_1_p1) will result in an error.
>
> ~~
>
> While Approach 1 and Approach 2 offer more flexibility to the user
> compared to Approach 3, they also introduce additional design
> complexity which does not seem simpler to address.

Thanks for explaining this, overall I like the Approach 1, and I also
see the problem when publish via root is given in that case COPY FROM
is executed on the root and it would be hard to exclude specific
partitions. What is the behavior when root of partition tree is added
but publish via root is not true, it doesn't add any relation to
publication rel or how does it manage to not copy data from
partitions?

--
Regards,
Dilip Kumar
Google


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-21 06:32:53
Message-ID: CAJpy0uCM40+cu8va2HBqE-pazPjhNdTDAQqK3nWbs4+5fs4Mxw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Jan 16, 2026 at 4:59 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Tue, Jan 6, 2026 at 6:13 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > Also addressed the remaining comments. I have also addressed the
> > comments by Peter in [1]. I have also done some minor cosmetic
> > changes.
> >
>
> CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE (t1,t2);
>
> Did we consider using EXCLUDE instead of EXCEPT? In another similar
> feature being discussed, the community is proposing to use EXCLUDE to
> SQL Standard, so won't it be better to use EXCLUDE here as well?
>
> [1] - https://www.postgresql.org/message-id/63e1587b-4258-41de-b823-948f8cc692d9%40eisentraut.org
>

I am listing all current usages of EXCEPT and EXCLUDE to decide us better:

EXCEPT:
1. Set Operator (EXCEPT / EXCEPT ALL) (docs at [1])

Syntax: query1 EXCEPT [ALL] query2.

EXCEPT returns all rows that are in the result of query1 but not in
the result of query2.

Example: SELECT id, name FROM employees EXCEPT SELECT id, name FROM contractors;

2. IMPORT FOREIGN SCHEMA … EXCEPT (docs at [2])

Syntax:
IMPORT FOREIGN SCHEMA remote_schema
[ { LIMIT TO | EXCEPT } ( table_list ) ]
FROM SERVER server_name INTO local_schema
[ OPTIONS (...) ];

LIMIT TO (table_list) → import only the listed tables.
EXCEPT (table_list) → import all tables except the listed ones.

Example:
IMPORT FOREIGN SCHEMA public EXCEPT (audit_log)
FROM SERVER remote_pg INTO remote_import;

~~

EXCLUDE:
1. Exclusion Constraints (docs at [3])
Syntax:
CREATE TABLE table_name
( column_name data_type,
EXCLUDE USING index_method ( column_name WITH operator [, ...] ) );

Prevents rows from violating a condition defined by operators.

Example:
CREATE TABLE circles ( c circle, EXCLUDE USING gist (c WITH &&) );
Or
CREATE TABLE foo (x int, EXCLUDE (x WITH =)); --This is essentially
like a UNIQUE constraint but defined via EXCLUDE.

2.
In Window Function Calls (docs at [4])
We use EXCLUDE in the window frame exclusion clause.
In SQL, when we use OVER (...) with ROWS or RANGE, we can also specify
EXCLUDE to control which rows are considered in the window frame.

Options explained:
EXCLUDE CURRENT ROW → exclude the current row from the frame.
EXCLUDE GROUP → excludes the current row and its ordering peers from the frame.
EXCLUDE TIES → excludes any peers of the current row from the frame,
but not the current row itself
EXCLUDE NO OTHERS → include everything (default).

Example:
SELECT id, value, SUM(value)
OVER ( ORDER BY id ROWS
BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
EXCLUDE CURRENT ROW )
AS running_sum_excluding_current FROM test;

~~

IMO, we use EXCEPT in postgres when we want to filter a set of objects
from all selected objects and we use EXCLUDE mostly in terms of rows
based constraints/exclusion.

And our example of :
Create publication pub1 for all tables EXCEPT/EXCLUDE tab1,tab2;

has more resemblance to:

IMPORT FOREIGN SCHEMA public EXCEPT (audit_log) FROM SERVER remote_pg
INTO remote_import;

So based on above, +1 for EXCEPT for our case.
~~

[1]: https://www.postgresql.org/docs/current/queries-union.html
[2]: https://www.postgresql.org/docs/current/sql-importforeignschema.html
[3]: https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-EXCLUSION
[4]: https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS

thanks
Shveta


From: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-21 07:21:15
Message-ID: CAFiTN-vMpoX=TnxZq2_CmAH_k_DnJLp1Tu7-YT+uWvNGoPzfxg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Jan 21, 2026 at 12:03 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Fri, Jan 16, 2026 at 4:59 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> > On Tue, Jan 6, 2026 at 6:13 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > >
> > > Also addressed the remaining comments. I have also addressed the
> > > comments by Peter in [1]. I have also done some minor cosmetic
> > > changes.
> > >
> >
> > CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE (t1,t2);
> >
> > Did we consider using EXCLUDE instead of EXCEPT? In another similar
> > feature being discussed, the community is proposing to use EXCLUDE to
> > SQL Standard, so won't it be better to use EXCLUDE here as well?
> >
> > [1] - https://www.postgresql.org/message-id/63e1587b-4258-41de-b823-948f8cc692d9%40eisentraut.org
> >
>
> I am listing all current usages of EXCEPT and EXCLUDE to decide us better:
>
> EXCEPT:
> 1. Set Operator (EXCEPT / EXCEPT ALL) (docs at [1])
>
> Syntax: query1 EXCEPT [ALL] query2.
>
> EXCEPT returns all rows that are in the result of query1 but not in
> the result of query2.
>
> Example: SELECT id, name FROM employees EXCEPT SELECT id, name FROM contractors;
>
>
> 2. IMPORT FOREIGN SCHEMA … EXCEPT (docs at [2])
>
> Syntax:
> IMPORT FOREIGN SCHEMA remote_schema
> [ { LIMIT TO | EXCEPT } ( table_list ) ]
> FROM SERVER server_name INTO local_schema
> [ OPTIONS (...) ];
>
> LIMIT TO (table_list) → import only the listed tables.
> EXCEPT (table_list) → import all tables except the listed ones.
>
> Example:
> IMPORT FOREIGN SCHEMA public EXCEPT (audit_log)
> FROM SERVER remote_pg INTO remote_import;
>
> ~~
>
> EXCLUDE:
> 1. Exclusion Constraints (docs at [3])
> Syntax:
> CREATE TABLE table_name
> ( column_name data_type,
> EXCLUDE USING index_method ( column_name WITH operator [, ...] ) );
>
> Prevents rows from violating a condition defined by operators.
>
> Example:
> CREATE TABLE circles ( c circle, EXCLUDE USING gist (c WITH &&) );
> Or
> CREATE TABLE foo (x int, EXCLUDE (x WITH =)); --This is essentially
> like a UNIQUE constraint but defined via EXCLUDE.
>
> 2.
> In Window Function Calls (docs at [4])
> We use EXCLUDE in the window frame exclusion clause.
> In SQL, when we use OVER (...) with ROWS or RANGE, we can also specify
> EXCLUDE to control which rows are considered in the window frame.
>
> Options explained:
> EXCLUDE CURRENT ROW → exclude the current row from the frame.
> EXCLUDE GROUP → excludes the current row and its ordering peers from the frame.
> EXCLUDE TIES → excludes any peers of the current row from the frame,
> but not the current row itself
> EXCLUDE NO OTHERS → include everything (default).
>
> Example:
> SELECT id, value, SUM(value)
> OVER ( ORDER BY id ROWS
> BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
> EXCLUDE CURRENT ROW )
> AS running_sum_excluding_current FROM test;
>
> ~~
>
> IMO, we use EXCEPT in postgres when we want to filter a set of objects
> from all selected objects and we use EXCLUDE mostly in terms of rows
> based constraints/exclusion.
>
> And our example of :
> Create publication pub1 for all tables EXCEPT/EXCLUDE tab1,tab2;
>
> has more resemblance to:
>
> IMPORT FOREIGN SCHEMA public EXCEPT (audit_log) FROM SERVER remote_pg
> INTO remote_import;
>
> So based on above, +1 for EXCEPT for our case.

I agree based on existing examples EXCEPT seems more relevant for our
use case. So +1 for EXCEPT.

--
Regards,
Dilip Kumar
Google


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-21 11:27:29
Message-ID: CAJpy0uDgGM_coNXK2AsmVm_DGEiMy_FQFmpkR41pcU=sxpaZ=w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Jan 21, 2026 at 11:35 AM Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:
>
> Thanks for explaining this, overall I like the Approach 1, and I also
> see the problem when publish via root is given in that case COPY FROM
> is executed on the root and it would be hard to exclude specific
> partitions. What is the behavior when root of partition tree is added
> but publish via root is not true, it doesn't add any relation to
> publication rel or how does it manage to not copy data from
> partitions?
>

So, I believe you are asking about the behavior of COPY on HEAD for
the following case:

CREATE PUBLICATION pub1 FOR TABLE tab_root WITH
(publish_via_partition_root = false);

In this scenario, pg_publication_rel contains an entry for tab_root,
while pg_publication_tables contains all leaf partitions (because
publish_via_partition_root = false). Consequently,
pg_subscription_rel, which is derived from pg_publication_tables, also
contains all corresponding leaf partitions. As a result, on HEAD, a
separate tablesync worker is launched for each leaf partition, and
each leaf partition is copied independently.

~~

Now, in Approach 4, when publish_via_partition_root is set to false,
we propose avoiding the inclusion of leaf partitions in
pg_publication_tables if their parent appears in the EXCEPT list.
Given the table hierarchy described in Approach1_challenges:

tab_root
├── tab_part_1
│ ├── tab_part_1_1
│ │ ├── tab_part_1_1_1
│ │ │ └── tab_part_1_1_1_1
│ │ └── tab_part_1_1_2
│ └── tab_part_1_2
│ ├── tab_part_1_2_1
│ └── tab_part_1_2_2
└── tab_part_2

If tab_part_1_1 is specified in the EXCEPT list, then
pg_publication_tables will include only those leaf partitions that are
not in the partition-chain of tab_part_1_1. As a result, both
pg_publication_tables and pg_subscription_rel (which is built from
pg_publication_tables via fetch_relation_list) will contain:

tab_part_1_2_1
tab_part_1_2_2
tab_part_2

With this setup, any INSERT into tab_part_1 or tab_root that routes
rows to tab_part_1_1_1_1 or tab_part_1_1_2 will not be replicated.
However, rows routed to any of the three leaf partitions listed above
will be replicated.

I hope it answers your query. If we have to go by Approach1, then do
you see any simpler way to overcome the challenges we mention for
publish_via_partition_root=true case. Or any other approach
altogether?

thanks
Shveta


From: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-21 11:41:31
Message-ID: CAFiTN-tEowDfXaPRy-CFEY0YZkSgLBO9EHgDfFmOf_YK_hnJiA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Jan 21, 2026 at 4:57 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Wed, Jan 21, 2026 at 11:35 AM Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:
> >
> > Thanks for explaining this, overall I like the Approach 1, and I also
> > see the problem when publish via root is given in that case COPY FROM
> > is executed on the root and it would be hard to exclude specific
> > partitions. What is the behavior when root of partition tree is added
> > but publish via root is not true, it doesn't add any relation to
> > publication rel or how does it manage to not copy data from
> > partitions?
> >
>
> So, I believe you are asking about the behavior of COPY on HEAD for
> the following case:
>
> CREATE PUBLICATION pub1 FOR TABLE tab_root WITH
> (publish_via_partition_root = false);
>
> In this scenario, pg_publication_rel contains an entry for tab_root,
> while pg_publication_tables contains all leaf partitions (because
> publish_via_partition_root = false). Consequently,
> pg_subscription_rel, which is derived from pg_publication_tables, also
> contains all corresponding leaf partitions. As a result, on HEAD, a
> separate tablesync worker is launched for each leaf partition, and
> each leaf partition is copied independently.
>
> ~~
>
> Now, in Approach 4, when publish_via_partition_root is set to false,
> we propose avoiding the inclusion of leaf partitions in
> pg_publication_tables if their parent appears in the EXCEPT list.
> Given the table hierarchy described in Approach1_challenges:
>
> tab_root
> ├── tab_part_1
> │ ├── tab_part_1_1
> │ │ ├── tab_part_1_1_1
> │ │ │ └── tab_part_1_1_1_1
> │ │ └── tab_part_1_1_2
> │ └── tab_part_1_2
> │ ├── tab_part_1_2_1
> │ └── tab_part_1_2_2
> └── tab_part_2
>
> If tab_part_1_1 is specified in the EXCEPT list, then
> pg_publication_tables will include only those leaf partitions that are
> not in the partition-chain of tab_part_1_1. As a result, both
> pg_publication_tables and pg_subscription_rel (which is built from
> pg_publication_tables via fetch_relation_list) will contain:
>
> tab_part_1_2_1
> tab_part_1_2_2
> tab_part_2
>
> With this setup, any INSERT into tab_part_1 or tab_root that routes
> rows to tab_part_1_1_1_1 or tab_part_1_1_2 will not be replicated.
> However, rows routed to any of the three leaf partitions listed above
> will be replicated.
>
> I hope it answers your query. If we have to go by Approach1, then do
> you see any simpler way to overcome the challenges we mention for
> publish_via_partition_root=true case. Or any other approach
> altogether?

Thanks for the explanation, that clears it up. I agree that Approach 3
is the right path forward. And it makes sense to extend this with
Approach 4. Logically, I think it's reasonable to say that if a user
chooses to partition via the root, they are treating the entire
partition tree as a single entity. Therefore, it makes sense to
disallow the exclusion of individual child partitions in that context.

--
Regards,
Dilip Kumar
Google


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-22 12:04:25
Message-ID: CANhcyEWTxqsrZsaqHwHO_eGD5=mrT=+RLGkCJ4cRvfua_fSdRQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 21 Jan 2026 at 17:11, Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:
>
> On Wed, Jan 21, 2026 at 4:57 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > On Wed, Jan 21, 2026 at 11:35 AM Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:
> > >
> > > Thanks for explaining this, overall I like the Approach 1, and I also
> > > see the problem when publish via root is given in that case COPY FROM
> > > is executed on the root and it would be hard to exclude specific
> > > partitions. What is the behavior when root of partition tree is added
> > > but publish via root is not true, it doesn't add any relation to
> > > publication rel or how does it manage to not copy data from
> > > partitions?
> > >
> >
> > So, I believe you are asking about the behavior of COPY on HEAD for
> > the following case:
> >
> > CREATE PUBLICATION pub1 FOR TABLE tab_root WITH
> > (publish_via_partition_root = false);
> >
> > In this scenario, pg_publication_rel contains an entry for tab_root,
> > while pg_publication_tables contains all leaf partitions (because
> > publish_via_partition_root = false). Consequently,
> > pg_subscription_rel, which is derived from pg_publication_tables, also
> > contains all corresponding leaf partitions. As a result, on HEAD, a
> > separate tablesync worker is launched for each leaf partition, and
> > each leaf partition is copied independently.
> >
> > ~~
> >
> > Now, in Approach 4, when publish_via_partition_root is set to false,
> > we propose avoiding the inclusion of leaf partitions in
> > pg_publication_tables if their parent appears in the EXCEPT list.
> > Given the table hierarchy described in Approach1_challenges:
> >
> > tab_root
> > ├── tab_part_1
> > │ ├── tab_part_1_1
> > │ │ ├── tab_part_1_1_1
> > │ │ │ └── tab_part_1_1_1_1
> > │ │ └── tab_part_1_1_2
> > │ └── tab_part_1_2
> > │ ├── tab_part_1_2_1
> > │ └── tab_part_1_2_2
> > └── tab_part_2
> >
> > If tab_part_1_1 is specified in the EXCEPT list, then
> > pg_publication_tables will include only those leaf partitions that are
> > not in the partition-chain of tab_part_1_1. As a result, both
> > pg_publication_tables and pg_subscription_rel (which is built from
> > pg_publication_tables via fetch_relation_list) will contain:
> >
> > tab_part_1_2_1
> > tab_part_1_2_2
> > tab_part_2
> >
> > With this setup, any INSERT into tab_part_1 or tab_root that routes
> > rows to tab_part_1_1_1_1 or tab_part_1_1_2 will not be replicated.
> > However, rows routed to any of the three leaf partitions listed above
> > will be replicated.
> >
> > I hope it answers your query. If we have to go by Approach1, then do
> > you see any simpler way to overcome the challenges we mention for
> > publish_via_partition_root=true case. Or any other approach
> > altogether?
>
> Thanks for the explanation, that clears it up. I agree that Approach 3
> is the right path forward. And it makes sense to extend this with
> Approach 4. Logically, I think it's reasonable to say that if a user
> chooses to partition via the root, they are treating the entire
> partition tree as a single entity. Therefore, it makes sense to
> disallow the exclusion of individual child partitions in that context.
>
Hi,

I have prepared a patch for Approach-3. We are also checking the
feasibility of other approaches.

Thanks,
Shlok Kyal

Attachment Content-Type Size
v36-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/x-patch 69.3 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-23 05:43:21
Message-ID: CAHut+PtKD6zoACwW61MuNBo8iqT8dc6Es4Rwqi5u7jCuEtW=Dw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok.

Some review comments for v36-0001.

======
1.
It seems that most of my v35 public/internal review comments from
around 8/JAN have not been addressed in v36.

======
doc/src/sgml/ref/create_publication.sgml

EXCEPT TABLE

2.
+ <para>
+ For partitioned tables, only the root partitioned table may be specified
+ in <literal>EXCEPT TABLE</literal>. Doing so excludes the root table and
+ all of its partitions from replication, regardless of the value of
+ <literal>publish_via_partition_root</literal>. The optional
+ <literal>*</literal> has no effect for partitioned tables.
+ </para>

2a.
AFAIK, the 'publish_via_partition_root' value has nothing to do with
EXCEPT(partition) in this patch, but why was it really necessary to
actually say that?

~

2b.
Should this be saying that "ONLY" also does not mean anything when a
partitioned table is specified?

======
src/backend/catalog/pg_publication.c

publication_add_relation:

3.
+ /*
+ * Handle the case where a partition is excluded by EXCEPT TABLE
+ */
+ if (pub->alltables && pri->except && targetrel->rd_rel->relispartition)
+ ereport(ERROR,
+ (errmsg("partition \"%s\" cannot be excluded using EXCEPT TABLE",
+ RelationGetRelationName(targetrel))));

Should we have a hintmsg here to ask/tell the user that they might
need to try EXCEPT the partitioned root instead?

======
src/backend/commands/tablecmds.c

ATExecAttachPartition:

4.
+ /* Check if the partiton is part of EXCEPT list of any publication */
+ GetRelationPublications(RelationGetRelid(attachrel), NULL, &except_pubids);
+ if (except_pubids != NIL)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot attach relation \"%s\" as partition because it is
part of EXCEPT list in publication",
+ RelationGetRelationName(attachrel))));

Maybe reword the message

SUGGESTION
... because it is named in a publication EXCEPT TABLE list

======
src/backend/utils/cache/relcache.c

RelationBuildPublicationDesc:

5.
+ /*
+ * Only the topmost ancestor of a partitioned table can be specified
+ * in EXCEPT TABLES clause of a FOR ALL TABLES publication. So fetch
+ * the publications excluding the topmost ancestor only.
+ */
+ GetRelationPublications(llast_oid(ancestors), NULL, &exceptpuboids);
+

I found that "So fetch..." sentence to be quite ambiguous.

SUGGESTION
... , so we only need to check the topmost ancestor.

======
.../t/037_rep_changes_except_table.pl

6.
+ ALTER TABLE sch1.t1 ATTACH PARTITION sch1.part2 FOR VALUES FROM
(101) TO (200);

Was there any reason to do this ALTER?
AFAIK, you could've said both PARTITION BY and PARTITION OF in the
original CREATE TABLE.

~~~

7.
+# Partititions cannot be excluded using EXCEPT TABLE

7a.
typo: /Partititions/Partitions/

~

7b.
TBH, I don't know if it was necessary to repeat these partition tests
all the time with/without publish_via_partition_root set, but if you
still think it is needed, then the comment should say that all
combinations are tested to demonstrate that the parameter has no
effect.

Meanwhile, the same goes for all the other tests too ... Given that
'publish_via_partition_root' has no impact on EXCEPT TABLE, then why
do we need so many combinations of tests to show that it has no
effect? IOW, many other parameters also have nothing to do with EXCEPT
TABLE, but we don't test those.

~~~

8.
+# Cannot attach partition that is part of EXCEPT list in publication

SUGGESTION
Cannot attach a partition that is named in the EXCEPT list of any publication

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-23 13:11:09
Message-ID: CALDaNm2x3fR+AEji0ZruTdss-4WDatraXKs1QA44eVnsBmbUiA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 21 Jan 2026 at 11:35, Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:
>
> On Mon, Jan 19, 2026 at 3:08 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > Approaches for Supporting EXCEPT in Partitioned Tables
> > ------------------------------------------------------------------------
> >
> > In an offline discussion with Peter Smith, Amit, and Shlok, we
> > identified several approaches for supporting EXCEPT with partitioned
> > tables and their partitions. I’d like to hear others’ opinions on
> > these approaches.
> >
> > Consider the following partition hierarchy:
> > tab_root
> > ├─ tab_part_1
> > │ ├─ tab_part_1_p1
> > │ └─ tab_part_1_p2
> > └─ tab_part_2
> > ├─ tab_part_2_p1
> > └─ tab_part_2_p2
> >
> >
> > Approach 1:
> > ---------------------------------
> > If we exclude a table, then the data in that table and all of its
> > partitions (i.e., the entire subtree under that table) should not be
> > replicated.
> >
> > For example EXCEPT (tab_part_1) skips replication of tab_part_1 and
> > all of its partitions.
> >
> > This behaviour remains the same with or without
> > publish_via_partition_root. The publish_via_partition_root flag only
> > affects publish_via_relid, i.e., the relation through which data is
> > published.
> >
> > This approach involves certain implementation challenges. For brevity,
> > these are documented in the attached 'Approach1_challenges' document.
> >
> > Approach 2:
> > ---------------------------------------------------
> > Assign meaning to ONLY and '*' for partition tables in the EXCEPT
> > list. In HEAD, ONLY and '*' do not have any meaning for partitioned
> > tables or partitions, and these keywords are currently ignored.
> >
> > Examples:
> > 1. EXCEPT (ONLY tab_part_1) skips replication of only the table
> > tab_part_1. Changes for tab_root, tab_part_1_p1, and tab_part_1_p2 are
> > still replicated.
> >
> > ii. EXCEPT (tab_part_1*) skips replication of tables tab_part_1,
> > tab_part_1_p1, and tab_part_1_p2
> >
> > The challenges described in Approach 1, particularly around tablesync
> > handling and COPY behaviour, would still need to be addressed under
> > this approach as well. ONLY or '*' with partitioned tables is not
> > supported in HEAD, supporting it specifically for ALL TABLES EXCEPT
> > may introduce additional confusion for users.
> >
> > Approach 3:
> > ----------------
> > Do not allow partitions to be specified in the EXCEPT clause.
> >
> > Only EXCEPT (tab_root) is supported, which excludes tab_root and all
> > of its partitions. Specifying EXCEPT (tab_part_1) or EXCEPT
> > (tab_part_1_p1) will result in an error.
> >
> > ~~
> >
> > While Approach 1 and Approach 2 offer more flexibility to the user
> > compared to Approach 3, they also introduce additional design
> > complexity which does not seem simpler to address.
>
> Thanks for explaining this, overall I like the Approach 1, and I also
> see the problem when publish via root is given in that case COPY FROM
> is executed on the root and it would be hard to exclude specific
> partitions.

Regarding the above issue which is also mentioned in
Approach1_challenges at [1]:
When a publication is created with publish_via_partition_root = true
and a specific partition(tab_part_1_1) is excluded, the expected
behavior is that changes from non-excluded partitions (for example,
tab_part_2 and tab_part_1_2 and their descendants) are replicated,
while changes from the excluded partition (tab_part_1_1 and its
subtree) are not.
tab_root
├── tab_part_1
│ ├── tab_part_1_1        (except)
│ │ ├── tab_part_1_1_1
│ │ │ └── tab_part_1_1_1_1
│ │ └── tab_part_1_1_2
│ └── tab_part_1_2
│ ├── tab_part_1_2_1
│ └── tab_part_1_2_2
└── tab_part_2

In this situation, replication cannot be performed purely via the
partition root (tab_root), because doing so would implicitly include
data from the excluded child partitions.

To address this, the publication creation should explicitly record the
excluded partition(tab_part_1_1) in pg_publication_rel with an
excluded = true flag. The publish_via_partition_root setting remains
stored at the publication level, as it is today. With
publish_via_partition_root = true, the publisher–subscriber mapping is
not partition-to-partition. Instead, all eligible data is mapped to
the subscriber’s partition root. Therefore,
pg_get_publication_tables() should return only the top-level root
table (tab_root) to the subscriber for table synchronization. During
initial table sync, when the tablesync worker prepares the COPY
command, it can query the publisher to determine the effective set of
tables that belong to the publication after applying the exclusion
rules. Based on this resolved table list, the tablesync worker can
construct a COPY query that unions data only from the non-excluded
partitions, for example:
COPY (
SELECT * FROM tab_part_1_2_1
UNION ALL
SELECT * FROM tab_part_1_2_2
UNION ALL
SELECT * FROM tab_part_2
)

This ensures that only non-excluded data is copied and applied to
tab_root on the subscriber, while preserving the semantics of
publish_via_partition_root = true.
Thoughts?

[1] - https://www.postgresql.org/message-id/CAJpy0uD81HRrMYr7S-6AV4W2PtbGKM-nf2D89zsoMHJ9jZssUg%40mail.gmail.com

Regards,
Vignesh


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-27 14:37:01
Message-ID: CALDaNm3kX=16L-72m13CqXL9uAiHURNZ+BLo-HfTEYHDFejj-A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 23 Jan 2026 at 18:41, vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Wed, 21 Jan 2026 at 11:35, Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:
> >
> > On Mon, Jan 19, 2026 at 3:08 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> > >
> > > Approaches for Supporting EXCEPT in Partitioned Tables
> > > ------------------------------------------------------------------------
> > >
> > > In an offline discussion with Peter Smith, Amit, and Shlok, we
> > > identified several approaches for supporting EXCEPT with partitioned
> > > tables and their partitions. I’d like to hear others’ opinions on
> > > these approaches.
> > >
> > > Consider the following partition hierarchy:
> > > tab_root
> > > ├─ tab_part_1
> > > │ ├─ tab_part_1_p1
> > > │ └─ tab_part_1_p2
> > > └─ tab_part_2
> > > ├─ tab_part_2_p1
> > > └─ tab_part_2_p2
> > >
> > >
> > > Approach 1:
> > > ---------------------------------
> > > If we exclude a table, then the data in that table and all of its
> > > partitions (i.e., the entire subtree under that table) should not be
> > > replicated.
> > >
> > > For example EXCEPT (tab_part_1) skips replication of tab_part_1 and
> > > all of its partitions.
> > >
> > > This behaviour remains the same with or without
> > > publish_via_partition_root. The publish_via_partition_root flag only
> > > affects publish_via_relid, i.e., the relation through which data is
> > > published.
> > >
> > > This approach involves certain implementation challenges. For brevity,
> > > these are documented in the attached 'Approach1_challenges' document.
> > >
> > > Approach 2:
> > > ---------------------------------------------------
> > > Assign meaning to ONLY and '*' for partition tables in the EXCEPT
> > > list. In HEAD, ONLY and '*' do not have any meaning for partitioned
> > > tables or partitions, and these keywords are currently ignored.
> > >
> > > Examples:
> > > 1. EXCEPT (ONLY tab_part_1) skips replication of only the table
> > > tab_part_1. Changes for tab_root, tab_part_1_p1, and tab_part_1_p2 are
> > > still replicated.
> > >
> > > ii. EXCEPT (tab_part_1*) skips replication of tables tab_part_1,
> > > tab_part_1_p1, and tab_part_1_p2
> > >
> > > The challenges described in Approach 1, particularly around tablesync
> > > handling and COPY behaviour, would still need to be addressed under
> > > this approach as well. ONLY or '*' with partitioned tables is not
> > > supported in HEAD, supporting it specifically for ALL TABLES EXCEPT
> > > may introduce additional confusion for users.
> > >
> > > Approach 3:
> > > ----------------
> > > Do not allow partitions to be specified in the EXCEPT clause.
> > >
> > > Only EXCEPT (tab_root) is supported, which excludes tab_root and all
> > > of its partitions. Specifying EXCEPT (tab_part_1) or EXCEPT
> > > (tab_part_1_p1) will result in an error.
> > >
> > > ~~
> > >
> > > While Approach 1 and Approach 2 offer more flexibility to the user
> > > compared to Approach 3, they also introduce additional design
> > > complexity which does not seem simpler to address.
> >
> > Thanks for explaining this, overall I like the Approach 1, and I also
> > see the problem when publish via root is given in that case COPY FROM
> > is executed on the root and it would be hard to exclude specific
> > partitions.
>
> Regarding the above issue which is also mentioned in
> Approach1_challenges at [1]:
> When a publication is created with publish_via_partition_root = true
> and a specific partition(tab_part_1_1) is excluded, the expected
> behavior is that changes from non-excluded partitions (for example,
> tab_part_2 and tab_part_1_2 and their descendants) are replicated,
> while changes from the excluded partition (tab_part_1_1 and its
> subtree) are not.
> tab_root
> ├── tab_part_1
> │ ├── tab_part_1_1        (except)
> │ │ ├── tab_part_1_1_1
> │ │ │ └── tab_part_1_1_1_1
> │ │ └── tab_part_1_1_2
> │ └── tab_part_1_2
> │ ├── tab_part_1_2_1
> │ └── tab_part_1_2_2
> └── tab_part_2
>
> In this situation, replication cannot be performed purely via the
> partition root (tab_root), because doing so would implicitly include
> data from the excluded child partitions.
>
> To address this, the publication creation should explicitly record the
> excluded partition(tab_part_1_1) in pg_publication_rel with an
> excluded = true flag. The publish_via_partition_root setting remains
> stored at the publication level, as it is today. With
> publish_via_partition_root = true, the publisher–subscriber mapping is
> not partition-to-partition. Instead, all eligible data is mapped to
> the subscriber’s partition root. Therefore,
> pg_get_publication_tables() should return only the top-level root
> table (tab_root) to the subscriber for table synchronization. During
> initial table sync, when the tablesync worker prepares the COPY
> command, it can query the publisher to determine the effective set of
> tables that belong to the publication after applying the exclusion
> rules. Based on this resolved table list, the tablesync worker can
> construct a COPY query that unions data only from the non-excluded
> partitions, for example:
> COPY (
> SELECT * FROM tab_part_1_2_1
> UNION ALL
> SELECT * FROM tab_part_1_2_2
> UNION ALL
> SELECT * FROM tab_part_2
> )
>
> This ensures that only non-excluded data is copied and applied to
> tab_root on the subscriber, while preserving the semantics of
> publish_via_partition_root = true.

Here is a patch which has the changes to handle the same.

Regards,
Vignesh

Attachment Content-Type Size
v37-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch text/x-patch 79.7 KB

From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-28 05:16:07
Message-ID: CAJpy0uBfEuzYX+qjAPM+GV5duOwMNqO6fkDtsN1OzONVNR9WGQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Jan 27, 2026 at 8:25 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Fri, 23 Jan 2026 at 18:41, vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > On Wed, 21 Jan 2026 at 11:35, Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:
> > >
> > > On Mon, Jan 19, 2026 at 3:08 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> > > >
> > > > Approaches for Supporting EXCEPT in Partitioned Tables
> > > > ------------------------------------------------------------------------
> > > >
> > > > In an offline discussion with Peter Smith, Amit, and Shlok, we
> > > > identified several approaches for supporting EXCEPT with partitioned
> > > > tables and their partitions. I’d like to hear others’ opinions on
> > > > these approaches.
> > > >
> > > > Consider the following partition hierarchy:
> > > > tab_root
> > > > ├─ tab_part_1
> > > > │ ├─ tab_part_1_p1
> > > > │ └─ tab_part_1_p2
> > > > └─ tab_part_2
> > > > ├─ tab_part_2_p1
> > > > └─ tab_part_2_p2
> > > >
> > > >
> > > > Approach 1:
> > > > ---------------------------------
> > > > If we exclude a table, then the data in that table and all of its
> > > > partitions (i.e., the entire subtree under that table) should not be
> > > > replicated.
> > > >
> > > > For example EXCEPT (tab_part_1) skips replication of tab_part_1 and
> > > > all of its partitions.
> > > >
> > > > This behaviour remains the same with or without
> > > > publish_via_partition_root. The publish_via_partition_root flag only
> > > > affects publish_via_relid, i.e., the relation through which data is
> > > > published.
> > > >
> > > > This approach involves certain implementation challenges. For brevity,
> > > > these are documented in the attached 'Approach1_challenges' document.
> > > >
> > > > Approach 2:
> > > > ---------------------------------------------------
> > > > Assign meaning to ONLY and '*' for partition tables in the EXCEPT
> > > > list. In HEAD, ONLY and '*' do not have any meaning for partitioned
> > > > tables or partitions, and these keywords are currently ignored.
> > > >
> > > > Examples:
> > > > 1. EXCEPT (ONLY tab_part_1) skips replication of only the table
> > > > tab_part_1. Changes for tab_root, tab_part_1_p1, and tab_part_1_p2 are
> > > > still replicated.
> > > >
> > > > ii. EXCEPT (tab_part_1*) skips replication of tables tab_part_1,
> > > > tab_part_1_p1, and tab_part_1_p2
> > > >
> > > > The challenges described in Approach 1, particularly around tablesync
> > > > handling and COPY behaviour, would still need to be addressed under
> > > > this approach as well. ONLY or '*' with partitioned tables is not
> > > > supported in HEAD, supporting it specifically for ALL TABLES EXCEPT
> > > > may introduce additional confusion for users.
> > > >
> > > > Approach 3:
> > > > ----------------
> > > > Do not allow partitions to be specified in the EXCEPT clause.
> > > >
> > > > Only EXCEPT (tab_root) is supported, which excludes tab_root and all
> > > > of its partitions. Specifying EXCEPT (tab_part_1) or EXCEPT
> > > > (tab_part_1_p1) will result in an error.
> > > >
> > > > ~~
> > > >
> > > > While Approach 1 and Approach 2 offer more flexibility to the user
> > > > compared to Approach 3, they also introduce additional design
> > > > complexity which does not seem simpler to address.
> > >
> > > Thanks for explaining this, overall I like the Approach 1, and I also
> > > see the problem when publish via root is given in that case COPY FROM
> > > is executed on the root and it would be hard to exclude specific
> > > partitions.
> >
> > Regarding the above issue which is also mentioned in
> > Approach1_challenges at [1]:
> > When a publication is created with publish_via_partition_root = true
> > and a specific partition(tab_part_1_1) is excluded, the expected
> > behavior is that changes from non-excluded partitions (for example,
> > tab_part_2 and tab_part_1_2 and their descendants) are replicated,
> > while changes from the excluded partition (tab_part_1_1 and its
> > subtree) are not.
> > tab_root
> > ├── tab_part_1
> > │ ├── tab_part_1_1        (except)
> > │ │ ├── tab_part_1_1_1
> > │ │ │ └── tab_part_1_1_1_1
> > │ │ └── tab_part_1_1_2
> > │ └── tab_part_1_2
> > │ ├── tab_part_1_2_1
> > │ └── tab_part_1_2_2
> > └── tab_part_2
> >
> > In this situation, replication cannot be performed purely via the
> > partition root (tab_root), because doing so would implicitly include
> > data from the excluded child partitions.
> >
> > To address this, the publication creation should explicitly record the
> > excluded partition(tab_part_1_1) in pg_publication_rel with an
> > excluded = true flag. The publish_via_partition_root setting remains
> > stored at the publication level, as it is today. With
> > publish_via_partition_root = true, the publisher–subscriber mapping is
> > not partition-to-partition. Instead, all eligible data is mapped to
> > the subscriber’s partition root. Therefore,
> > pg_get_publication_tables() should return only the top-level root
> > table (tab_root) to the subscriber for table synchronization. During
> > initial table sync, when the tablesync worker prepares the COPY
> > command, it can query the publisher to determine the effective set of
> > tables that belong to the publication after applying the exclusion
> > rules. Based on this resolved table list, the tablesync worker can
> > construct a COPY query that unions data only from the non-excluded
> > partitions, for example:
> > COPY (
> > SELECT * FROM tab_part_1_2_1
> > UNION ALL
> > SELECT * FROM tab_part_1_2_2
> > UNION ALL
> > SELECT * FROM tab_part_2
> > )
> >
> > This ensures that only non-excluded data is copied and applied to
> > tab_root on the subscriber, while preserving the semantics of
> > publish_via_partition_root = true.

I agree with the suggested changes in tablesync. It will be good if we
can add these details in the commit-msg section of the patch. Also
please mention how increment replication is impacted (or supposed to
work) with Approach1.

> Here is a patch which has the changes to handle the same.
>

Thank You for the patch.

1)
There are certain parts of Approach 3 still present in Approach 1, as
an example:

1a)
+ For partitioned tables, only the root partitioned table may be specified
+ in <literal>EXCEPT TABLE</literal>.

1b)
+ /*
+ * Only the topmost ancestor of a partitioned table can be specified
+ * in EXCEPT TABLES clause of a FOR ALL TABLES publication. So fetch
+ * the publications excluding the topmost ancestor only.
+ */
+ GetRelationPublications(llast_oid(ancestors), NULL, &exceptpuboids);
+

1c)
+ /* Check if the partiton is part of EXCEPT list of any publication */
+ GetRelationPublications(RelationGetRelid(attachrel), NULL, &except_pubids);
+ if (except_pubids != NIL)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot attach relation \"%s\" as partition because it is
part of EXCEPT list in publication",
+ RelationGetRelationName(attachrel))));
+

Overall, please take a diff of v35 and v37 to find such parts and
please correct these and others (if any).

2)
Also I don't think if below is correct statement for Approach 1:

+ * 2. For a partition, if the topmost ancestor is part of
+ * the EXCEPT TABLE list, we don't publish it.

Even if any ancestor is part of EXECPT list (not only top most) we
should not publish that partition, isn't it?

3)
I tried a scenario and found that incremental replication is not
working correctly. Attached the failing test as Approach1_v37_fail.txt

Once these basic things are corrected, I can review further.

thanks
Shveta

Attachment Content-Type Size
Approach1_v37_fail.txt text/plain 3.6 KB

From: vignesh C <vignesh21(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-29 15:11:26
Message-ID: CALDaNm2MZU8-JbFruQAxF8OZfcH4ZsBrCsWDg3VMbO-P+xKmBg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 28 Jan 2026 at 10:46, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> Thank You for the patch.
>
> 1)
> There are certain parts of Approach 3 still present in Approach 1, as
> an example:
>
> 1a)
> + For partitioned tables, only the root partitioned table may be specified
> + in <literal>EXCEPT TABLE</literal>.
>
> 1b)
> + /*
> + * Only the topmost ancestor of a partitioned table can be specified
> + * in EXCEPT TABLES clause of a FOR ALL TABLES publication. So fetch
> + * the publications excluding the topmost ancestor only.
> + */
> + GetRelationPublications(llast_oid(ancestors), NULL, &exceptpuboids);
> +
>
> 1c)
> + /* Check if the partiton is part of EXCEPT list of any publication */
> + GetRelationPublications(RelationGetRelid(attachrel), NULL, &except_pubids);
> + if (except_pubids != NIL)
> + ereport(ERROR,
> + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> + errmsg("cannot attach relation \"%s\" as partition because it is
> part of EXCEPT list in publication",
> + RelationGetRelationName(attachrel))));
> +
>
> Overall, please take a diff of v35 and v37 to find such parts and
> please correct these and others (if any).
>
> 2)
> Also I don't think if below is correct statement for Approach 1:
>
> + * 2. For a partition, if the topmost ancestor is part of
> + * the EXCEPT TABLE list, we don't publish it.
>
> Even if any ancestor is part of EXECPT list (not only top most) we
> should not publish that partition, isn't it?
>
> 3)
> I tried a scenario and found that incremental replication is not
> working correctly. Attached the failing test as Approach1_v37_fail.txt
>
> Once these basic things are corrected, I can review further.

These comments are addressed in the v38 version patch attached.
Currently the approach-3 changes is present separately in
v38-0002-Restrict-EXCEPT-TABLE-to-root-partitioned-tables-apporach-3.patch
which can be applied on top of
v38-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch.
Similarly the approach-1 changes is present separately in
v38-0002-handle-EXCEPT-TABLE-correctly-with-partitioned-approach-1.patch
which can be applied on top of
v38-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch.
Currently few of the query are logged as LOG messages, I will reduce
the log level for these queries once few rounds of review are
completed on the queries.

Regards,
Vignesh

Attachment Content-Type Size
v38-0002-Restrict-EXCEPT-TABLE-to-root-partitioned-tables-apporach-3.patch text/x-patch 20.6 KB
v38-0002-handle-EXCEPT-TABLE-correctly-with-partitioned-approach-1.patch text/x-patch 26.8 KB
v38-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch text/x-patch 68.0 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-29 21:36:53
Message-ID: CAHut+Psy+osUZ-zPekrFnnW6+h0D_dgpssx=pDpQ03COpCc-mw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Vignesh/Shlok.

1.
I've changed the name of the CF entry [1] for this because EXCEPT
(column-list) is no longer part of the current focus.

BEFORE
Support EXCEPT tables and EXCEPT (column-list) in publications
AFTER
Support EXCEPT tables in publications

2.
I understand the latest patch structure to be like:

0001 + 0002 (approach #1)
or
0001 + 0002 (approach #3)

AFAICT, this is breaking the CF bot, which attempts to apply all
patches at once [2]. IMO, next time you should change the patch suffix
of "0002 (approach #3)" to something like ".txt" or ".nocfbot", so
CFbot won't see it, and we can continue to get CI results for the
other patches.

======
[1] https://commitfest.postgresql.org/patch/6099/
[2] https://cfbot.cputube.org/patch_6099.log

Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-30 08:16:13
Message-ID: CAHut+PsiWwmNSuCXTWM0iPDm3yGskLts-fukELTB__rbBids-A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Vignesh.

Some review comments for v38-0001.

======

1. General. Patch structure

This patch set structure seems muddled to me; I think patch 0001
requires proper handling for EXCEPT (partitions), otherwise, it cannot
be independently committed.

It's my understanding that the goal is to try approach #1, but if that
proves too difficult, then the fallback would be approach #3. Yet
AFAICT this patch 0001 is neither -- I have no idea anymore what patch
0001 does for partitions; IIUC it looks like just old partition logic
from a few versions back (???).

Personally, I felt it would be better to combine 0001 + 0002 (approach
#3), then 0002 would be a patch that *replaces* approach #3 logic with
approach #1 logic. That way, 0001 is self-contained, and 0002 is an
evolution of the feature.

OTOH if the plan is that 0001 and (one of the) 0002 *must* be merged
prior to commit, then I would have expected that the 0001 has no
EXCEPT(partition) logic and not tests at all -- just maybe a bunch of
placeholders that patch 0002 would flesh out.

Anyway, the following review comments are based on the patch set as it
currently stands.

~~~

2. Still unaddressed comments for 3 weeks?

It seems most (all?) of my review comments from 8/January remain
unaddressed in this 0001 patch. Multiple versions have come and gone,
but the following review comments are still pending, according to my
records:

8/1 #1 (code review)
8/1 #3 (code review)
8/1 #1 (internal review)
8/1 #2a (internal review)
8/1 #2b (internal review)
8/1 #C2 (cosmetic review)
8/1 #C3 (cosmetic review)
8/1 #C4 (cosmetic review)
etc..

======
Commit Message

3.
The message needs to explain what this patch is doing regarding
partition tables and partitions. Currently, I have no idea. It seems
just old logic that is neither approach #1 nor approach #3.

======
doc/src/sgml/ref/create_publication.sgml

4.
+ <para>
+ For partitioned tables, when
<literal>publish_via_partition_root</literal>
+ is set to <literal>true</literal>, specifying a root partitioned table in
+ <literal>EXCEPT TABLE</literal> excludes it and all its partitions from
+ replication. Specifying a leaf partition has no effect, as its
changes are
+ still replicated via the root partitioned table. When
+ <literal>publish_via_partition_root</literal> is set to
+ <literal>false</literal>, specifying a root partitioned table has no
+ effect, as changes are replicated via the leaf partitions. Specifying a
+ leaf partition excludes only that partition from replication.
The optional
+ <literal>*</literal> has no meaning for partitioned tables.
+ </para>

4a.
Huh? This is not at all my understanding of how either approach #1 or
approach #3 would work.

~

4b.
I thought the patch set is currently arranged to handle partitions in
the alternate patch 0002s.

So, I expected this doc fragment to be more like:
<para>
For partitioned tables, TBA.
</para>

Later, your subsequent patch 0002 should replace this "TBA" part
according to approach #1 or #3 implementation.

======
src/backend/catalog/pg_publication.c

publication_add_relation:

5.
+ /*
+ * Handle the case where a partition is excluded by EXCEPT TABLE while
+ * publish_via_partition_root = true.
+ */
+ if (pub->alltables && pub->pubviaroot && pri->except &&
+ targetrel->rd_rel->relispartition)
+ ereport(WARNING,
+ (errmsg("partition \"%s\" might be replicated as
publish_via_partition_root is \"%s\"",
+ RelationGetRelationName(targetrel), "true")));
+
+ /*
+ * Handle the case where a partitioned table is excluded by EXCEPT TABLE
+ * while publish_via_partition_root = false.
+ */
+ if (pub->alltables && !pub->pubviaroot && pri->except &&
+ targetrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ ereport(WARNING,
+ (errmsg("partitioned table \"%s\" might be replicated as
publish_via_partition_root is \"%s\"",
+ RelationGetRelationName(targetrel), "false")));
+

Huh? IIUC, this is neither approach #1 nor approach #3.

======
src/backend/replication/pgoutput/pgoutput.c

get_rel_sync_entry:

6.
+ *
+ * If this is a FOR ALL TABLES publication and it has an EXCEPT
+ * TABLE list:
+ *
+ * 1. If pubviaroot is set and the relation is a partition, check
+ * whether the partition root is included in the EXCEPT TABLE
+ * list. If so, do not publish the change.
+ *
+ * 2. If pubviaroot is not set, check whether the relation itself
+ * is included in the EXCEPT TABLE list. If so, do not publish the
+ * change.
+ *
+ * This is achieved by keeping the variable "publish" set to
+ * false. And eventually, entry->pubactions will remain all false
+ * for this publication.

Again, this logic seems to describe neither approach #1 nor approach
#3. So, what is it (???)

======
src/test/subscription/t/037_rep_changes_except_table.pl

7.
IIUC, the patch set is arranged so that the 2 x patch 00002
implementations are for the alternate partition handling. So I was not
expecting patch 0001 to have any partition tests at all.

If 0001 is not implementing approach #1 or approach #3 logic, then
what are these tests testing?

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-01-30 09:12:29
Message-ID: CAJpy0uB-zjzvcH=1Gi3dshQim2WFKmwHnDWpYmOgoa+UrMHVwg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Jan 29, 2026 at 8:41 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Wed, 28 Jan 2026 at 10:46, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > Thank You for the patch.
> >
> > 1)
> > There are certain parts of Approach 3 still present in Approach 1, as
> > an example:
> >
> > 1a)
> > + For partitioned tables, only the root partitioned table may be specified
> > + in <literal>EXCEPT TABLE</literal>.
> >
> > 1b)
> > + /*
> > + * Only the topmost ancestor of a partitioned table can be specified
> > + * in EXCEPT TABLES clause of a FOR ALL TABLES publication. So fetch
> > + * the publications excluding the topmost ancestor only.
> > + */
> > + GetRelationPublications(llast_oid(ancestors), NULL, &exceptpuboids);
> > +
> >
> > 1c)
> > + /* Check if the partiton is part of EXCEPT list of any publication */
> > + GetRelationPublications(RelationGetRelid(attachrel), NULL, &except_pubids);
> > + if (except_pubids != NIL)
> > + ereport(ERROR,
> > + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> > + errmsg("cannot attach relation \"%s\" as partition because it is
> > part of EXCEPT list in publication",
> > + RelationGetRelationName(attachrel))));
> > +
> >
> > Overall, please take a diff of v35 and v37 to find such parts and
> > please correct these and others (if any).
> >
> > 2)
> > Also I don't think if below is correct statement for Approach 1:
> >
> > + * 2. For a partition, if the topmost ancestor is part of
> > + * the EXCEPT TABLE list, we don't publish it.
> >
> > Even if any ancestor is part of EXECPT list (not only top most) we
> > should not publish that partition, isn't it?
> >
> > 3)
> > I tried a scenario and found that incremental replication is not
> > working correctly. Attached the failing test as Approach1_v37_fail.txt
> >
> > Once these basic things are corrected, I can review further.
>
> These comments are addressed in the v38 version patch attached.
> Currently the approach-3 changes is present separately in
> v38-0002-Restrict-EXCEPT-TABLE-to-root-partitioned-tables-apporach-3.patch
> which can be applied on top of
> v38-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch.
> Similarly the approach-1 changes is present separately in
> v38-0002-handle-EXCEPT-TABLE-correctly-with-partitioned-approach-1.patch
> which can be applied on top of
> v38-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch.
> Currently few of the query are logged as LOG messages, I will reduce
> the log level for these queries once few rounds of review are
> completed on the queries.
>

I was trying to test Approach 1 and haven’t fully reviewed or
validated it yet. A few initial observations:

postgres=# CREATE PUBLICATION pub1 for all tables
EXCEPT(tab_part_1,tab_part_2_p2) WITH
(PUBLISH_VIA_PARTITION_ROOT=true);
WARNING: partition "tab_part_1" might be replicated as
publish_via_partition_root is "true"
WARNING: partition "tab_part_2_p2" might be replicated as
publish_via_partition_root is "true"
CREATE PUBLICATION

postgres=# CREATE PUBLICATION pub1 for all tables
EXCEPT(tab_part_1,tab_part_2_p2) WITH
(PUBLISH_VIA_PARTITION_ROOT=false);
WARNING: partitioned table "tab_part_1" might be replicated as
publish_via_partition_root is "false"
CREATE PUBLICATION

IIUC, these Warnings are not expected in Approach1.

thanks
Shveta


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-02 05:31:52
Message-ID: CAJpy0uAOvtMBP-oV9Tgoznt5-UsE2dzAjZW3eJmgKcU-X-vEzg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Jan 30, 2026 at 1:46 PM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Vignesh.
>
> Some review comments for v38-0001.
>
> ======
>
> 1. General. Patch structure
>
> This patch set structure seems muddled to me; I think patch 0001
> requires proper handling for EXCEPT (partitions), otherwise, it cannot
> be independently committed.
>
> It's my understanding that the goal is to try approach #1, but if that
> proves too difficult, then the fallback would be approach #3. Yet
> AFAICT this patch 0001 is neither -- I have no idea anymore what patch
> 0001 does for partitions; IIUC it looks like just old partition logic
> from a few versions back (???).
>
> Personally, I felt it would be better to combine 0001 + 0002 (approach
> #3), then 0002 would be a patch that *replaces* approach #3 logic with
> approach #1 logic. That way, 0001 is self-contained, and 0002 is an
> evolution of the feature.
>

I agree that the current patch structure is hard to follow and doesn’t
add much value, since patch001 isn’t aligned with a specific approach.
How about this patch structure:

patch001: Implement EXCEPT syntax and CREATE PUBLICATION changes. This
includes all changes required to correctly populate
pg_publication_tables and pg_publication_rel.

Expectation for patch001:
When this patch is applied on its own, CREATE PUBLICATION command with
the EXCEPT clause should work, and the appropriate entries should
appear in pg_publication_tables/pg_publication_rel with the except
flag set correctly. No publishing expected in this patch.

patch002: Enable publishing and subscription support.
All changes required to make subscriptions work should go here, including:
--table sync and other subscriber-side changes
--pgoutput logic to determine which tables are published

Expectation for patch002:
Changes should be published and replicated correctly to the subscriber.

patch003: pg_dump, tests, documentation, etc.

All of the above changes/patches are intended to support Approach001.

Approach003 has a limitation in that it allows 'only' ROOT table to be
specified in the EXCEPT clause. If tab_root is listed in EXCEPT and a
user later attempts to attach it as a partition of another table
using:
'ALTER TABLE root ATTACH PARTITION tab_root', we would need to block
the ATTACH PARTITION command. Given this, we should first try to
implement Approach001 and evaluate its feasibility. If it turns out to
be impractical,
we can fall back to Approach003 or consider other alternatives. For
now, the Approach003 patch can remain on hold.

thanks
Shveta


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-02 05:57:02
Message-ID: CAHut+Pv4B6csSdq052ZqKK6Ka76G300f95pJTvZvwLcMQ3buMg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Feb 2, 2026 at 4:32 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Fri, Jan 30, 2026 at 1:46 PM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >
> > Hi Vignesh.
> >
> > Some review comments for v38-0001.
> >
> > ======
> >
> > 1. General. Patch structure
> >
> > This patch set structure seems muddled to me; I think patch 0001
> > requires proper handling for EXCEPT (partitions), otherwise, it cannot
> > be independently committed.
> >
> > It's my understanding that the goal is to try approach #1, but if that
> > proves too difficult, then the fallback would be approach #3. Yet
> > AFAICT this patch 0001 is neither -- I have no idea anymore what patch
> > 0001 does for partitions; IIUC it looks like just old partition logic
> > from a few versions back (???).
> >
> > Personally, I felt it would be better to combine 0001 + 0002 (approach
> > #3), then 0002 would be a patch that *replaces* approach #3 logic with
> > approach #1 logic. That way, 0001 is self-contained, and 0002 is an
> > evolution of the feature.
> >
>
> I agree that the current patch structure is hard to follow and doesn’t
> add much value, since patch001 isn’t aligned with a specific approach.
> How about this patch structure:
>
> patch001: Implement EXCEPT syntax and CREATE PUBLICATION changes. This
> includes all changes required to correctly populate
> pg_publication_tables and pg_publication_rel.
>
> Expectation for patch001:
> When this patch is applied on its own, CREATE PUBLICATION command with
> the EXCEPT clause should work, and the appropriate entries should
> appear in pg_publication_tables/pg_publication_rel with the except
> flag set correctly. No publishing expected in this patch.
>
> patch002: Enable publishing and subscription support.
> All changes required to make subscriptions work should go here, including:
> --table sync and other subscriber-side changes
> --pgoutput logic to determine which tables are published
>
> Expectation for patch002:
> Changes should be published and replicated correctly to the subscriber.
>
> patch003: pg_dump, tests, documentation, etc.
>
> All of the above changes/patches are intended to support Approach001.
>
> Approach003 has a limitation in that it allows 'only' ROOT table to be
> specified in the EXCEPT clause. If tab_root is listed in EXCEPT and a
> user later attempts to attach it as a partition of another table
> using:
> 'ALTER TABLE root ATTACH PARTITION tab_root', we would need to block
> the ATTACH PARTITION command. Given this, we should first try to
> implement Approach001 and evaluate its feasibility. If it turns out to
> be impractical,
> we can fall back to Approach003 or consider other alternatives. For
> now, the Approach003 patch can remain on hold.
>

Hi Shveta,

Your split proposal sounds like an improvement.

Personally, I feel each patch should be *self-contained*, not only
because then it could safely be pushed independently, but also because
I normally work 1 patch at a time
- apply 0001 / review 0001
- apply 0002 / review 0002
- etc

Tests:
IMO if patch 0001 does something then it should also include the
necessary tests for that "something". Then patch 0002 adds something
more so the 0002 tests should evolve to add a few more tests to what
were there for 0001 etc.
IOW, I don't really want to be forced to apply everything in order to
run the tests for 0001.

Docs:
Again personally I prefer everything *self-contained* for 0001 would
have docs for 001 etc, so I can focus on just one improvement at a
time, but I'm OK with docs being kept separated if others prefer it
that way.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-02 06:12:21
Message-ID: CAJpy0uCDJg9BbnQVRNskwCA9dfH-GbU1wdQxG1Bdiry-xJDrHg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Feb 2, 2026 at 11:27 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> On Mon, Feb 2, 2026 at 4:32 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > On Fri, Jan 30, 2026 at 1:46 PM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> > >
> > > Hi Vignesh.
> > >
> > > Some review comments for v38-0001.
> > >
> > > ======
> > >
> > > 1. General. Patch structure
> > >
> > > This patch set structure seems muddled to me; I think patch 0001
> > > requires proper handling for EXCEPT (partitions), otherwise, it cannot
> > > be independently committed.
> > >
> > > It's my understanding that the goal is to try approach #1, but if that
> > > proves too difficult, then the fallback would be approach #3. Yet
> > > AFAICT this patch 0001 is neither -- I have no idea anymore what patch
> > > 0001 does for partitions; IIUC it looks like just old partition logic
> > > from a few versions back (???).
> > >
> > > Personally, I felt it would be better to combine 0001 + 0002 (approach
> > > #3), then 0002 would be a patch that *replaces* approach #3 logic with
> > > approach #1 logic. That way, 0001 is self-contained, and 0002 is an
> > > evolution of the feature.
> > >
> >
> > I agree that the current patch structure is hard to follow and doesn’t
> > add much value, since patch001 isn’t aligned with a specific approach.
> > How about this patch structure:
> >
> > patch001: Implement EXCEPT syntax and CREATE PUBLICATION changes. This
> > includes all changes required to correctly populate
> > pg_publication_tables and pg_publication_rel.
> >
> > Expectation for patch001:
> > When this patch is applied on its own, CREATE PUBLICATION command with
> > the EXCEPT clause should work, and the appropriate entries should
> > appear in pg_publication_tables/pg_publication_rel with the except
> > flag set correctly. No publishing expected in this patch.
> >
> > patch002: Enable publishing and subscription support.
> > All changes required to make subscriptions work should go here, including:
> > --table sync and other subscriber-side changes
> > --pgoutput logic to determine which tables are published
> >
> > Expectation for patch002:
> > Changes should be published and replicated correctly to the subscriber.
> >
> > patch003: pg_dump, tests, documentation, etc.
> >
> > All of the above changes/patches are intended to support Approach001.
> >
> > Approach003 has a limitation in that it allows 'only' ROOT table to be
> > specified in the EXCEPT clause. If tab_root is listed in EXCEPT and a
> > user later attempts to attach it as a partition of another table
> > using:
> > 'ALTER TABLE root ATTACH PARTITION tab_root', we would need to block
> > the ATTACH PARTITION command. Given this, we should first try to
> > implement Approach001 and evaluate its feasibility. If it turns out to
> > be impractical,
> > we can fall back to Approach003 or consider other alternatives. For
> > now, the Approach003 patch can remain on hold.
> >
>
> Hi Shveta,
>
> Your split proposal sounds like an improvement.
>
> Personally, I feel each patch should be *self-contained*, not only
> because then it could safely be pushed independently, but also because
> I normally work 1 patch at a time
> - apply 0001 / review 0001
> - apply 0002 / review 0002
> - etc
>
> Tests:
> IMO if patch 0001 does something then it should also include the
> necessary tests for that "something". Then patch 0002 adds something
> more so the 0002 tests should evolve to add a few more tests to what
> were there for 0001 etc.
> IOW, I don't really want to be forced to apply everything in order to
> run the tests for 0001.

+1. we should be adding tests in the concerned patch

>
> Docs:
> Again personally I prefer everything *self-contained* for 0001 would
> have docs for 001 etc, so I can focus on just one improvement at a
> time, but I'm OK with docs being kept separated if others prefer it
> that way.

I think splitting the doccould be challenging. We can start by keeping
it in patch003, and once we have better clarity, we can consider
splitting the doc if needed.
OTOH, each patch’s commit message should clearly state its purpose, so
the EXCEPT concept can be understood without referring to the doc
coming in later patch.

thanks
Shveta


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-02 11:48:45
Message-ID: CANhcyEXP5BS+0Hq2o=Jmx6J5Nf+H0TW9yayO21NnVwtFqauDGw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 29 Jan 2026 at 20:41, vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Wed, 28 Jan 2026 at 10:46, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > Thank You for the patch.
> >
> > 1)
> > There are certain parts of Approach 3 still present in Approach 1, as
> > an example:
> >
> > 1a)
> > + For partitioned tables, only the root partitioned table may be specified
> > + in <literal>EXCEPT TABLE</literal>.
> >
> > 1b)
> > + /*
> > + * Only the topmost ancestor of a partitioned table can be specified
> > + * in EXCEPT TABLES clause of a FOR ALL TABLES publication. So fetch
> > + * the publications excluding the topmost ancestor only.
> > + */
> > + GetRelationPublications(llast_oid(ancestors), NULL, &exceptpuboids);
> > +
> >
> > 1c)
> > + /* Check if the partiton is part of EXCEPT list of any publication */
> > + GetRelationPublications(RelationGetRelid(attachrel), NULL, &except_pubids);
> > + if (except_pubids != NIL)
> > + ereport(ERROR,
> > + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> > + errmsg("cannot attach relation \"%s\" as partition because it is
> > part of EXCEPT list in publication",
> > + RelationGetRelationName(attachrel))));
> > +
> >
> > Overall, please take a diff of v35 and v37 to find such parts and
> > please correct these and others (if any).
> >
> > 2)
> > Also I don't think if below is correct statement for Approach 1:
> >
> > + * 2. For a partition, if the topmost ancestor is part of
> > + * the EXCEPT TABLE list, we don't publish it.
> >
> > Even if any ancestor is part of EXECPT list (not only top most) we
> > should not publish that partition, isn't it?
> >
> > 3)
> > I tried a scenario and found that incremental replication is not
> > working correctly. Attached the failing test as Approach1_v37_fail.txt
> >
> > Once these basic things are corrected, I can review further.
>
> These comments are addressed in the v38 version patch attached.
> Currently the approach-3 changes is present separately in
> v38-0002-Restrict-EXCEPT-TABLE-to-root-partitioned-tables-apporach-3.patch
> which can be applied on top of
> v38-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch.
> Similarly the approach-1 changes is present separately in
> v38-0002-handle-EXCEPT-TABLE-correctly-with-partitioned-approach-1.patch
> which can be applied on top of
> v38-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch.
> Currently few of the query are logged as LOG messages, I will reduce
> the log level for these queries once few rounds of review are
> completed on the queries.

Hi Vignesh,

I reviewed v38-0002-handle-EXCEPT-TABLE-correctly-with-partitioned-approach-1.patch
patch. Here are my comments:

1. in pgoutput.c:
@@ -2228,6 +2228,11 @@ get_rel_sync_entry(PGOutputData *data, Relation relation)
{
List *ancestors = get_partition_ancestors(relid);

+ GetRelationPublications(relid, NULL, &exceptpubids);
+
+ foreach_oid(ancestor, ancestors)
+ GetRelationPublications(ancestor, NULL, &exceptpubids);
+
pub_relid = llast_oid(ancestors);
ancestor_level = list_length(ancestors);
}

when we create a publication on a partitioned table and
publish_via_partition_root is false,
the changes of the partitions should not be published as discussed.
But, while testing I found that the changes are being published.

Test:
CREATE SCHEMA sc1;
CREATE TABLE sc1.t1(id int) PARTITION BY RANGE(id);
CREATE TABLE sc1.child1(id int) PARTITION BY RANGE(id);
CREATE TABLE sc1.child2 PARTITION OF sc1.t1 FOR VALUES FROM (101) TO (200);
CREATE TABLE sc1.child1_1 PARTITION OF sc1.child1 FOR VALUES FROM (0) TO (50);
CREATE TABLE sc1.child1_2 PARTITION OF sc1.child1 FOR VALUES FROM (51) TO (100);
ALTER TABLE sc1.t1 ATTACH PARTITION sc1.child1 FOR VALUES FROM (0) TO (100);

CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE (sc1.t1);
insert into sc1. t1 values (1), (60), (150);

I get following output:
postgres=# SELECT * FROM pg_logical_slot_get_binary_changes(
's1',
NULL,
NULL,
'proto_version', '1',
'publication_names', 'pub1'
);
lsn | xid | data
------------+-----+----------------------------------------------------------------------
0/0175A1A0 | 777 | \x42000000000175a3f80002eccfc016338000000309
0/0175A1A0 | 777 |
\x520000400a736331006368696c64315f31006400010069640000000017ffffffff
0/0175A1A0 | 777 | \x490000400a4e0001740000000131
0/0175A268 | 777 |
\x520000400d736331006368696c64315f32006400010069640000000017ffffffff
0/0175A268 | 777 | \x490000400d4e000174000000023630
0/0175A330 | 777 |
\x5200004007736331006368696c6432006400010069640000000017ffffffff
0/0175A330 | 777 | \x49000040074e00017400000003313530
0/0175A428 | 777 | \x4300000000000175a3f8000000000175a4280002eccfc0163380
(8 rows)

I think this check should be done irrespective of the value of
publish_via_partition_root.
+ foreach_oid(ancestor, ancestors)
+ GetRelationPublications(ancestor, NULL, &exceptpubids);

2. In get_rel_sync_entry we have a comment:
*
* 2. If pubviaroot is not set, check whether the relation itself
* is included in the EXCEPT TABLE list. If so, do not publish the
* change.
*
This comment does not seem correct. Even if publish_via_partition_root
is false, we should not publish changes if any of its ancestors is
excluded.
This is my understanding of approach 1 [1]. Correct me if I am wrong.

3. In tablesync.c:

+ /*
+ * Store the tables as a list of schemaname and tablename.
+ */
+ natt = 0;
this assignment 'natt = 0', is not required

4. While testing, I noticed that the new query introduced in tablesync
can be invoked for "FOR TABLE". SHould we only call it for "ALL
TABLES" publications?
+ if (server_version >= 190000 && !is_partition &&
+ lrel->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ resetStringInfo(&cmd);
+
+ /*
+ * This query recursively traverses the inheritance (partition) tree
+ * starting from the given table OID and determines which leaf
+ * relations should be included for replication. Exclusion propagates
+ * from parent to child, and a relation is also treated as excluded if
+ * it is explicitly marked with prexcept = true in pg_publication_rel
+ * for the specified publications. The final result returns only
+ * non excluded leaf relations.
+ */
Test:
Create publication for table sc1.t1 using (publish_via_partition_root
= true) and create subscription on it. In subscriber logs we can see
the logs for the new query.
sc1.t1 has the same structure as in comment 1.

5. I was testing some scenarios and found a difference in behaviour of
tablesync and incremental changes.
Consider the same table structure as comment1. But we have two publications as:
CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE (sc1.child1) WITH
(publish_via_partition_root = true);
CREATE PUBLICATION pub2 FOR ALL TABLES WITH (publish_via_partition_root = true);

And subscription is created
CREATE SUBSCRIPTION sub1 CONNECTION 'host=localhost port=5432
dbname=postgres' PUBLICATION pub1, pub2;

Before creating the subscription I did a insert on publisher node:
INSERT INTO sc1.t1 VALUES(1), (51), (101);

Output after tablesync:
postgres=# select * from sc1.t1;
id
-----
101
(1 row)

Now, I again did a insert on publisher node:
INSERT INTO sc1.t1 VALUES(1), (51), (101);

Output after incremental sync:
postgres=# select * from sc1.t1;
id
-----
101
1
51
101
(4 rows)

What should be the behaviour if a partitioned table is published by a
publication and excluded by another publication?

I checked the behaviour of publication with row_filter for similar conditions:
CREATE PUBLICATION pub1 FOR TABLE sc1.t1 WHERE (id > 100) WITH
(publish_via_partition_root = true);
CREATE PUBLICATION pub2 FOR TABLE sc1.t1 WITH
(publish_via_partition_root = true);

Here is the behaviour:
Before creating the publication I did a insert on publisher node:
INSERT INTO sc1.t1 VALUES(1), (51), (101);

Output after tablesync:
postgres=# select * from sc1.t1;
id
-----
101
1
51
(3 rows)

Now, I again did a insert on publisher node:
INSERT INTO sc1.t1 VALUES(1), (51), (101);

Output after incremental sync:
postgres=# select * from sc1.t1;
id
-----
101
1
51
1
51
101
(6 rows)

So, I think in the EXCEPT table case we should follow the same
behaviour with tablesync i.e. publish the change if any of the
publications publishes it . Thoughts?

[1]: https://www.postgresql.org/message-id/CAJpy0uD81HRrMYr7S-6AV4W2PtbGKM-nf2D89zsoMHJ9jZssUg@mail.gmail.com

Thanks,
Shlok Kyal


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-03 16:52:52
Message-ID: CALDaNm1Y5C_-gOA95a+07P5z4DY=PuXbnvdqMT6g7t7OEKD2YA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 2 Feb 2026 at 17:18, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> I reviewed v38-0002-handle-EXCEPT-TABLE-correctly-with-partitioned-approach-1.patch
> patch. Here are my comments:
>
> 4. While testing, I noticed that the new query introduced in tablesync
> can be invoked for "FOR TABLE". SHould we only call it for "ALL
> TABLES" publications?
> + if (server_version >= 190000 && !is_partition &&
> + lrel->relkind == RELKIND_PARTITIONED_TABLE)
> + {
> + resetStringInfo(&cmd);
> +
> + /*
> + * This query recursively traverses the inheritance (partition) tree
> + * starting from the given table OID and determines which leaf
> + * relations should be included for replication. Exclusion propagates
> + * from parent to child, and a relation is also treated as excluded if
> + * it is explicitly marked with prexcept = true in pg_publication_rel
> + * for the specified publications. The final result returns only
> + * non excluded leaf relations.
> + */
> Test:
> Create publication for table sc1.t1 using (publish_via_partition_root
> = true) and create subscription on it. In subscriber logs we can see
> the logs for the new query.
> sc1.t1 has the same structure as in comment 1.

We will not know if it is a table publication or all tables
publication from here. Also there can be a possibility of multiple
publications. We will invoke it and handle it from the publisher to
return appropriate tables.

Thanks for the review and detailed comments. All remaining feedback
has been addressed in the attached v39 patch.

In addition, the SQL query previously used to compute the set of
effective tables has been replaced with a C implementation. The SQL
approach had become increasingly complex and difficult to reason
about, especially as more publication combinations were added.
Implementing this logic in C significantly improves readability and
maintainability, and makes it easier to handle complex scenarios, such
as:
a) Multiple publications where one publication has no EXCEPT tables
and another does.
b) Multiple publications where one publication is an ALL TABLES
publication with EXCEPT, while another is a table-specific
publication.
c) Multiple publications where none of the publications define any
EXCEPT tables.

Peter's comments from [1] and Shveta's comments form [2] will be
addressed in the next version.
[1] - https://www.postgresql.org/message-id/CAHut%2BPsiWwmNSuCXTWM0iPDm3yGskLts-fukELTB__rbBids-A%40mail.gmail.com
[2] - https://www.postgresql.org/message-id/CAJpy0uAOvtMBP-oV9Tgoznt5-UsE2dzAjZW3eJmgKcU-X-vEzg%40mail.gmail.com

Regards,
Vignesh

Attachment Content-Type Size
v39-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/x-patch 68.0 KB
v39-0002-handle-EXCEPT-TABLE-correctly-with-partitioned-t.patch application/x-patch 39.7 KB

From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-04 08:16:06
Message-ID: CANhcyEWz2Pmcgtt73kV5E5YY=5LSM-YqCXSinoBHL_y=HYMZRQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, 3 Feb 2026 at 22:23, vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Mon, 2 Feb 2026 at 17:18, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > I reviewed v38-0002-handle-EXCEPT-TABLE-correctly-with-partitioned-approach-1.patch
> > patch. Here are my comments:
> >
> > 4. While testing, I noticed that the new query introduced in tablesync
> > can be invoked for "FOR TABLE". SHould we only call it for "ALL
> > TABLES" publications?
> > + if (server_version >= 190000 && !is_partition &&
> > + lrel->relkind == RELKIND_PARTITIONED_TABLE)
> > + {
> > + resetStringInfo(&cmd);
> > +
> > + /*
> > + * This query recursively traverses the inheritance (partition) tree
> > + * starting from the given table OID and determines which leaf
> > + * relations should be included for replication. Exclusion propagates
> > + * from parent to child, and a relation is also treated as excluded if
> > + * it is explicitly marked with prexcept = true in pg_publication_rel
> > + * for the specified publications. The final result returns only
> > + * non excluded leaf relations.
> > + */
> > Test:
> > Create publication for table sc1.t1 using (publish_via_partition_root
> > = true) and create subscription on it. In subscriber logs we can see
> > the logs for the new query.
> > sc1.t1 has the same structure as in comment 1.
>
> We will not know if it is a table publication or all tables
> publication from here. Also there can be a possibility of multiple
> publications. We will invoke it and handle it from the publisher to
> return appropriate tables.
>
> Thanks for the review and detailed comments. All remaining feedback
> has been addressed in the attached v39 patch.
>
> In addition, the SQL query previously used to compute the set of
> effective tables has been replaced with a C implementation. The SQL
> approach had become increasingly complex and difficult to reason
> about, especially as more publication combinations were added.
> Implementing this logic in C significantly improves readability and
> maintainability, and makes it easier to handle complex scenarios, such
> as:
> a) Multiple publications where one publication has no EXCEPT tables
> and another does.
> b) Multiple publications where one publication is an ALL TABLES
> publication with EXCEPT, while another is a table-specific
> publication.
> c) Multiple publications where none of the publications define any
> EXCEPT tables.
>
> Peter's comments from [1] and Shveta's comments form [2] will be
> addressed in the next version.
> [1] - https://www.postgresql.org/message-id/CAHut%2BPsiWwmNSuCXTWM0iPDm3yGskLts-fukELTB__rbBids-A%40mail.gmail.com
> [2] - https://www.postgresql.org/message-id/CAJpy0uAOvtMBP-oV9Tgoznt5-UsE2dzAjZW3eJmgKcU-X-vEzg%40mail.gmail.com
>
Hi Vignesh,

Thanks for providing the updated patch.
While testing the patch I have found a small bug:
```
+ if (am_partition)
{
List *ancestors = get_partition_ancestors(relid);

- pub_relid = llast_oid(ancestors);
- ancestor_level = list_length(ancestors);
+ foreach_oid(ancestor, ancestors)
+ GetRelationPublications(ancestor, NULL, &exceptpubids);
+
+ if (pub->pubviaroot)
+ {
+ pub_relid = llast_oid(ancestors);
+ ancestor_level = list_length(ancestors);
+ }
}

GetRelationPublications(pub_relid, NULL, &exceptpubids);
```
Here at last "GetRelationPublications" should be called for 'relid',
instead of 'pub_relid'. The call for function
"GetRelationPublications" can be skipped for table which is not root
partitioned but is specified explicitly in the EXCEPT TABLE list.
Test:
The partition structure is as:
sc1.t1
- sc1.child1
- sc1.child1_1
- sc1.child1_2
- sc1.child2

Suppose we create two publications.
CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE (sc1.child2) WITH
(publish_via_partition_root = true);
CREATE PUBLICATION pub2 FOR TABLE sc1.child1_1 WITH
(publish_via_partition_root = true);
And on subscriber node we create a subscriber as:
CREATE SUBSCRIPTION sub1 CONNECTION 'host=localhost port=5432
dbname=postgres' PUBLICATION pub1, pub2;

Ideally changes of 'sc1.child2' should not be replicated, but
increment sync replicates the data for 'sc1.child2'.
I have fixed this in the latest version of patch.
I have also added extended tests for this patch as 0003 patch. The
last test in the file tests the above issue.

I have also addressed Peter's comment in [1].
For comment:
> 3.
> + appendPQExpBuffer(query, "ONLY %s", fmtQualifiedDumpable(tbinfo));
>
> I think that unconditionally choosing "ONLY" here may not be the right
> thing to do, particularly when the excluded table is a partitioned
> table. (e.g. this is related to off-list discussions about how to
> EXCEPT partition tables).
The ONLY clause has no effect with partition tables but ONLY clause is
required for inherited tables.
And ALTER PUBLICATION ... ADD TABLE also uses ONLY clause
unconditionally. So, I think this behaviour is consistent with ALTER
PUBLICATION ... ADD TABLE
According to the latest discussion, I think we are proceeding with
Approach 1 in [2]. And EXCEPT TABLE is independent of ONLY. So, I
think we can keep it.

[1]: https://www.postgresql.org/message-id/CAHut+PvmCPdbScDoGV3jX42STm2F3DUWbj7nnbn5Y_zs6w8XWA@mail.gmail.com
[2]: https://www.postgresql.org/message-id/CAJpy0uD81HRrMYr7S-6AV4W2PtbGKM-nf2D89zsoMHJ9jZssUg@mail.gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v40-0002-handle-EXCEPT-TABLE-correctly-with-partitioned-t.patch application/octet-stream 39.5 KB
v40-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 67.8 KB
v40-0003-Extended-tests-for-EXCEPT-TABLE-patch.patch application/octet-stream 5.0 KB

From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-05 05:29:06
Message-ID: CANhcyEWda-0kWVCn8zQ4z9snFK4sCo1-JEewFGWs-9PMrJAmrg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, 3 Feb 2026 at 22:23, vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Mon, 2 Feb 2026 at 17:18, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > I reviewed v38-0002-handle-EXCEPT-TABLE-correctly-with-partitioned-approach-1.patch
> > patch. Here are my comments:
> >
> > 4. While testing, I noticed that the new query introduced in tablesync
> > can be invoked for "FOR TABLE". SHould we only call it for "ALL
> > TABLES" publications?
> > + if (server_version >= 190000 && !is_partition &&
> > + lrel->relkind == RELKIND_PARTITIONED_TABLE)
> > + {
> > + resetStringInfo(&cmd);
> > +
> > + /*
> > + * This query recursively traverses the inheritance (partition) tree
> > + * starting from the given table OID and determines which leaf
> > + * relations should be included for replication. Exclusion propagates
> > + * from parent to child, and a relation is also treated as excluded if
> > + * it is explicitly marked with prexcept = true in pg_publication_rel
> > + * for the specified publications. The final result returns only
> > + * non excluded leaf relations.
> > + */
> > Test:
> > Create publication for table sc1.t1 using (publish_via_partition_root
> > = true) and create subscription on it. In subscriber logs we can see
> > the logs for the new query.
> > sc1.t1 has the same structure as in comment 1.
>
> We will not know if it is a table publication or all tables
> publication from here. Also there can be a possibility of multiple
> publications. We will invoke it and handle it from the publisher to
> return appropriate tables.
>
> Thanks for the review and detailed comments. All remaining feedback
> has been addressed in the attached v39 patch.
>
> In addition, the SQL query previously used to compute the set of
> effective tables has been replaced with a C implementation. The SQL
> approach had become increasingly complex and difficult to reason
> about, especially as more publication combinations were added.
> Implementing this logic in C significantly improves readability and
> maintainability, and makes it easier to handle complex scenarios, such
> as:
> a) Multiple publications where one publication has no EXCEPT tables
> and another does.
> b) Multiple publications where one publication is an ALL TABLES
> publication with EXCEPT, while another is a table-specific
> publication.
> c) Multiple publications where none of the publications define any
> EXCEPT tables.
>
> Peter's comments from [1] and Shveta's comments form [2] will be
> addressed in the next version.
> [1] - https://www.postgresql.org/message-id/CAHut%2BPsiWwmNSuCXTWM0iPDm3yGskLts-fukELTB__rbBids-A%40mail.gmail.com
> [2] - https://www.postgresql.org/message-id/CAJpy0uAOvtMBP-oV9Tgoznt5-UsE2dzAjZW3eJmgKcU-X-vEzg%40mail.gmail.com

Hi Vignesh,

I found one bug.

For Partition structure:
sc1.t1
- sc1.child1
- sc1.child1_1
- sc1.child1_2
- sc1.child2

If we specify sc1.child1 and sc1.child2 in the EXCEPT list and
publish_via_partition_root = true,
tablesync publish all the changes. It is wrong.
Behavour of incremental sync is correct and it donot publish any changes.
Publication:
CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE (sc1.child1,
sc1.child2) WITH (publish_via_partition_root = true);

I checked, pg_get_publication_effective_tables is not returning any row:
postgres=# SELECT schemaname, relname FROM
pg_get_publication_effective_tables(16385, ARRAY['pub1']);
schemaname | relname
------------+---------
(0 rows)

But the COPY command in tablesync is formed as:
COPY sc1.t1 (id) TO STDOUT

Same behaviour when publication is:
CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLE (sc1.child1_1,
sc1.child1_2, sc1.child2) WITH (publish_via_partition_root = true);

I think it is because, when we specify all the partitions of a
partitioned table in the EXCEPT list, the function
'fetch_remote_table_info' will have 'effective_relations' as an empty
list.
So, instead of the condition 'if (effective_relations &&
list_length(effective_relations))' it will go inside the 'else if'
condition and form the above COPY command.

One possible solution I can think of is if all the partitions of a
partitioned table is excluded using EXCEPT TABLE, we can avoid having
the partitioned table in 'pg_publication_tables' and hence the
pg_subsciption_rel will also not have the corresponding entry.
So, the issue can be avoided.

I have added the fix of the same in the latest v41 patch and added the
corresponding test in 101_test.pl file.
I have also merged the v40-0001 and v40-0002 patches to form v41-0001
patch and v41-0002 has the extended tests.

Thanks,
Shlok Kyal

Attachment Content-Type Size
v41-0002-Extended-tests-for-EXCEPT-TABLE-patch.patch application/octet-stream 6.2 KB
v41-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 90.5 KB

From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-06 10:23:57
Message-ID: CAJpy0uB=gaJgDaP8MiVeZmpxALrmDPbx=fqoidAbzhwEO3cv-g@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Feb 5, 2026 at 10:59 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> I have added the fix of the same in the latest v41 patch and added the
> corresponding test in 101_test.pl file.
> I have also merged the v40-0001 and v40-0002 patches to form v41-0001
> patch and v41-0002 has the extended tests.
>

Thank You for the patched Shlok. While testing I found a case where
table-sync and incremental-sync are not replicating same set of
tables.

I have attached the test-case and results in DifferentPubViaRoot.txt

The problem happens when we have a subscriber subscribing to multiple
pubs with different EXCEPT and different PUBLISH_VIA_PARTITION_ROOT
value. Example:

CREATE PUBLICATION pub1 for ALL TABLES EXCEPT table (tab_part_1_p1,
tab_part_2_p2) WITH (PUBLISH_VIA_PARTITION_ROOT=true);
CREATE PUBLICATION pub2 for ALL TABLES EXCEPT table (tab_part_2) WITH
(PUBLISH_VIA_PARTITION_ROOT=false);

We need to decide the behaviour of such a case for Apporach1. It will
be good to analyze row-filter and column-list behaviour for equivalent
cases i.e. publication publishing the same set of tables with
different row-filters and different PUBLISH_VIA_PARTITION_ROOT value.
Once we have clarity on that, we can decide about the behaviour here.

thanks
Shveta

Attachment Content-Type Size
DifferentPubViaRoot.txt text/plain 4.5 KB

From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-08 10:20:58
Message-ID: CAA4eK1J9=vfNYU=K=0pfEf=b8iZFB0FGocCOpJL1tdTY-g94uw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Feb 6, 2026 at 3:54 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Thu, Feb 5, 2026 at 10:59 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > I have added the fix of the same in the latest v41 patch and added the
> > corresponding test in 101_test.pl file.
> > I have also merged the v40-0001 and v40-0002 patches to form v41-0001
> > patch and v41-0002 has the extended tests.
> >
>
> Thank You for the patched Shlok. While testing I found a case where
> table-sync and incremental-sync are not replicating same set of
> tables.
>
> I have attached the test-case and results in DifferentPubViaRoot.txt
>
> The problem happens when we have a subscriber subscribing to multiple
> pubs with different EXCEPT and different PUBLISH_VIA_PARTITION_ROOT
> value. Example:
>
> CREATE PUBLICATION pub1 for ALL TABLES EXCEPT table (tab_part_1_p1,
> tab_part_2_p2) WITH (PUBLISH_VIA_PARTITION_ROOT=true);
> CREATE PUBLICATION pub2 for ALL TABLES EXCEPT table (tab_part_2) WITH
> (PUBLISH_VIA_PARTITION_ROOT=false);
>
> We need to decide the behaviour of such a case for Apporach1.
>

It is better to disallow such combinations where combining
publications could lead to contradictory behavior. For example, pub1:
FOR ALL Tables EXCEPT (tab1) and pub2: FOR TABLE tab1. Now, combining
pub1 and pub2 via subscription should result in an ERROR. We have
similar restrictions for column lists. See section: "Warning:
Combining Column Lists from Multiple Publications" in docs [1]. Does
that sound reasonable to you?

[1] - https://www.postgresql.org/docs/devel/logical-replication-col-lists.html

--
With Regards,
Amit Kapila.


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-09 01:10:52
Message-ID: CAHut+PsxDe-mVq_6YyhaUCyPUuohZE5dRtf80syP3y_n+Z6Tog@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sun, Feb 8, 2026 at 9:21 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Fri, Feb 6, 2026 at 3:54 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > On Thu, Feb 5, 2026 at 10:59 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > >
> > > I have added the fix of the same in the latest v41 patch and added the
> > > corresponding test in 101_test.pl file.
> > > I have also merged the v40-0001 and v40-0002 patches to form v41-0001
> > > patch and v41-0002 has the extended tests.
> > >
> >
> > Thank You for the patched Shlok. While testing I found a case where
> > table-sync and incremental-sync are not replicating same set of
> > tables.
> >
> > I have attached the test-case and results in DifferentPubViaRoot.txt
> >
> > The problem happens when we have a subscriber subscribing to multiple
> > pubs with different EXCEPT and different PUBLISH_VIA_PARTITION_ROOT
> > value. Example:
> >
> > CREATE PUBLICATION pub1 for ALL TABLES EXCEPT table (tab_part_1_p1,
> > tab_part_2_p2) WITH (PUBLISH_VIA_PARTITION_ROOT=true);
> > CREATE PUBLICATION pub2 for ALL TABLES EXCEPT table (tab_part_2) WITH
> > (PUBLISH_VIA_PARTITION_ROOT=false);
> >
> > We need to decide the behaviour of such a case for Apporach1.
> >
>
> It is better to disallow such combinations where combining
> publications could lead to contradictory behavior. For example, pub1:
> FOR ALL Tables EXCEPT (tab1) and pub2: FOR TABLE tab1. Now, combining
> pub1 and pub2 via subscription should result in an ERROR. We have
> similar restrictions for column lists. See section: "Warning:
> Combining Column Lists from Multiple Publications" in docs [1]. Does
> that sound reasonable to you?
>
> [1] - https://www.postgresql.org/docs/devel/logical-replication-col-lists.html
>

Hi Amit.

I understand there can be some tricky scenarios where partitions are
involved, but I was not sure why "pub1: FOR ALL Tables EXCEPT (tab1)
and pub2: FOR TABLE tab1" is an example of contradictory behaviour.

Consider if the publisher has 3 tables tab1,tab2,tab3:
Here, "pub1: FOR ALL Tables EXCEPT (tab1)" is like a shorthand for
saying "pub1: FOR TABLE tab2,tab3"
So what's wrong for the subscriber to combine pub1 and pub2 in this case?

Indeed, if the user wants ALL TABLES, but they want a row filter
applied *only* for tab1, isn't this combination probably a good way to
achieve that? e.g. "pub1: FOR ALL Tables EXCEPT (tab1) and pub2: FOR
TABLE tab1 WHERE (c == 99)".

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-09 05:36:03
Message-ID: CAA4eK1JXdUArUqJ_uPjwXcYR8qj2hJyVORdRNhmx9=Kp0EXumg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Feb 9, 2026 at 6:41 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> On Sun, Feb 8, 2026 at 9:21 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> > On Fri, Feb 6, 2026 at 3:54 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> > >
> > > On Thu, Feb 5, 2026 at 10:59 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > > >
> > > > I have added the fix of the same in the latest v41 patch and added the
> > > > corresponding test in 101_test.pl file.
> > > > I have also merged the v40-0001 and v40-0002 patches to form v41-0001
> > > > patch and v41-0002 has the extended tests.
> > > >
> > >
> > > Thank You for the patched Shlok. While testing I found a case where
> > > table-sync and incremental-sync are not replicating same set of
> > > tables.
> > >
> > > I have attached the test-case and results in DifferentPubViaRoot.txt
> > >
> > > The problem happens when we have a subscriber subscribing to multiple
> > > pubs with different EXCEPT and different PUBLISH_VIA_PARTITION_ROOT
> > > value. Example:
> > >
> > > CREATE PUBLICATION pub1 for ALL TABLES EXCEPT table (tab_part_1_p1,
> > > tab_part_2_p2) WITH (PUBLISH_VIA_PARTITION_ROOT=true);
> > > CREATE PUBLICATION pub2 for ALL TABLES EXCEPT table (tab_part_2) WITH
> > > (PUBLISH_VIA_PARTITION_ROOT=false);
> > >
> > > We need to decide the behaviour of such a case for Apporach1.
> > >
> >
> > It is better to disallow such combinations where combining
> > publications could lead to contradictory behavior. For example, pub1:
> > FOR ALL Tables EXCEPT (tab1) and pub2: FOR TABLE tab1. Now, combining
> > pub1 and pub2 via subscription should result in an ERROR. We have
> > similar restrictions for column lists. See section: "Warning:
> > Combining Column Lists from Multiple Publications" in docs [1]. Does
> > that sound reasonable to you?
> >
> > [1] - https://www.postgresql.org/docs/devel/logical-replication-col-lists.html
> >
>
> Hi Amit.
>
> I understand there can be some tricky scenarios where partitions are
> involved, but I was not sure why "pub1: FOR ALL Tables EXCEPT (tab1)
> and pub2: FOR TABLE tab1" is an example of contradictory behaviour.
>
> Consider if the publisher has 3 tables tab1,tab2,tab3:
> Here, "pub1: FOR ALL Tables EXCEPT (tab1)" is like a shorthand for
> saying "pub1: FOR TABLE tab2,tab3"
> So what's wrong for the subscriber to combine pub1 and pub2 in this case?
>

It is because one of the publications (pub2) indicates to include a
particular table tab1 and the other one (pub1) to exclude the same
table. And things become much more complex when the Except list
contains partitions as shown in Shveta's example. So, I think it makes
sense to keep things simple at least for the first version, we can
consider to uplift this restriction if we see some use cases from the
field.

--
With Regards,
Amit Kapila.


From: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-09 06:22:55
Message-ID: CAKFQuwauV8v46mM3kZ9ducnN9Oq6E2etLbvf5KxVj4K0CEZKHg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sunday, February 8, 2026, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:

> On Mon, Feb 9, 2026 at 6:41 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> > Hi Amit.
> >
> > I understand there can be some tricky scenarios where partitions are
> > involved, but I was not sure why "pub1: FOR ALL Tables EXCEPT (tab1)
> > and pub2: FOR TABLE tab1" is an example of contradictory behaviour.
> >
> > Consider if the publisher has 3 tables tab1,tab2,tab3:
> > Here, "pub1: FOR ALL Tables EXCEPT (tab1)" is like a shorthand for
> > saying "pub1: FOR TABLE tab2,tab3"
> > So what's wrong for the subscriber to combine pub1 and pub2 in this case?
> >
>
> It is because one of the publications (pub2) indicates to include a
> particular table tab1 and the other one (pub1) to exclude the same
> table. And things become much more complex when the Except list
> contains partitions as shown in Shveta's example. So, I think it makes
> sense to keep things simple at least for the first version, we can
> consider to uplift this restriction if we see some use cases from the
> field.
>
>
>
I’m with Peter here - I do not think it is wise to expose the exception
listing outside the publication. Publication combinations should be purely
additive in much the same way grants are in the system. Except lists are
internal shorthand for describing the positive list of tables a publication
makes available - all tables except.

David J.


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-10 06:05:13
Message-ID: CAJpy0uC_0uvhmXyWegKGRozhpyoLGHwHrUAK=Wk+bSmzqLMoSw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Feb 9, 2026 at 11:52 AM David G. Johnston
<david(dot)g(dot)johnston(at)gmail(dot)com> wrote:
>
> On Sunday, February 8, 2026, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>>
>> On Mon, Feb 9, 2026 at 6:41 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>>
>> > Hi Amit.
>> >
>> > I understand there can be some tricky scenarios where partitions are
>> > involved, but I was not sure why "pub1: FOR ALL Tables EXCEPT (tab1)
>> > and pub2: FOR TABLE tab1" is an example of contradictory behaviour.
>> >
>> > Consider if the publisher has 3 tables tab1,tab2,tab3:
>> > Here, "pub1: FOR ALL Tables EXCEPT (tab1)" is like a shorthand for
>> > saying "pub1: FOR TABLE tab2,tab3"
>> > So what's wrong for the subscriber to combine pub1 and pub2 in this case?
>> >
>>
>> It is because one of the publications (pub2) indicates to include a
>> particular table tab1 and the other one (pub1) to exclude the same
>> table. And things become much more complex when the Except list
>> contains partitions as shown in Shveta's example. So, I think it makes
>> sense to keep things simple at least for the first version, we can
>> consider to uplift this restriction if we see some use cases from the
>> field.
>>
>>
>
> I’m with Peter here - I do not think it is wise to expose the exception listing outside the publication. Publication combinations should be purely additive in much the same way grants are in the system. Except lists are internal shorthand for describing the positive list of tables a publication makes available - all tables except.
>

The earlier case -
pub1: FOR ALL TABLES EXCEPT (tab1)
pub2: FOR TABLE tab1 WHERE (c = 99)

seems a valid scenario, and we are currently evaluating its
implementation feasibility under Approach 1.

OTOH, subscribing to two different publications that are both defined
as 'FOR ALL TABLES' but have different EXCEPT lists introduces
unnecessary implementation complexity without a clear business use
case. This becomes especially complex when the publications exclude
different partitions of the same partitioned table. For example:

pub1: FOR ALL TABLES EXCEPT (part1, part2) WITH
(publish_via_partition_root=true)
pub2: FOR ALL TABLES EXCEPT (part7) WITH
(publish_via_partition_root=false)

IMO, there is no clear need for a user to create multiple 'ALL TABLES'
publications with different EXCEPT lists and then combine them at the
subscriber level. Given this, to keep the patch simpler, we plan to
emit an error for this scenario (multi-pub EXCEPTs case) for now. If a
valid requirement emerges in the future, we can revisit and consider
supporting it.

thanks
Shveta


From: vignesh C <vignesh21(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-10 17:41:03
Message-ID: CALDaNm2EU7qdEnGmirzVn9a1O-6y3q5c7nzsBZCuyVjaPS37mg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, 10 Feb 2026 at 11:35, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Mon, Feb 9, 2026 at 11:52 AM David G. Johnston
> <david(dot)g(dot)johnston(at)gmail(dot)com> wrote:
> >
> > On Sunday, February 8, 2026, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >>
> >> On Mon, Feb 9, 2026 at 6:41 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >>
> >> > Hi Amit.
> >> >
> >> > I understand there can be some tricky scenarios where partitions are
> >> > involved, but I was not sure why "pub1: FOR ALL Tables EXCEPT (tab1)
> >> > and pub2: FOR TABLE tab1" is an example of contradictory behaviour.
> >> >
> >> > Consider if the publisher has 3 tables tab1,tab2,tab3:
> >> > Here, "pub1: FOR ALL Tables EXCEPT (tab1)" is like a shorthand for
> >> > saying "pub1: FOR TABLE tab2,tab3"
> >> > So what's wrong for the subscriber to combine pub1 and pub2 in this case?
> >> >
> >>
> >> It is because one of the publications (pub2) indicates to include a
> >> particular table tab1 and the other one (pub1) to exclude the same
> >> table. And things become much more complex when the Except list
> >> contains partitions as shown in Shveta's example. So, I think it makes
> >> sense to keep things simple at least for the first version, we can
> >> consider to uplift this restriction if we see some use cases from the
> >> field.
> >>
> >>
> >
> > I’m with Peter here - I do not think it is wise to expose the exception listing outside the publication. Publication combinations should be purely additive in much the same way grants are in the system. Except lists are internal shorthand for describing the positive list of tables a publication makes available - all tables except.
> >
>
> The earlier case -
> pub1: FOR ALL TABLES EXCEPT (tab1)
> pub2: FOR TABLE tab1 WHERE (c = 99)
>
> seems a valid scenario, and we are currently evaluating its
> implementation feasibility under Approach 1.
>
> OTOH, subscribing to two different publications that are both defined
> as 'FOR ALL TABLES' but have different EXCEPT lists introduces
> unnecessary implementation complexity without a clear business use
> case. This becomes especially complex when the publications exclude
> different partitions of the same partitioned table. For example:
>
> pub1: FOR ALL TABLES EXCEPT (part1, part2) WITH
> (publish_via_partition_root=true)
> pub2: FOR ALL TABLES EXCEPT (part7) WITH
> (publish_via_partition_root=false)
>
> IMO, there is no clear need for a user to create multiple 'ALL TABLES'
> publications with different EXCEPT lists and then combine them at the
> subscriber level. Given this, to keep the patch simpler, we plan to
> emit an error for this scenario (multi-pub EXCEPTs case) for now. If a
> valid requirement emerges in the future, we can revisit and consider
> supporting it.

I agree with this. This has been handled.
Additionally it also resolves conflicts between overlapping
publications with differing publish_via_partition_root settings. When
a partition is excluded from a "via root" publication but included in
another table publication with "via root" as false, then it is
published through its root ancestor by default to give priority to the
root table.
Ex:
-- Publisher tables
CREATE TABLE tab_root (id int, range_col int) PARTITION BY RANGE (range_col);
CREATE TABLE tab_part_1 PARTITION OF tab_root FOR VALUES FROM (1) TO
(1000) PARTITION BY RANGE (range_col);
CREATE TABLE tab_part_2 PARTITION OF tab_root FOR VALUES FROM (1000)
TO (2000) PARTITION BY RANGE (range_col);
CREATE TABLE tab_part_1_p1 PARTITION OF tab_part_1 FOR VALUES FROM (1) TO (500);
CREATE TABLE tab_part_1_p2 PARTITION OF tab_part_1 FOR VALUES FROM
(500) TO (1000);
CREATE TABLE tab_part_2_p1 PARTITION OF tab_part_2 FOR VALUES FROM
(1000) TO (1500);
CREATE TABLE tab_part_2_p2 PARTITION OF tab_part_2 FOR VALUES FROM
(1500) TO (2000);

-- Publication
CREATE PUBLICATION pub1 for ALL TABLES EXCEPT table (tab_part_1_p1,
tab_part_1_p2) WITH (PUBLISH_VIA_PARTITION_ROOT=true);
CREATE PUBLICATION pub2 for table tab_part_1_p2 WITH
(PUBLISH_VIA_PARTITION_ROOT=false);

-- Subscriber tables
CREATE TABLE tab_root (id int, range_col int);
CREATE TABLE tab_part_1 (id int, range_col int);
CREATE TABLE tab_part_2 (id int, range_col int);
CREATE TABLE tab_part_1_p1 (id int, range_col int);
CREATE TABLE tab_part_1_p2 (id int, range_col int);
CREATE TABLE tab_part_2_p1 (id int, range_col int);
CREATE TABLE tab_part_2_p2 (id int, range_col int);

Subscription with both pub1 and pub2 publications.:
create subscription sub1 connection 'dbname=postgres host=localhost
port=5432' publication pub1,pub2;

Consider the insert statements:
insert into tab_part_1_p1 values(1,100);
insert into tab_part_1_p2 values(2,600);
insert into tab_part_2_p1 values(3,1100);
insert into tab_part_2_p2 values(4,1600);

The tab_part_2_p2 table's row is replicated to the subscriber’s
tab_root table, since root table publications take precedence.
postgres=# select * from tab_root ;
id | range_col
----+-----------
2 | 600
3 | 1100
4 | 1600
(3 rows)

The attached v42 version patch has the changes for the same.

Regards,
Vignesh

Attachment Content-Type Size
v42-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 102.0 KB
v42-0002-Extended-tests-for-EXCEPT-TABLE-patch.patch application/octet-stream 4.9 KB

From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-11 05:17:43
Message-ID: CAJpy0uD5nVQ9vasP+UP=1ySdG_M64iBXVuzu1CT7b7b-KdbdPA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Feb 10, 2026 at 11:11 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Tue, 10 Feb 2026 at 11:35, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > On Mon, Feb 9, 2026 at 11:52 AM David G. Johnston
> > <david(dot)g(dot)johnston(at)gmail(dot)com> wrote:
> > >
> > > On Sunday, February 8, 2026, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> > >>
> > >> On Mon, Feb 9, 2026 at 6:41 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> > >>
> > >> > Hi Amit.
> > >> >
> > >> > I understand there can be some tricky scenarios where partitions are
> > >> > involved, but I was not sure why "pub1: FOR ALL Tables EXCEPT (tab1)
> > >> > and pub2: FOR TABLE tab1" is an example of contradictory behaviour.
> > >> >
> > >> > Consider if the publisher has 3 tables tab1,tab2,tab3:
> > >> > Here, "pub1: FOR ALL Tables EXCEPT (tab1)" is like a shorthand for
> > >> > saying "pub1: FOR TABLE tab2,tab3"
> > >> > So what's wrong for the subscriber to combine pub1 and pub2 in this case?
> > >> >
> > >>
> > >> It is because one of the publications (pub2) indicates to include a
> > >> particular table tab1 and the other one (pub1) to exclude the same
> > >> table. And things become much more complex when the Except list
> > >> contains partitions as shown in Shveta's example. So, I think it makes
> > >> sense to keep things simple at least for the first version, we can
> > >> consider to uplift this restriction if we see some use cases from the
> > >> field.
> > >>
> > >>
> > >
> > > I’m with Peter here - I do not think it is wise to expose the exception listing outside the publication. Publication combinations should be purely additive in much the same way grants are in the system. Except lists are internal shorthand for describing the positive list of tables a publication makes available - all tables except.
> > >
> >
> > The earlier case -
> > pub1: FOR ALL TABLES EXCEPT (tab1)
> > pub2: FOR TABLE tab1 WHERE (c = 99)
> >
> > seems a valid scenario, and we are currently evaluating its
> > implementation feasibility under Approach 1.
> >
> > OTOH, subscribing to two different publications that are both defined
> > as 'FOR ALL TABLES' but have different EXCEPT lists introduces
> > unnecessary implementation complexity without a clear business use
> > case. This becomes especially complex when the publications exclude
> > different partitions of the same partitioned table. For example:
> >
> > pub1: FOR ALL TABLES EXCEPT (part1, part2) WITH
> > (publish_via_partition_root=true)
> > pub2: FOR ALL TABLES EXCEPT (part7) WITH
> > (publish_via_partition_root=false)
> >
> > IMO, there is no clear need for a user to create multiple 'ALL TABLES'
> > publications with different EXCEPT lists and then combine them at the
> > subscriber level. Given this, to keep the patch simpler, we plan to
> > emit an error for this scenario (multi-pub EXCEPTs case) for now. If a
> > valid requirement emerges in the future, we can revisit and consider
> > supporting it.
>
> I agree with this. This has been handled.
> Additionally it also resolves conflicts between overlapping
> publications with differing publish_via_partition_root settings. When
> a partition is excluded from a "via root" publication but included in
> another table publication with "via root" as false, then it is
> published through its root ancestor by default to give priority to the
> root table.

Okay, this behaviour is the same as that of HEAD. I think the patch
has not changed anything in that.

So will it be right to conclude this:

In the case where a subscriber subscribes to multiple publications:

a) If a table or partition is included in one publication and excluded
in another, we treat it as included.

b) If any publisher has publish_via_partition_root = true, we consider
this setting to apply to all publishers in that subscription. In other
words, all changes are published through the topmost ancestor included
in the publications. This behavior is the same as in HEAD; nothing has
changed here.

c) If the publications have different EXCEPT lists, this scenario is
currently not supported (for the reasons stated in [1]). In such
cases, we raise an error.

[1]: https://www.postgresql.org/message-id/CAJpy0uC_0uvhmXyWegKGRozhpyoLGHwHrUAK%3DWk%2BbSmzqLMoSw%40mail.gmail.com

> Ex:
> -- Publisher tables
> CREATE TABLE tab_root (id int, range_col int) PARTITION BY RANGE (range_col);
> CREATE TABLE tab_part_1 PARTITION OF tab_root FOR VALUES FROM (1) TO
> (1000) PARTITION BY RANGE (range_col);
> CREATE TABLE tab_part_2 PARTITION OF tab_root FOR VALUES FROM (1000)
> TO (2000) PARTITION BY RANGE (range_col);
> CREATE TABLE tab_part_1_p1 PARTITION OF tab_part_1 FOR VALUES FROM (1) TO (500);
> CREATE TABLE tab_part_1_p2 PARTITION OF tab_part_1 FOR VALUES FROM
> (500) TO (1000);
> CREATE TABLE tab_part_2_p1 PARTITION OF tab_part_2 FOR VALUES FROM
> (1000) TO (1500);
> CREATE TABLE tab_part_2_p2 PARTITION OF tab_part_2 FOR VALUES FROM
> (1500) TO (2000);
>
> -- Publication
> CREATE PUBLICATION pub1 for ALL TABLES EXCEPT table (tab_part_1_p1,
> tab_part_1_p2) WITH (PUBLISH_VIA_PARTITION_ROOT=true);
> CREATE PUBLICATION pub2 for table tab_part_1_p2 WITH
> (PUBLISH_VIA_PARTITION_ROOT=false);
>
> -- Subscriber tables
> CREATE TABLE tab_root (id int, range_col int);
> CREATE TABLE tab_part_1 (id int, range_col int);
> CREATE TABLE tab_part_2 (id int, range_col int);
> CREATE TABLE tab_part_1_p1 (id int, range_col int);
> CREATE TABLE tab_part_1_p2 (id int, range_col int);
> CREATE TABLE tab_part_2_p1 (id int, range_col int);
> CREATE TABLE tab_part_2_p2 (id int, range_col int);
>
> Subscription with both pub1 and pub2 publications.:
> create subscription sub1 connection 'dbname=postgres host=localhost
> port=5432' publication pub1,pub2;
>
> Consider the insert statements:
> insert into tab_part_1_p1 values(1,100);
> insert into tab_part_1_p2 values(2,600);
> insert into tab_part_2_p1 values(3,1100);
> insert into tab_part_2_p2 values(4,1600);
>
> The tab_part_2_p2 table's row is replicated to the subscriber’s
> tab_root table, since root table publications take precedence.

I think your intent was to focus on results for tab_part_1_p2 as that
was included in pub2 but excluded in pub1.

> postgres=# select * from tab_root ;
> id | range_col
> ----+-----------
> 2 | 600
> 3 | 1100
> 4 | 1600
> (3 rows)
>
> The attached v42 version patch has the changes for the same.
>

Thanks, will review.

thanks
Shveta


From: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-11 06:02:50
Message-ID: CAKFQuwaEizi5bUD1kM-gn_0Lp-q=O3Axn267jekyehSJtkc=FA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tuesday, February 10, 2026, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:

> >
> > The attached v42 version patch has the changes for the same.
> >
>
> Thanks, will review.
>

Publication names are unique within the database. In
check_publications_except_list, the use of “select distinct” when pulling
from pg_publication by name is unnecessary. Furthermore, if we only have a
single publication name it is unnecessary to perform the check and thus no
need to even run the query.

David J.

+check_publications_except_list(WalReceiverConn *wrconn, List *publications)
+{
+ WalRcvExecResult *res;
+ StringInfoData cmd;
+ TupleTableSlot *slot;
+ Oid tableRow[1] = {TEXTOID};
+ List *except_publications = NIL;
+
+ initStringInfo(&cmd);
+ appendStringInfoString(&cmd,
+ "SELECT DISTINCT p.pubname\n"
+ " FROM pg_catalog.pg_publication p\n"
+ " WHERE p.pubname IN (");
+
+ GetPublicationsStr(publications, &cmd, true);
+
+ appendStringInfoString(&cmd,
+ ")\n"
+ " AND EXISTS (SELECT 1\n"
+ " FROM pg_catalog.pg_publication_rel pr\n"
+ " WHERE pr.prpubid = p.oid\n"
+ " AND pr.prexcept IS TRUE)");


From: vignesh C <vignesh21(at)gmail(dot)com>
To: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-11 06:28:12
Message-ID: CALDaNm2OgXwcd+BBYKSdqudw8Nn3catvvezuDEba4tbJZs0xZg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 11 Feb 2026 at 11:32, David G. Johnston
<david(dot)g(dot)johnston(at)gmail(dot)com> wrote:
>
> On Tuesday, February 10, 2026, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>>
>> >
>> > The attached v42 version patch has the changes for the same.
>> >
>>
>> Thanks, will review.
>
>
> Publication names are unique within the database. In check_publications_except_list, the use of “select distinct” when pulling from pg_publication by name is unnecessary. Furthermore, if we only have a single publication name it is unnecessary to perform the check and thus no need to even run the query.

Thanks, we will handle this in the next version.

Regards,
Vignesh


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-12 06:58:28
Message-ID: CANhcyEVB6XkVQ4YYN3x+P5NeG=tOWg-OWebGiqMp02XXMVUa6A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 11 Feb 2026 at 11:32, David G. Johnston
<david(dot)g(dot)johnston(at)gmail(dot)com> wrote:
>
> On Tuesday, February 10, 2026, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>>
>> >
>> > The attached v42 version patch has the changes for the same.
>> >
>>
>> Thanks, will review.
>
>
> Publication names are unique within the database. In check_publications_except_list, the use of “select distinct” when pulling from pg_publication by name is unnecessary. Furthermore, if we only have a single publication name it is unnecessary to perform the check and thus no need to even run the query.
>
> David J.
>
>
> +check_publications_except_list(WalReceiverConn *wrconn, List *publications)
> +{
> + WalRcvExecResult *res;
> + StringInfoData cmd;
> + TupleTableSlot *slot;
> + Oid tableRow[1] = {TEXTOID};
> + List *except_publications = NIL;
> +
> + initStringInfo(&cmd);
> + appendStringInfoString(&cmd,
> + "SELECT DISTINCT p.pubname\n"
> + " FROM pg_catalog.pg_publication p\n"
> + " WHERE p.pubname IN (");
> +
> + GetPublicationsStr(publications, &cmd, true);
> +
> + appendStringInfoString(&cmd,
> + ")\n"
> + " AND EXISTS (SELECT 1\n"
> + " FROM pg_catalog.pg_publication_rel pr\n"
> + " WHERE pr.prpubid = p.oid\n"
> + " AND pr.prexcept IS TRUE)");

Hi David,

We have addressed the comments in the latest v43 patch.
Also we have refactored the code in
'pg_get_publication_effective_tables' and added comments to make it
simpler to understand.

Thanks,
Shlok Kyal

Attachment Content-Type Size
v43-0002-Extended-tests-for-EXCEPT-TABLE-patch.patch application/octet-stream 4.9 KB
v43-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 101.8 KB

From: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-12 08:28:16
Message-ID: CAKFQuwbx5QErvadzs5Nmj7A0LUyS63pnHxrop5FAmd58wcfn+w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Feb 11, 2026 at 11:58 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
wrote:

>
> We have addressed the comments in the latest v43 patch.
>

Non-comprehensive review.

Shouldn't the early exits look like:

<begin function>
if (list_length(publications) < 2)
return;

perform query here, capture except_publications

if (list_length(except_publications) < 2)
return;

construct error message and ereport
<end function>

+ if (publication_has_any_exception(puboid))
+ {
+ except_pub_names = lappend(except_pub_names,
+ makeString(pubform->pubname.data));
+ has_any_exclusion = true;
+ except_pub_id = pubform->oid;
+ }

Either rename has_any_exclusion to has_any_exception or, given how
ambiguous that reads in code, maybe standardize on calling these exclusions
throughout the code and either just accept we've chosen EXCEPT for the
syntax for good reasons or consider whether to EXCLUDING (table1, table2)
would be a better choice.

+ errmsg("could not get non excluded table list for table \"%s.%s\" from
publisher: %s", -- triple negative; try to avoid "non excluded" as a term -
those are "included".

pg_get_publication_effective_tables - the second input argument is an array
of publication names so the singular form here is a bit misleading. Should
this be subscription-oriented? Otherwise, pg_get_tables_from_publications
seems like a more accurate name. "effective" or "only the included ones"
seems reasonable to imply.

Related, the check in there for "does at least one publication have
an exclusion list" makes sense but feels awfully similar to the check for
"at most one publication has an exclusion list"...too late for me to figure
out what if anything to do make/do about it though.

David J.


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-13 11:41:08
Message-ID: CAJpy0uBF+=CCpyuH_mP+JZerF5cnBtHzPCvyQn5+9TneEBrY=w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Feb 12, 2026 at 1:58 PM David G. Johnston
<david(dot)g(dot)johnston(at)gmail(dot)com> wrote:
>
> On Wed, Feb 11, 2026 at 11:58 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>>
>>
>> We have addressed the comments in the latest v43 patch.
>
>
> Non-comprehensive review.

Thanks, we will review and address these.

> Shouldn't the early exits look like:
>
> <begin function>
> if (list_length(publications) < 2)
> return;
>
> perform query here, capture except_publications
>
> if (list_length(except_publications) < 2)
> return;
>
> construct error message and ereport
> <end function>
>
>
> + if (publication_has_any_exception(puboid))
> + {
> + except_pub_names = lappend(except_pub_names,
> + makeString(pubform->pubname.data));
> + has_any_exclusion = true;
> + except_pub_id = pubform->oid;
> + }
>
> Either rename has_any_exclusion to has_any_exception or, given how ambiguous that reads in code, maybe standardize on calling these exclusions throughout the code and either just accept we've chosen EXCEPT for the syntax for good reasons or consider whether to EXCLUDING (table1, table2) would be a better choice.

We have chosen 'EXCEPT' based on [1]. There were agreements on this,
see [2]. We will modify function names and comments to be in sync with
the 'EXCEPT' keyword.

[1]: https://www.postgresql.org/message-id/CAJpy0uCM40%2Bcu8va2HBqE-pazPjhNdTDAQqK3nWbs4%2B5fs4Mxw%40mail.gmail.com
[2]: https://www.postgresql.org/message-id/CAFiTN-vMpoX%3DTnxZq2_CmAH_k_DnJLp1Tu7-YT%2BuWvNGoPzfxg%40mail.gmail.com

thanks
Shveta


From: vignesh C <vignesh21(at)gmail(dot)com>
To: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-16 03:20:36
Message-ID: CALDaNm0MpQPoU+C-Jt6BDOfFSFoU=DsFaV-Ohs2nkGnGfLiCcQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 12 Feb 2026 at 13:58, David G. Johnston
<david(dot)g(dot)johnston(at)gmail(dot)com> wrote:
>
> On Wed, Feb 11, 2026 at 11:58 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>>
>>
>> We have addressed the comments in the latest v43 patch.
>
>
> Non-comprehensive review.
>
> Shouldn't the early exits look like:
>
> <begin function>
> if (list_length(publications) < 2)
> return;
>
> perform query here, capture except_publications
>
> if (list_length(except_publications) < 2)
> return;
>
> construct error message and ereport
> <end function>

Modified

>
> + if (publication_has_any_exception(puboid))
> + {
> + except_pub_names = lappend(except_pub_names,
> + makeString(pubform->pubname.data));
> + has_any_exclusion = true;
> + except_pub_id = pubform->oid;
> + }
>
> Either rename has_any_exclusion to has_any_exception or, given how ambiguous that reads in code, maybe standardize on calling these exclusions throughout the code and either just accept we've chosen EXCEPT for the syntax for good reasons or consider whether to EXCLUDING (table1, table2) would be a better choice.

Changed it to has_any_exception

> + errmsg("could not get non excluded table list for table \"%s.%s\" from publisher: %s", -- triple negative; try to avoid "non excluded" as a term - those are "included".
>
> pg_get_publication_effective_tables - the second input argument is an array of publication names so the singular form here is a bit misleading. Should this be subscription-oriented? Otherwise, pg_get_tables_from_publications seems like a more accurate name. "effective" or "only the included ones" seems reasonable to imply.

We have used similarly in the existing pg_get_publication_tables, I
felt the existing might be ok to keep it consistent unless there is a
better consistent name.

> Related, the check in there for "does at least one publication have an exclusion list" makes sense but feels awfully similar to the check for "at most one publication has an exclusion list"...too late for me to figure out what if anything to do make/do about it though.

Ideally this is not expected to happen. But under rare cases it can
happen if the publication is dropped/recreated with except after
creating a subscription. It is better to throw an error in these cases
as we do not allow multiple publications except tables.

Thanks for the comments, the attached v44 version patch has the
changes for the same.

Regards,
Vignesh

Attachment Content-Type Size
v44-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 107.0 KB
v44-0002-Extended-tests-for-EXCEPT-TABLE-patch.patch application/octet-stream 4.9 KB

From: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-16 04:36:58
Message-ID: CAFiTN-sYKNNW=8Z_qdqzyr9sA+-G-PpTSs5R1mVbPT6aKyEAqw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Feb 16, 2026 at 8:50 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Thu, 12 Feb 2026 at 13:58, David G. Johnston
> <david(dot)g(dot)johnston(at)gmail(dot)com> wrote:
> >
> > On Wed, Feb 11, 2026 at 11:58 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >>
> >>
> >> We have addressed the comments in the latest v43 patch.
> >
> >
> > Non-comprehensive review.
> >
> > Shouldn't the early exits look like:
> >
> > <begin function>
> > if (list_length(publications) < 2)
> > return;
> >
> > perform query here, capture except_publications
> >
> > if (list_length(except_publications) < 2)
> > return;
> >
> > construct error message and ereport
> > <end function>
>
> Modified
>
> >
> > + if (publication_has_any_exception(puboid))
> > + {
> > + except_pub_names = lappend(except_pub_names,
> > + makeString(pubform->pubname.data));
> > + has_any_exclusion = true;
> > + except_pub_id = pubform->oid;
> > + }
> >
> > Either rename has_any_exclusion to has_any_exception or, given how ambiguous that reads in code, maybe standardize on calling these exclusions throughout the code and either just accept we've chosen EXCEPT for the syntax for good reasons or consider whether to EXCLUDING (table1, table2) would be a better choice.
>
> Changed it to has_any_exception
>
> > + errmsg("could not get non excluded table list for table \"%s.%s\" from publisher: %s", -- triple negative; try to avoid "non excluded" as a term - those are "included".
> >
> > pg_get_publication_effective_tables - the second input argument is an array of publication names so the singular form here is a bit misleading. Should this be subscription-oriented? Otherwise, pg_get_tables_from_publications seems like a more accurate name. "effective" or "only the included ones" seems reasonable to imply.
>
> We have used similarly in the existing pg_get_publication_tables, I
> felt the existing might be ok to keep it consistent unless there is a
> better consistent name.
>
> > Related, the check in there for "does at least one publication have an exclusion list" makes sense but feels awfully similar to the check for "at most one publication has an exclusion list"...too late for me to figure out what if anything to do make/do about it though.
>
> Ideally this is not expected to happen. But under rare cases it can
> happen if the publication is dropped/recreated with except after
> creating a subscription. It is better to throw an error in these cases
> as we do not allow multiple publications except tables.
>
> Thanks for the comments, the attached v44 version patch has the
> changes for the same.

I started looking into the patch, I have a few comments/questions

1.
+ <para>
+ Similarly, if another publication includes the same table with a row
+ filter, but it is also covered by a
+ <literal>FOR ALL TABLES ... EXCEPT</literal> publication, the table is
+ published without applying the row filter, since row filters cannot be
+ specified for <literal>FOR ALL TABLES ... EXCEPT</literal> publications
+ and such publications are therefore treated as having no row filter.
+ </para>

I did not understand what this paragraph is trying to explain? what
do you mean by it is covered by FOR ALL TABLES ... EXCEPT, does it
mean the relation is not excluded by EXCEPT?

2.
+ <para>
+ Create a publication that publishes all sequences for synchronization, and
+ all changes in all tables except <structname>users</structname> and
+ <structname>departments</structname>:
+<programlisting>
+CREATE PUBLICATION all_sequences_tables_except FOR ALL SEQUENCES, ALL
TABLES EXCEPT (users, departments);

Do we support EXCEPT SEQUENCES as well or that's for the future?

3.
+/* Helper: Check syscache for prexcept flag */
+bool
+is_relid_published_as_except(Oid relid, Oid pubid)
+{

IMHO the function name doesn't look great for its purpose, we just
want to check whether the relid is excluded, published_as_except seems
confusing, no?

4.
+/*
+ * Throws an ERROR if multiple publications with exceptions are found.
+ *
+ * This check is mandatory because logical replication currently does not
+ * support subscribing to multiple publications if more than one of them
+ * uses an exclusion list.
+ */

IMHO explaining the reason why this is not supported or giving
reference to any other comments where it is already explained would be
useful.

5.
+ /*
+ * If the root ancestor is covered by a FOR ALL TABLES
+ * EXCEPT publication that uses
+ * publish_via_partition_root, we must publish changes via
+ * the root identity.
+ */
+ if (root_published_via_exceptpub)
+ {
+ pub_relid = root_ancestor;
+ ancestor_level = list_length(ancestors);
+ }

I find this comment a bit confusing, what does "covered by a FOR ALL
TABLES EXCEPT publication" means? It means relation is not in the
EXCEPT list or in the EXCEPT list?

--
Regards,
Dilip Kumar
Google


From: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>
To: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-16 06:24:27
Message-ID: CAKFQuwYJKiDV6QgLLD+FHZ2zCi7DWLo_xoqYutJQbtPX+DJxdQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sunday, February 15, 2026, Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:

> On Mon, Feb 16, 2026 at 8:50 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> I started looking into the patch, I have a few comments/questions
>
> 1.
> + <para>
> + Similarly, if another publication includes the same table with a row
> + filter, but it is also covered by a
> + <literal>FOR ALL TABLES ... EXCEPT</literal> publication, the table
> is
> + published without applying the row filter, since row filters cannot
> be
> + specified for <literal>FOR ALL TABLES ... EXCEPT</literal>
> publications
> + and such publications are therefore treated as having no row filter.
> + </para>
>
> I did not understand what this paragraph is trying to explain? what
> do you mean by it is covered by FOR ALL TABLES ... EXCEPT, does it
> mean the relation is not excluded by EXCEPT?

I concur the wording is tough to parse. “Covered” is probably not a good
word to use. Stick with either included or excluded. In this case, the
point being communicated is if two publications include a table and one
doesn’t have a where clause a combining subscription will consider the
where clause to be a constant true when combining the where clauses using
OR.

This wording basically already exists in create subscription. This
paragraph and the preceding one, which discuss “if another publication
exists”, seems out of place in the create publication documentation. This
page should be restricted to only those behaviors that manifest when
dealing with a single publication, detailing what it produces.

>
> 4.
> +/*
> + * Throws an ERROR if multiple publications with exceptions are found.
> + *
> + * This check is mandatory because logical replication currently does not
> + * support subscribing to multiple publications if more than one of them
> + * uses an exclusion list.
> + */
>
> IMHO explaining the reason why this is not supported or giving
> reference to any other comments where it is already explained would be
> useful.

The word “exceptions” needs to be turned into “except clauses” or
“exclusions”.

>
> 5.
> + /*
> + * If the root ancestor is covered by a FOR ALL TABLES
> + * EXCEPT publication that uses
> + * publish_via_partition_root, we must publish changes via
> + * the root identity.
> + */
> + if (root_published_via_exceptpub)
> + {
> + pub_relid = root_ancestor;
> + ancestor_level = list_length(ancestors);
> + }
>
> I find this comment a bit confusing, what does "covered by a FOR ALL
> TABLES EXCEPT publication" means?

root_published_via_exceptpub … shouldn’t this just be
“root_published_via_alltables? It’s the all table clause that prohibits "
where" and accepts "except". IOW, it's sufficient to drop mention of
except because the nature of the boolean means that 'false == except'.

Something Like:
When dealing with multiple publications in a subscription, a
publish_via_partition_root attribute on an ALL TABLES publication causes
the system to direct the data for all subscribed partitions to the
partition root, even if other publications do not specify
publish_via_partition_root (so long as the partition root in question
hasn't been excluded from the ALL TABLES publication).

Note: all tables + publish_via_partition_root = false comes to mind here
but I'm unable to dive into the sidebar at the moment. It seems like
root_published_via_alltables being false covers that case sufficiently
though since in effect the root isn't published in that scenario.

+ * If the relation is a partition, check whether the current
+ * relation or any of the ancestors is included in the EXCEPT
+ * TABLE list. If so, do not publish the change. This is done
+ * irrespective of pubviaroot setting.

I don't understand the motivation for pointing out pubviaroot here. Of
course a table that is not published doesn't care what 'pub'viaroot says.

+ * If the top-most ancestor is covered by a 'FOR ALL TABLES
+ * EXCEPT' publication, we don't need to track per-relation
+ * metadata here. These publications apply globally and do not
+ * support row filters or column lists that would require
+ * specific tracking for this partition.

Suggestion:
/* Partitions whose top-most ancestor is being published via an ALL TABLES
publication need not be individually published via any other publication.
Repeated occurrences of a partition take the least restricted definition,
which the ALL TABLES publication always provides. I.e., all columns, all
rows, no children left behind. */
if (root_published_via_alltables)
continue;

The last two sentences are inferrable (from the definition/description of
the rules of publication combining) and probably should be excluded.

If the root is either "except'ed or there is no "publish via partition
root" this is false and the subsequent lappend happens per usual. That
seems correct.

+ * explicitly specified in the EXCEPT claus of the given publication.
s.b., "clause"

David J.


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>
Cc: Dilip Kumar <dilipbalaut(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-16 07:14:53
Message-ID: CAJpy0uBDgwki1k5zPhTX5b6shG0TuHdnsceCG75+WVMN_CtsKA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Feb 16, 2026 at 11:55 AM David G. Johnston
<david(dot)g(dot)johnston(at)gmail(dot)com> wrote:
>
> On Sunday, February 15, 2026, Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:
>>
>> On Mon, Feb 16, 2026 at 8:50 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>> >
>> I started looking into the patch, I have a few comments/questions
>>
>> 1.
>> + <para>
>> + Similarly, if another publication includes the same table with a row
>> + filter, but it is also covered by a
>> + <literal>FOR ALL TABLES ... EXCEPT</literal> publication, the table is
>> + published without applying the row filter, since row filters cannot be
>> + specified for <literal>FOR ALL TABLES ... EXCEPT</literal> publications
>> + and such publications are therefore treated as having no row filter.
>> + </para>
>>
>> I did not understand what this paragraph is trying to explain? what
>> do you mean by it is covered by FOR ALL TABLES ... EXCEPT, does it
>> mean the relation is not excluded by EXCEPT?
>
>
> I concur the wording is tough to parse. “Covered” is probably not a good word to use. Stick with either included or excluded. In this case, the point being communicated is if two publications include a table and one doesn’t have a where clause a combining subscription will consider the where clause to be a constant true when combining the where clauses using OR.
>
> This wording basically already exists in create subscription.

--yes, it exists already in doc ([1]) in the row-filter page.

> This paragraph and the preceding one, which discuss “if another publication exists”, seems out of place in the create publication documentation. This page should be restricted to only those behaviors that manifest when dealing with a single publication, detailing what it produces.

If we want to mention it in brief, I still feel CREATE-PUBLICATION
page is a good place. SImilar to how we mention in
'publish_via_partition_root' section. See 'There can be a case where a
subscription combines multiple publications.' in [2].

Overall, I think this complete paragraph could be removed from
CREATE-PUBLICATION. I find it over-detailed.

+ <para>
+ When a partition is listed in the <literal>EXCEPT</literal> clause of a
+ <literal>FOR ALL TABLES</literal> publication with
+ <literal>publish_via_partition_root</literal> set to
+ <literal>true</literal>, the root partitioned table remains included in
+ the publication. If that partition is explicitly included by another
+ publication with <literal>publish_via_partition_root</literal> set to
+ <literal>false</literal>, its changes are still replicated. In this
+ case, the changes are published using the identity of the root
+ partitioned table, since it is the top-most ancestor included in the
+ <literal>FOR ALL TABLES</literal> publication, thereby ensuring
+ consistent routing of changes within the partition hierarchy.
+ </para>
+ <para>
+ Similarly, if another publication includes the same table with a row
+ filter, but it is also covered by a
+ <literal>FOR ALL TABLES ... EXCEPT</literal> publication, the table is
+ published without applying the row filter, since row filters cannot be
+ specified for <literal>FOR ALL TABLES ... EXCEPT</literal> publications
+ and such publications are therefore treated as having no row filter.
+ </para>

Instead we can have something like below:

There can be a case where a subscription includes multiple
publications. In such a case, a table or partition that is included in
one publication and listed in the EXCEPT TABLE clause of another is
considered included for replication. Subscribing to multiple
publications with different EXCEPT TABLE lists is currently not
supported.

~~

I feel it is unnecessary to mention row filters or column lists
specifically in the context of the EXCEPT TABLE clause because IIUC:

--They do not apply to FOR ALL TABLES publications, which is where
EXCEPT TABLE is relevant.
--In the case of multiple publications, the behavior of row filters
and column lists remains unchanged from the HEAD behavior. The EXCEPT
clause simply excludes the specified table; rest of the behaviour
remains the same.

Thoughts?

~~

Few other comments on doc:

1)
catalogs.sgml:
prexcept:
+ True if the relation is excluded from the publication.

We shall use the term 'table' instead of 'relation' to refer clearly
that it is a table and not a sequence.

2)
logical-replication.sgml:
+ <xref linkend="logical-replication-sequences"/>. When a publication is
+ created with <literal>FOR ALL TABLES</literal>, tables can be explicitly
+ excluded from publication using the
+ <link linkend="sql-createpublication-params-for-except-table"><literal>EXCEPT
TABLE</literal></link>
+ clause.

Suggestion:
'tables can be explicitly' --> 'a table or set of tables can be explicitly'

3)
create_publication.sgml:

+ For inherited tables, if <literal>ONLY</literal> is specified before the
+ table name, only that table is excluded from the publication. If
+ <literal>ONLY</literal> is not specified, the table and all its
descendant
+ tables (if any) are excluded. Optionally, <literal>*</literal> can be
+ specified after the table name to explicitly indicate that descendant
+ tables are excluded.
+ </para>
+ <para>
+ For partitioned tables, when a table is specified in EXCEPT TABLE, then
+ changes to that table and all of its partitions (that is, the entire
+ partition subtree rooted at that table) are not replicated. This behavior
+ is the same regardless of whether
+ <literal>publish_via_partition_root</literal> is set to
+ <literal>true</literal> or <literal>false</literal>. The
+ <literal>publish_via_partition_root</literal> setting only determines
+ which relation is used as the publishing relation for replicated changes,
+ and does not affect exclusion semantics.

a)
Can we make the tone of both paragraphs the same? Suggestion:
For partitioned tables, if a table is specified in EXCEPT TABLE, that
table and all of its partitions (that is, the entire partition subtree
rooted at that table) are excluded from the publication.

b)
This behavior
+ is the same regardless of whether
+ <literal>publish_via_partition_root</literal> is set to
+ <literal>true</literal> or <literal>false</literal>. The
+ <literal>publish_via_partition_root</literal> setting only determines
+ which relation is used as the publishing relation for replicated changes,
+ and does not affect exclusion semantics.

I think there is no need to explicitly mention the
'publish_via_partition_root' thing here, unless others think
otherwise.

~~

[1]: https://www.postgresql.org/docs/current/logical-replication-row-filter.html#LOGICAL-REPLICATION-ROW-FILTER-COMBINING
[2]: https://www.postgresql.org/docs/current/sql-createpublication.html#SQL-CREATEPUBLICATION-PARAMS-WITH-PUBLISH-VIA-PARTITION-ROOT

thanks
Shveta


From: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-16 12:41:16
Message-ID: CABdArM4KucFdHYPFCcpvpN7_OVnV5rpnDY7Daz7Cjn6ZuN-dkg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Feb 16, 2026 at 8:50 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> Thanks for the comments, the attached v44 version patch has the
> changes for the same.
>
I’ve started reviewing/testing the patch. Few comments:

1) File - /doc/src/sgml/catalogs.sgml
if there is no publication qualifying condition.</para></entry>
</row>

+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>prexcept</structfield> <type>bool</type>
+ </para>

Should the column order in the doc match the order in
pg_publication_rel? In the table, the "prexcept" column appears before
"prqual", whereas in the doc it is listed after.

pg_publication.c: GetAllPublicationExcludedTables()
2) There may be a scope for optimization in how relids are processed.
Each time a new parentid is appended to the relids list, the first for
loop:

+ while (is_parent_in_except)
+ {
+ List *parentids = NIL;
+ List *curr = NIL;
+
+ foreach_oid(relid, relids) <<< this
+ {
+ Oid parentid;
+
+ if (!get_rel_relispartition(relid))
+ continue;
+

reprocesses all existing relids. Could we restrict it to check only
the newly added relids and avoid redundant work? Does this make sense?

I also feel the function would benefit from a few brief comments to
clarify the logic.

The attached file has the changes for the suggested optimization and
few comment suggestions for the function, if they seem suitable.

--
Thanks,
Nisha

Attachment Content-Type Size
nisha_v44_suggestion.txt text/plain 1014 bytes

From: vignesh C <vignesh21(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-17 05:43:32
Message-ID: CALDaNm11LKbC2epEyHOvD6H_ONqLqhDQk7sXWwcneyhrTbFaTw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 16 Feb 2026 at 12:45, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Mon, Feb 16, 2026 at 11:55 AM David G. Johnston
> <david(dot)g(dot)johnston(at)gmail(dot)com> wrote:
> >
> > On Sunday, February 15, 2026, Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:
> >>
> >> On Mon, Feb 16, 2026 at 8:50 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >> >
> >> I started looking into the patch, I have a few comments/questions
> >>
> >> 1.
> >> + <para>
> >> + Similarly, if another publication includes the same table with a row
> >> + filter, but it is also covered by a
> >> + <literal>FOR ALL TABLES ... EXCEPT</literal> publication, the table is
> >> + published without applying the row filter, since row filters cannot be
> >> + specified for <literal>FOR ALL TABLES ... EXCEPT</literal> publications
> >> + and such publications are therefore treated as having no row filter.
> >> + </para>
> >>
> >> I did not understand what this paragraph is trying to explain? what
> >> do you mean by it is covered by FOR ALL TABLES ... EXCEPT, does it
> >> mean the relation is not excluded by EXCEPT?
> >
> >
> > I concur the wording is tough to parse. “Covered” is probably not a good word to use. Stick with either included or excluded. In this case, the point being communicated is if two publications include a table and one doesn’t have a where clause a combining subscription will consider the where clause to be a constant true when combining the where clauses using OR.
> >
> > This wording basically already exists in create subscription.
>
> --yes, it exists already in doc ([1]) in the row-filter page.
>
> > This paragraph and the preceding one, which discuss “if another publication exists”, seems out of place in the create publication documentation. This page should be restricted to only those behaviors that manifest when dealing with a single publication, detailing what it produces.
>
> If we want to mention it in brief, I still feel CREATE-PUBLICATION
> page is a good place. SImilar to how we mention in
> 'publish_via_partition_root' section. See 'There can be a case where a
> subscription combines multiple publications.' in [2].
>
> Overall, I think this complete paragraph could be removed from
> CREATE-PUBLICATION. I find it over-detailed.
>
> + <para>
> + When a partition is listed in the <literal>EXCEPT</literal> clause of a
> + <literal>FOR ALL TABLES</literal> publication with
> + <literal>publish_via_partition_root</literal> set to
> + <literal>true</literal>, the root partitioned table remains included in
> + the publication. If that partition is explicitly included by another
> + publication with <literal>publish_via_partition_root</literal> set to
> + <literal>false</literal>, its changes are still replicated. In this
> + case, the changes are published using the identity of the root
> + partitioned table, since it is the top-most ancestor included in the
> + <literal>FOR ALL TABLES</literal> publication, thereby ensuring
> + consistent routing of changes within the partition hierarchy.
> + </para>
> + <para>
> + Similarly, if another publication includes the same table with a row
> + filter, but it is also covered by a
> + <literal>FOR ALL TABLES ... EXCEPT</literal> publication, the table is
> + published without applying the row filter, since row filters cannot be
> + specified for <literal>FOR ALL TABLES ... EXCEPT</literal> publications
> + and such publications are therefore treated as having no row filter.
> + </para>
>
> Instead we can have something like below:
>
> There can be a case where a subscription includes multiple
> publications. In such a case, a table or partition that is included in
> one publication and listed in the EXCEPT TABLE clause of another is
> considered included for replication. Subscribing to multiple
> publications with different EXCEPT TABLE lists is currently not
> supported.

Updated

> ~~
>
> I feel it is unnecessary to mention row filters or column lists
> specifically in the context of the EXCEPT TABLE clause because IIUC:
>
> --They do not apply to FOR ALL TABLES publications, which is where
> EXCEPT TABLE is relevant.
> --In the case of multiple publications, the behavior of row filters
> and column lists remains unchanged from the HEAD behavior. The EXCEPT
> clause simply excludes the specified table; rest of the behaviour
> remains the same.
>
> Thoughts?

Agree, removed these

> ~~
>
>
> Few other comments on doc:
>
> 1)
> catalogs.sgml:
> prexcept:
> + True if the relation is excluded from the publication.
>
> We shall use the term 'table' instead of 'relation' to refer clearly
> that it is a table and not a sequence.

Modified

> 2)
> logical-replication.sgml:
> + <xref linkend="logical-replication-sequences"/>. When a publication is
> + created with <literal>FOR ALL TABLES</literal>, tables can be explicitly
> + excluded from publication using the
> + <link linkend="sql-createpublication-params-for-except-table"><literal>EXCEPT
> TABLE</literal></link>
> + clause.
>
> Suggestion:
> 'tables can be explicitly' --> 'a table or set of tables can be explicitly'

Modified

> 3)
> create_publication.sgml:
>
> + For inherited tables, if <literal>ONLY</literal> is specified before the
> + table name, only that table is excluded from the publication. If
> + <literal>ONLY</literal> is not specified, the table and all its
> descendant
> + tables (if any) are excluded. Optionally, <literal>*</literal> can be
> + specified after the table name to explicitly indicate that descendant
> + tables are excluded.
> + </para>
> + <para>
> + For partitioned tables, when a table is specified in EXCEPT TABLE, then
> + changes to that table and all of its partitions (that is, the entire
> + partition subtree rooted at that table) are not replicated. This behavior
> + is the same regardless of whether
> + <literal>publish_via_partition_root</literal> is set to
> + <literal>true</literal> or <literal>false</literal>. The
> + <literal>publish_via_partition_root</literal> setting only determines
> + which relation is used as the publishing relation for replicated changes,
> + and does not affect exclusion semantics.
>
> a)
> Can we make the tone of both paragraphs the same? Suggestion:
> For partitioned tables, if a table is specified in EXCEPT TABLE, that
> table and all of its partitions (that is, the entire partition subtree
> rooted at that table) are excluded from the publication.
>
> b)
> This behavior
> + is the same regardless of whether
> + <literal>publish_via_partition_root</literal> is set to
> + <literal>true</literal> or <literal>false</literal>. The
> + <literal>publish_via_partition_root</literal> setting only determines
> + which relation is used as the publishing relation for replicated changes,
> + and does not affect exclusion semantics.
>
> I think there is no need to explicitly mention the
> 'publish_via_partition_root' thing here, unless others think
> otherwise.

Removed

Thanks for the comments. The attached v45 version patch has the
changes for the same.

Regards,
Vignesh

Attachment Content-Type Size
v45-0002-Extended-tests-for-EXCEPT-TABLE-patch.patch application/octet-stream 4.9 KB
v45-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 105.5 KB

From: vignesh C <vignesh21(at)gmail(dot)com>
To: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>
Cc: Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-17 06:23:00
Message-ID: CALDaNm3J5V5Z4JT+1owL+bZs4W221E2H8Zkf5YCrA1dAU1BvsA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 16 Feb 2026 at 11:55, David G. Johnston
<david(dot)g(dot)johnston(at)gmail(dot)com> wrote:
>
> On Sunday, February 15, 2026, Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:
>>
>> On Mon, Feb 16, 2026 at 8:50 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>> >
>> I started looking into the patch, I have a few comments/questions
>>
>> 1.
>> + <para>
>> + Similarly, if another publication includes the same table with a row
>> + filter, but it is also covered by a
>> + <literal>FOR ALL TABLES ... EXCEPT</literal> publication, the table is
>> + published without applying the row filter, since row filters cannot be
>> + specified for <literal>FOR ALL TABLES ... EXCEPT</literal> publications
>> + and such publications are therefore treated as having no row filter.
>> + </para>
>>
>> I did not understand what this paragraph is trying to explain? what
>> do you mean by it is covered by FOR ALL TABLES ... EXCEPT, does it
>> mean the relation is not excluded by EXCEPT?
>
>
> I concur the wording is tough to parse. “Covered” is probably not a good word to use. Stick with either included or excluded. In this case, the point being communicated is if two publications include a table and one doesn’t have a where clause a combining subscription will consider the where clause to be a constant true when combining the where clauses using OR.
>
> This wording basically already exists in create subscription. This paragraph and the preceding one, which discuss “if another publication exists”, seems out of place in the create publication documentation. This page should be restricted to only those behaviors that manifest when dealing with a single publication, detailing what it produces.

I have removed these as they follow the existing row filter rules
already mentioned.

>>
>>
>> 4.
>> +/*
>> + * Throws an ERROR if multiple publications with exceptions are found.
>> + *
>> + * This check is mandatory because logical replication currently does not
>> + * support subscribing to multiple publications if more than one of them
>> + * uses an exclusion list.
>> + */
>>
>> IMHO explaining the reason why this is not supported or giving
>> reference to any other comments where it is already explained would be
>> useful.
>
>
> The word “exceptions” needs to be turned into “except clauses” or “exclusions”.

Modified

>>
>>
>> 5.
>> + /*
>> + * If the root ancestor is covered by a FOR ALL TABLES
>> + * EXCEPT publication that uses
>> + * publish_via_partition_root, we must publish changes via
>> + * the root identity.
>> + */
>> + if (root_published_via_exceptpub)
>> + {
>> + pub_relid = root_ancestor;
>> + ancestor_level = list_length(ancestors);
>> + }
>>
>> I find this comment a bit confusing, what does "covered by a FOR ALL
>> TABLES EXCEPT publication" means?
>
>
>
> root_published_via_exceptpub … shouldn’t this just be “root_published_via_alltables? It’s the all table clause that prohibits "where" and accepts "except". IOW, it's sufficient to drop mention of except because the nature of the boolean means that 'false == except'.
>
> Something Like:
> When dealing with multiple publications in a subscription, a publish_via_partition_root attribute on an ALL TABLES publication causes the system to direct the data for all subscribed partitions to the partition root, even if other publications do not specify publish_via_partition_root (so long as the partition root in question hasn't been excluded from the ALL TABLES publication).

Updated with few changes. Let me know if it did not convey the same
meaning, I will use your exact wording.

> Note: all tables + publish_via_partition_root = false comes to mind here but I'm unable to dive into the sidebar at the moment. It seems like root_published_via_alltables being false covers that case sufficiently though since in effect the root isn't published in that scenario.
>
> + * If the relation is a partition, check whether the current
> + * relation or any of the ancestors is included in the EXCEPT
> + * TABLE list. If so, do not publish the change. This is done
> + * irrespective of pubviaroot setting.
>
> I don't understand the motivation for pointing out pubviaroot here. Of course a table that is not published doesn't care what 'pub'viaroot says.

Removed this to avoid confusion.

> + * If the top-most ancestor is covered by a 'FOR ALL TABLES
> + * EXCEPT' publication, we don't need to track per-relation
> + * metadata here. These publications apply globally and do not
> + * support row filters or column lists that would require
> + * specific tracking for this partition.
>
> Suggestion:
> /* Partitions whose top-most ancestor is being published via an ALL TABLES publication need not be individually published via any other publication. Repeated occurrences of a partition take the least restricted definition, which the ALL TABLES publication always provides. I.e., all columns, all rows, no children left behind. */
> if (root_published_via_alltables)
> continue;

Modified, I have left the no children left behind as the child
specified in the except clause will be skipped if it is not included
via another publication.

> The last two sentences are inferrable (from the definition/description of the rules of publication combining) and probably should be excluded.
>
> If the root is either "except'ed or there is no "publish via partition root" this is false and the subsequent lappend happens per usual. That seems correct.

I have removed the newly added comment i.e.:
* If the relation is part of EXCEPT TABLE list of a publication,
* the 'publish' variable is already set to false.
I have retained the other one as it was an existing comment.

> + * explicitly specified in the EXCEPT claus of the given publication.
> s.b., "clause"

Fixed this.

Thanks for the comments, these are addressed in the v45 version posted at [1].
[1] - https://www.postgresql.org/message-id/CALDaNm11LKbC2epEyHOvD6H_ONqLqhDQk7sXWwcneyhrTbFaTw%40mail.gmail.com

Regards,
Vignesh


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-17 06:31:53
Message-ID: CAJpy0uC5SPBD1hh0-rAuFVvVcyTk8xWt-y=qE6b8EEkjz=k=ng@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Feb 17, 2026 at 11:13 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> Thanks for the comments. The attached v45 version patch has the
> changes for the same.
>

Thanks Vignesh, please find a few comments from v44 itself. Please
ignore if already addressed. Will switch to v45 now.

1)
publication_has_any_exception:
+ ScanKeyInit(&skey,
+ Anum_pg_publication_rel_prpubid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(pubid));
+
+ scan = systable_beginscan(pubRel,
+ PublicationRelPrrelidPrpubidIndexId,
+ true, NULL, 1, &skey);

PublicationRelPrrelidPrpubidIndexId is index on relid and pubid, I
don't think it will be used in this case where we have only pubid key.
Shall we use PublicationRelPrpubidIndexId instead?

2)
+/*
+ * is_relid_published_explicitly
+ *
+ * Checks if the given relation OID is explicitly part of the publication.
+ * This corresponds to the 'FOR TABLE' syntax.
+ */
+static bool
+is_relid_published_explicitly(Oid relid, Oid pubid)
+{
+ /*
+ * Search the syscache for pg_publication_rel using the (relid, pubid)
+ * index.
+ */
+ return SearchSysCacheExists2(PUBLICATIONRELMAP,
+ ObjectIdGetDatum(relid),
+ ObjectIdGetDatum(pubid));
+}

How are we ensuring that it is not fetching the one with except-flag
as true? Shall we assert when pub is all-tables to rule out that
case/mistake? Or if we code-flow is expected to come to this function
even for 'all-tables' pub (it appears to me t by looking at the
caller), we shall return in such a case instead of Assert.

3)
Shall we rename these:
'is_relid_published_as_except' as 'is_relid_excepted'.
'is_relid_published_as_except_with_ancestors' as 'is_relid_or_ancestor_excepted'

These will be to match tones of:
is_schema_published
is_relid_published_explicitly

I feel even for 'is_relid_published_explicitly', we can simply say
'is_relid_published'. Comments (and assert/checks) can explain that it
is for FOR-TABLE pub.

4)
+ List *except_leaves = NIL;
+ List *allowed_leaves = NIL;

Similar to allowed_leaves, shall we have excepted_leaves instead of
except_leaves?

5)
pg_get_publication_effective_tables():

+
+ /*
+ * Check whether the table itself or its schema is
+ * included in this publication.
+ */
+ if (is_relid_published_explicitly(curr_relid, pubid) ||
+ is_schema_published(get_rel_namespace(curr_relid), pubid))
+ {
+ allowed_leaves = lappend_oid(allowed_leaves, curr_relid);
+ }
+ else
+ {
+ List *ancestors = get_partition_ancestors(curr_relid);
+
+ /*
+ * Check whether any ancestor, or its schema, is
+ * included in this publication.
+ */
+ foreach_oid(anc_oid, ancestors)
+ {
+ if (is_relid_published_explicitly(anc_oid, pubid) ||
+ is_schema_published(get_rel_namespace(anc_oid), pubid))
+ allowed_leaves = lappend_oid(allowed_leaves, curr_relid);
+ }
+ }

Do you think we can convert this code part to
is_relid_or_ancestor_published(), similar to
is_relid_published_as_except_with_ancestors()?

is_relid_or_ancestor_published() can check both pg_publication_rel and
pg_publication_namespace. I do not see individual use-case scenarios
for is_relid_published_explicitly() and is_schema_published() and thus
it is better to club these in one function. So at the end we will be
left with 2 such functions:

is_relid_or_ancestor_published
is_relid_or_ancestor_excepted/excluded (choose the name based on
others comments too)

thanks
Shveta


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
Cc: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-17 06:35:47
Message-ID: CALDaNm1KRCcR5jr=3aP0M3fv1pMNAZre9mSuQw8zw58gzuF9dw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 16 Feb 2026 at 10:07, Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:
>
> I started looking into the patch, I have a few comments/questions
>
> 1.
> + <para>
> + Similarly, if another publication includes the same table with a row
> + filter, but it is also covered by a
> + <literal>FOR ALL TABLES ... EXCEPT</literal> publication, the table is
> + published without applying the row filter, since row filters cannot be
> + specified for <literal>FOR ALL TABLES ... EXCEPT</literal> publications
> + and such publications are therefore treated as having no row filter.
> + </para>
>
> I did not understand what this paragraph is trying to explain? what
> do you mean by it is covered by FOR ALL TABLES ... EXCEPT, does it
> mean the relation is not excluded by EXCEPT?

I have removed these as they follow the existing row filter rules
already mentioned.

> 2.
> + <para>
> + Create a publication that publishes all sequences for synchronization, and
> + all changes in all tables except <structname>users</structname> and
> + <structname>departments</structname>:
> +<programlisting>
> +CREATE PUBLICATION all_sequences_tables_except FOR ALL SEQUENCES, ALL
> TABLES EXCEPT (users, departments);
>
> Do we support EXCEPT SEQUENCES as well or that's for the future?

We don't support sequences, it will be handled later.

> 3.
> +/* Helper: Check syscache for prexcept flag */
> +bool
> +is_relid_published_as_except(Oid relid, Oid pubid)
> +{
>
> IMHO the function name doesn't look great for its purpose, we just
> want to check whether the relid is excluded, published_as_except seems
> confusing, no?

Modified it to is_relation_excluded

> 4.
> +/*
> + * Throws an ERROR if multiple publications with exceptions are found.
> + *
> + * This check is mandatory because logical replication currently does not
> + * support subscribing to multiple publications if more than one of them
> + * uses an exclusion list.
> + */
>
> IMHO explaining the reason why this is not supported or giving
> reference to any other comments where it is already explained would be
> useful.

Updated comments

> 5.
> + /*
> + * If the root ancestor is covered by a FOR ALL TABLES
> + * EXCEPT publication that uses
> + * publish_via_partition_root, we must publish changes via
> + * the root identity.
> + */
> + if (root_published_via_exceptpub)
> + {
> + pub_relid = root_ancestor;
> + ancestor_level = list_length(ancestors);
> + }
>
> I find this comment a bit confusing, what does "covered by a FOR ALL
> TABLES EXCEPT publication" means? It means relation is not in the
> EXCEPT list or in the EXCEPT list?

Updated comments to:
/*
* If the root ancestor is effectively published by an
* ALL TABLES publication with publish_via_partition_root,
* then changes for its partitions must be published
* using the root identity.
*
* This applies even if other publications do not specify
* publish_via_partition_root, provided the root is not
* excluded from that ALL TABLES publication.
*/

Thanks for the comments, these are addressed in the v45 version posted at [1].
Additionally the v45 version also addresses Nisha's comments from [2].

[1] - https://www.postgresql.org/message-id/CALDaNm11LKbC2epEyHOvD6H_ONqLqhDQk7sXWwcneyhrTbFaTw%40mail.gmail.com
[2] - https://www.postgresql.org/message-id/CABdArM4KucFdHYPFCcpvpN7_OVnV5rpnDY7Daz7Cjn6ZuN-dkg%40mail.gmail.com

Regards,
Vignesh


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-17 11:38:32
Message-ID: CAJpy0uAHr8=YUKSyEBs8G4P0zGGb6mcUr-YJdB56tdYMF9yoKA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Feb 17, 2026 at 12:01 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Tue, Feb 17, 2026 at 11:13 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > Thanks for the comments. The attached v45 version patch has the
> > changes for the same.
> >
>
> Thanks Vignesh, please find a few comments from v44 itself. Please
> ignore if already addressed. Will switch to v45 now.
>
>
> 1)
> publication_has_any_exception:
> + ScanKeyInit(&skey,
> + Anum_pg_publication_rel_prpubid,
> + BTEqualStrategyNumber, F_OIDEQ,
> + ObjectIdGetDatum(pubid));
> +
> + scan = systable_beginscan(pubRel,
> + PublicationRelPrrelidPrpubidIndexId,
> + true, NULL, 1, &skey);
>
> PublicationRelPrrelidPrpubidIndexId is index on relid and pubid, I
> don't think it will be used in this case where we have only pubid key.
> Shall we use PublicationRelPrpubidIndexId instead?
>
> 2)
> +/*
> + * is_relid_published_explicitly
> + *
> + * Checks if the given relation OID is explicitly part of the publication.
> + * This corresponds to the 'FOR TABLE' syntax.
> + */
> +static bool
> +is_relid_published_explicitly(Oid relid, Oid pubid)
> +{
> + /*
> + * Search the syscache for pg_publication_rel using the (relid, pubid)
> + * index.
> + */
> + return SearchSysCacheExists2(PUBLICATIONRELMAP,
> + ObjectIdGetDatum(relid),
> + ObjectIdGetDatum(pubid));
> +}
>
> How are we ensuring that it is not fetching the one with except-flag
> as true? Shall we assert when pub is all-tables to rule out that
> case/mistake? Or if we code-flow is expected to come to this function
> even for 'all-tables' pub (it appears to me t by looking at the
> caller), we shall return in such a case instead of Assert.
>
>
> 3)
> Shall we rename these:
> 'is_relid_published_as_except' as 'is_relid_excepted'.
> 'is_relid_published_as_except_with_ancestors' as 'is_relid_or_ancestor_excepted'
>
> These will be to match tones of:
> is_schema_published
> is_relid_published_explicitly
>
> I feel even for 'is_relid_published_explicitly', we can simply say
> 'is_relid_published'. Comments (and assert/checks) can explain that it
> is for FOR-TABLE pub.
>
> 4)
> + List *except_leaves = NIL;
> + List *allowed_leaves = NIL;
>
> Similar to allowed_leaves, shall we have excepted_leaves instead of
> except_leaves?
>
> 5)
> pg_get_publication_effective_tables():
>
> +
> + /*
> + * Check whether the table itself or its schema is
> + * included in this publication.
> + */
> + if (is_relid_published_explicitly(curr_relid, pubid) ||
> + is_schema_published(get_rel_namespace(curr_relid), pubid))
> + {
> + allowed_leaves = lappend_oid(allowed_leaves, curr_relid);
> + }
> + else
> + {
> + List *ancestors = get_partition_ancestors(curr_relid);
> +
> + /*
> + * Check whether any ancestor, or its schema, is
> + * included in this publication.
> + */
> + foreach_oid(anc_oid, ancestors)
> + {
> + if (is_relid_published_explicitly(anc_oid, pubid) ||
> + is_schema_published(get_rel_namespace(anc_oid), pubid))
> + allowed_leaves = lappend_oid(allowed_leaves, curr_relid);
> + }
> + }
>
> Do you think we can convert this code part to
> is_relid_or_ancestor_published(), similar to
> is_relid_published_as_except_with_ancestors()?
>
> is_relid_or_ancestor_published() can check both pg_publication_rel and
> pg_publication_namespace. I do not see individual use-case scenarios
> for is_relid_published_explicitly() and is_schema_published() and thus
> it is better to club these in one function. So at the end we will be
> left with 2 such functions:
>
> is_relid_or_ancestor_published
> is_relid_or_ancestor_excepted/excluded (choose the name based on
> others comments too)
>

A few more:

6)
postgres=# CREATE PUBLICATION pub4 for ALL TABLES EXCEPT TABLE (tab1);
ERROR: cannot add relation "tab1" to publication
DETAIL: This operation is not supported for temporary tables.

postgres=# CREATE PUBLICATION pub4 for ALL TABLES EXCEPT TABLE (tab2);
ERROR: cannot add relation "tab2" to publication
DETAIL: This operation is not supported for unlogged tables.

Shall we change the error message here as we are not trying to add
relation here.

7)
Currently the error i s:

postgres=# create subscription sub1 connection '...' publication pub1,pub2,pub3;
ERROR: publications "pub1", "pub2", "pub3" are defined with EXCEPT TABLE
HINT: Subscription cannot be created using multiple publications that
specify EXCEPT TABLE.

Hint looks more like DETAIL. Shall we have this:

ERROR: cannot create subscription with multiple publications that
specify EXCEPT TABLE
DETAIL: The publications "pub1", "pub2", and "pub3" define EXCEPT
TABLE clauses.

8)
pg_get_publication_effective_tables():

+ /* Return root immediately if no filtering logic is needed */
+ if (has_clean_all_tables_pub || !has_any_except)

I think we do not need any additional boolean 'has_any_except' for
this purpose. We can simply rely on 'except_pub_names' being Nil.

9)
+ /* Return root immediately if no filtering logic is needed */
+ if (has_clean_all_tables_pub || !has_any_except)
+ {
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+ final_output = list_make1_oid(root_relid);
+ MemoryContextSwitchTo(oldcontext);
+ }
+ else

Can we please write a comment atop 'else' block to say what it is
going to attempt? This is because there is a big chunk of code in
'else' block and it is difficult to construct our logic by reading
each part of it.

10)
CreatePublication() has changed the way we process publications.
Earlier, we had explicit checks for publication types such as
'for_all_tables' and 'for_all_sequences' etc, which made the code
easier to follow. That differentiation based on publication type is no
longer there. As an example,
we now invoke functions like TransformPubWhereClauses() and
CheckPubRelationColumnList() even for FOR ALL TABLES ... EXCEPT
publications, which are not needed. We could consider restoring the
previous structure, where logic was clearly separated based on
publication type.

thanks
Shveta


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-18 06:11:38
Message-ID: CAA4eK1KWqttt3UMdR8P0wYyqDO6cuLhuvGb5cDpuctG8F10EFA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Feb 17, 2026 at 5:08 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Tue, Feb 17, 2026 at 12:01 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > On Tue, Feb 17, 2026 at 11:13 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > >
> > > Thanks for the comments. The attached v45 version patch has the
> > > changes for the same.
> > >
> >
> > Thanks Vignesh, please find a few comments from v44 itself. Please
> > ignore if already addressed. Will switch to v45 now.
> >
> >
> > 1)
> > publication_has_any_exception:
> > + ScanKeyInit(&skey,
> > + Anum_pg_publication_rel_prpubid,
> > + BTEqualStrategyNumber, F_OIDEQ,
> > + ObjectIdGetDatum(pubid));
> > +
> > + scan = systable_beginscan(pubRel,
> > + PublicationRelPrrelidPrpubidIndexId,
> > + true, NULL, 1, &skey);
> >
> > PublicationRelPrrelidPrpubidIndexId is index on relid and pubid, I
> > don't think it will be used in this case where we have only pubid key.
> > Shall we use PublicationRelPrpubidIndexId instead?
> >
> > 2)
> > +/*
> > + * is_relid_published_explicitly
> > + *
> > + * Checks if the given relation OID is explicitly part of the publication.
> > + * This corresponds to the 'FOR TABLE' syntax.
> > + */
> > +static bool
> > +is_relid_published_explicitly(Oid relid, Oid pubid)
> > +{
> > + /*
> > + * Search the syscache for pg_publication_rel using the (relid, pubid)
> > + * index.
> > + */
> > + return SearchSysCacheExists2(PUBLICATIONRELMAP,
> > + ObjectIdGetDatum(relid),
> > + ObjectIdGetDatum(pubid));
> > +}
> >
> > How are we ensuring that it is not fetching the one with except-flag
> > as true? Shall we assert when pub is all-tables to rule out that
> > case/mistake? Or if we code-flow is expected to come to this function
> > even for 'all-tables' pub (it appears to me t by looking at the
> > caller), we shall return in such a case instead of Assert.
> >
> >
> > 3)
> > Shall we rename these:
> > 'is_relid_published_as_except' as 'is_relid_excepted'.
> > 'is_relid_published_as_except_with_ancestors' as 'is_relid_or_ancestor_excepted'
> >
> > These will be to match tones of:
> > is_schema_published
> > is_relid_published_explicitly
> >
> > I feel even for 'is_relid_published_explicitly', we can simply say
> > 'is_relid_published'. Comments (and assert/checks) can explain that it
> > is for FOR-TABLE pub.
> >
> > 4)
> > + List *except_leaves = NIL;
> > + List *allowed_leaves = NIL;
> >
> > Similar to allowed_leaves, shall we have excepted_leaves instead of
> > except_leaves?
> >
> > 5)
> > pg_get_publication_effective_tables():
> >
> > +
> > + /*
> > + * Check whether the table itself or its schema is
> > + * included in this publication.
> > + */
> > + if (is_relid_published_explicitly(curr_relid, pubid) ||
> > + is_schema_published(get_rel_namespace(curr_relid), pubid))
> > + {
> > + allowed_leaves = lappend_oid(allowed_leaves, curr_relid);
> > + }
> > + else
> > + {
> > + List *ancestors = get_partition_ancestors(curr_relid);
> > +
> > + /*
> > + * Check whether any ancestor, or its schema, is
> > + * included in this publication.
> > + */
> > + foreach_oid(anc_oid, ancestors)
> > + {
> > + if (is_relid_published_explicitly(anc_oid, pubid) ||
> > + is_schema_published(get_rel_namespace(anc_oid), pubid))
> > + allowed_leaves = lappend_oid(allowed_leaves, curr_relid);
> > + }
> > + }
> >
> > Do you think we can convert this code part to
> > is_relid_or_ancestor_published(), similar to
> > is_relid_published_as_except_with_ancestors()?
> >
> > is_relid_or_ancestor_published() can check both pg_publication_rel and
> > pg_publication_namespace. I do not see individual use-case scenarios
> > for is_relid_published_explicitly() and is_schema_published() and thus
> > it is better to club these in one function. So at the end we will be
> > left with 2 such functions:
> >
> > is_relid_or_ancestor_published
> > is_relid_or_ancestor_excepted/excluded (choose the name based on
> > others comments too)
> >
>
> A few more:
>
> 6)
> postgres=# CREATE PUBLICATION pub4 for ALL TABLES EXCEPT TABLE (tab1);
> ERROR: cannot add relation "tab1" to publication
> DETAIL: This operation is not supported for temporary tables.
>
> postgres=# CREATE PUBLICATION pub4 for ALL TABLES EXCEPT TABLE (tab2);
> ERROR: cannot add relation "tab2" to publication
> DETAIL: This operation is not supported for unlogged tables.
>
> Shall we change the error message here as we are not trying to add
> relation here.
>

But aren't these existing messages? As these are not added by this
patch and equally apply to existing code, so, isn't it better to
discuss these separately if you think these are not suitable?

> 7)
> Currently the error i s:
>
> postgres=# create subscription sub1 connection '...' publication pub1,pub2,pub3;
> ERROR: publications "pub1", "pub2", "pub3" are defined with EXCEPT TABLE
> HINT: Subscription cannot be created using multiple publications that
> specify EXCEPT TABLE.
>
> Hint looks more like DETAIL. Shall we have this:
>
> ERROR: cannot create subscription with multiple publications that
> specify EXCEPT TABLE
> DETAIL: The publications "pub1", "pub2", and "pub3" define EXCEPT
> TABLE clauses.
>

So, you are talking about below error:
+ ereport(ERROR,
+ errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("publications %s are defined with EXCEPT TABLE", pubnames.data),
+ errhint("Subscription cannot be created using multiple publications
that specify EXCEPT TABLE."));

Apart from the message, the error code here should be
ERRCODE_FEATURE_NOT_SUPPORTED. How about an errmsg like: "cannot
combine publications %s with EXCEPT TABLE clauses",
except_publications? If we choose a message like that then we don't
need a hint. I suggest you can refer to the following column list
message to form a message for the except clause.

ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot use different column lists for table \"%s.%s\" in
different publications",
nspname, relname));

Few other minor comments:
1.
+ * Combining different exclusion lists with varying settings for
+ * 'publish_via_partition_root' can result in ambiguous publication
+ * identities.

It would be better if you give one such example case so that it is
easy for reader to understand why we don't support this combination.

2.
+ *
+ * Publications declared with FOR ALL TABLES should use
+ * GetAllPublicationRelations() to obtain the complete set of tables covered by
+ * the publication.
+ */
+List *
+GetPublicationIncludedRelations(Oid pubid, PublicationPartOpt pub_partopt)

Shouldn't this mention the ALL SEQUENCES case as well in the comments
as we were previously doing for GetPublicationRelations.

--
With Regards,
Amit Kapila.


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-18 06:50:23
Message-ID: CAA4eK1+Qv7rbsSs8FgNeNUwzt2cuquPN6b2-QM5XUiYHzJWLsQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Feb 17, 2026 at 5:08 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> 10)
> CreatePublication() has changed the way we process publications.
> Earlier, we had explicit checks for publication types such as
> 'for_all_tables' and 'for_all_sequences' etc, which made the code
> easier to follow. That differentiation based on publication type is no
> longer there. As an example,
> we now invoke functions like TransformPubWhereClauses() and
> CheckPubRelationColumnList() even for FOR ALL TABLES ... EXCEPT
> publications, which are not needed. We could consider restoring the
> previous structure, where logic was clearly separated based on
> publication type.
>

Yeah, we can do that if it doesn't add more complexity w.r.t except
clause because the proposed approach tries to unify the code path
where we need to add relations to pg_publication_rel. I think we are
doing some of the new stuff even for all sequences case as well which
is not required for the patch. If we want we can keep a flag
indicating the presence of the except flag in CreatePublicationStmt to
simplify the handling. BTW, the patch doesn't implement EXCEPT clause
for ALL SEQUENCES, is it because we want to deal with that separately
to avoid additional complexity in the patch? Otherwise, I think that
is a natural extension of this work.

--
With Regards,
Amit Kapila.


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-18 06:57:55
Message-ID: CAJpy0uBo0Av05UWUkAPxXbW6FL1rqAvW8q5amocmo8LYF+ReMQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Feb 18, 2026 at 11:41 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Tue, Feb 17, 2026 at 5:08 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > On Tue, Feb 17, 2026 at 12:01 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> > >
> > > On Tue, Feb 17, 2026 at 11:13 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > > >
> > > > Thanks for the comments. The attached v45 version patch has the
> > > > changes for the same.
> > > >
> > >
> > > Thanks Vignesh, please find a few comments from v44 itself. Please
> > > ignore if already addressed. Will switch to v45 now.
> > >
> > >
> > > 1)
> > > publication_has_any_exception:
> > > + ScanKeyInit(&skey,
> > > + Anum_pg_publication_rel_prpubid,
> > > + BTEqualStrategyNumber, F_OIDEQ,
> > > + ObjectIdGetDatum(pubid));
> > > +
> > > + scan = systable_beginscan(pubRel,
> > > + PublicationRelPrrelidPrpubidIndexId,
> > > + true, NULL, 1, &skey);
> > >
> > > PublicationRelPrrelidPrpubidIndexId is index on relid and pubid, I
> > > don't think it will be used in this case where we have only pubid key.
> > > Shall we use PublicationRelPrpubidIndexId instead?
> > >
> > > 2)
> > > +/*
> > > + * is_relid_published_explicitly
> > > + *
> > > + * Checks if the given relation OID is explicitly part of the publication.
> > > + * This corresponds to the 'FOR TABLE' syntax.
> > > + */
> > > +static bool
> > > +is_relid_published_explicitly(Oid relid, Oid pubid)
> > > +{
> > > + /*
> > > + * Search the syscache for pg_publication_rel using the (relid, pubid)
> > > + * index.
> > > + */
> > > + return SearchSysCacheExists2(PUBLICATIONRELMAP,
> > > + ObjectIdGetDatum(relid),
> > > + ObjectIdGetDatum(pubid));
> > > +}
> > >
> > > How are we ensuring that it is not fetching the one with except-flag
> > > as true? Shall we assert when pub is all-tables to rule out that
> > > case/mistake? Or if we code-flow is expected to come to this function
> > > even for 'all-tables' pub (it appears to me t by looking at the
> > > caller), we shall return in such a case instead of Assert.
> > >
> > >
> > > 3)
> > > Shall we rename these:
> > > 'is_relid_published_as_except' as 'is_relid_excepted'.
> > > 'is_relid_published_as_except_with_ancestors' as 'is_relid_or_ancestor_excepted'
> > >
> > > These will be to match tones of:
> > > is_schema_published
> > > is_relid_published_explicitly
> > >
> > > I feel even for 'is_relid_published_explicitly', we can simply say
> > > 'is_relid_published'. Comments (and assert/checks) can explain that it
> > > is for FOR-TABLE pub.
> > >
> > > 4)
> > > + List *except_leaves = NIL;
> > > + List *allowed_leaves = NIL;
> > >
> > > Similar to allowed_leaves, shall we have excepted_leaves instead of
> > > except_leaves?
> > >
> > > 5)
> > > pg_get_publication_effective_tables():
> > >
> > > +
> > > + /*
> > > + * Check whether the table itself or its schema is
> > > + * included in this publication.
> > > + */
> > > + if (is_relid_published_explicitly(curr_relid, pubid) ||
> > > + is_schema_published(get_rel_namespace(curr_relid), pubid))
> > > + {
> > > + allowed_leaves = lappend_oid(allowed_leaves, curr_relid);
> > > + }
> > > + else
> > > + {
> > > + List *ancestors = get_partition_ancestors(curr_relid);
> > > +
> > > + /*
> > > + * Check whether any ancestor, or its schema, is
> > > + * included in this publication.
> > > + */
> > > + foreach_oid(anc_oid, ancestors)
> > > + {
> > > + if (is_relid_published_explicitly(anc_oid, pubid) ||
> > > + is_schema_published(get_rel_namespace(anc_oid), pubid))
> > > + allowed_leaves = lappend_oid(allowed_leaves, curr_relid);
> > > + }
> > > + }
> > >
> > > Do you think we can convert this code part to
> > > is_relid_or_ancestor_published(), similar to
> > > is_relid_published_as_except_with_ancestors()?
> > >
> > > is_relid_or_ancestor_published() can check both pg_publication_rel and
> > > pg_publication_namespace. I do not see individual use-case scenarios
> > > for is_relid_published_explicitly() and is_schema_published() and thus
> > > it is better to club these in one function. So at the end we will be
> > > left with 2 such functions:
> > >
> > > is_relid_or_ancestor_published
> > > is_relid_or_ancestor_excepted/excluded (choose the name based on
> > > others comments too)
> > >
> >
> > A few more:
> >
> > 6)
> > postgres=# CREATE PUBLICATION pub4 for ALL TABLES EXCEPT TABLE (tab1);
> > ERROR: cannot add relation "tab1" to publication
> > DETAIL: This operation is not supported for temporary tables.
> >
> > postgres=# CREATE PUBLICATION pub4 for ALL TABLES EXCEPT TABLE (tab2);
> > ERROR: cannot add relation "tab2" to publication
> > DETAIL: This operation is not supported for unlogged tables.
> >
> > Shall we change the error message here as we are not trying to add
> > relation here.
> >
>
> But aren't these existing messages? As these are not added by this
> patch and equally apply to existing code, so, isn't it better to
> discuss these separately if you think these are not suitable?
>

I do not have strong opinion here but this is what I originally had in mind:

1) 'cannot add relation .. to publication' is confusing when the user
is actually trying to exclude them.
2) Since these tables are already excluded because of their unlogged
and temporary nature, the error is further misleading.

Perhaps we shall have:
ERROR: cannot specify relation "tab1" in publication
DETAIL: Unlogged tables are automatically excluded from publication.

Or something better? Or do you think we are okay as is?

> > 7)
> > Currently the error i s:
> >
> > postgres=# create subscription sub1 connection '...' publication pub1,pub2,pub3;
> > ERROR: publications "pub1", "pub2", "pub3" are defined with EXCEPT TABLE
> > HINT: Subscription cannot be created using multiple publications that
> > specify EXCEPT TABLE.
> >
> > Hint looks more like DETAIL. Shall we have this:
> >
> > ERROR: cannot create subscription with multiple publications that
> > specify EXCEPT TABLE
> > DETAIL: The publications "pub1", "pub2", and "pub3" define EXCEPT
> > TABLE clauses.
> >
>
> So, you are talking about below error:
> + ereport(ERROR,
> + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> + errmsg("publications %s are defined with EXCEPT TABLE", pubnames.data),
> + errhint("Subscription cannot be created using multiple publications
> that specify EXCEPT TABLE."));
>
> Apart from the message, the error code here should be
> ERRCODE_FEATURE_NOT_SUPPORTED. How about an errmsg like: "cannot
> combine publications %s with EXCEPT TABLE clauses",
> except_publications? If we choose a message like that then we don't
> need a hint. I suggest you can refer to the following column list
> message to form a message for the except clause.

The proposed message looks good.

thanks
Shveta


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-18 07:39:08
Message-ID: CAA4eK1J=41eienWGzgAnB_-fAGjZdB2daP_N=84NSm1QT56YVQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Feb 18, 2026 at 12:28 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Wed, Feb 18, 2026 at 11:41 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> > On Tue, Feb 17, 2026 at 5:08 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> > >
> > > A few more:
> > >
> > > 6)
> > > postgres=# CREATE PUBLICATION pub4 for ALL TABLES EXCEPT TABLE (tab1);
> > > ERROR: cannot add relation "tab1" to publication
> > > DETAIL: This operation is not supported for temporary tables.
> > >
> > > postgres=# CREATE PUBLICATION pub4 for ALL TABLES EXCEPT TABLE (tab2);
> > > ERROR: cannot add relation "tab2" to publication
> > > DETAIL: This operation is not supported for unlogged tables.
> > >
> > > Shall we change the error message here as we are not trying to add
> > > relation here.
> > >
> >
> > But aren't these existing messages? As these are not added by this
> > patch and equally apply to existing code, so, isn't it better to
> > discuss these separately if you think these are not suitable?
> >
>
> I do not have strong opinion here but this is what I originally had in mind:
>
> 1) 'cannot add relation .. to publication' is confusing when the user
> is actually trying to exclude them.
> 2) Since these tables are already excluded because of their unlogged
> and temporary nature, the error is further misleading.
>
> Perhaps we shall have:
> ERROR: cannot specify relation "tab1" in publication
> DETAIL: Unlogged tables are automatically excluded from publication.
>

Your proposed message for this case sounds good to me.

--
With Regards,
Amit Kapila.


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-18 11:04:07
Message-ID: CAA4eK1KyWMYxPKL3Owveb3xciGpgfDRZcX1J3Y4yppJXRQAgBQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Feb 18, 2026 at 11:41 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Tue, Feb 17, 2026 at 5:08 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
>
> > 7)
> > Currently the error i s:
> >
> > postgres=# create subscription sub1 connection '...' publication pub1,pub2,pub3;
> > ERROR: publications "pub1", "pub2", "pub3" are defined with EXCEPT TABLE
> > HINT: Subscription cannot be created using multiple publications that
> > specify EXCEPT TABLE.
> >
> > Hint looks more like DETAIL. Shall we have this:
> >
> > ERROR: cannot create subscription with multiple publications that
> > specify EXCEPT TABLE
> > DETAIL: The publications "pub1", "pub2", and "pub3" define EXCEPT
> > TABLE clauses.
> >
>
> So, you are talking about below error:
> + ereport(ERROR,
> + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> + errmsg("publications %s are defined with EXCEPT TABLE", pubnames.data),
> + errhint("Subscription cannot be created using multiple publications
> that specify EXCEPT TABLE."));
>
> Apart from the message, the error code here should be
> ERRCODE_FEATURE_NOT_SUPPORTED. How about an errmsg like: "cannot
> combine publications %s with EXCEPT TABLE clauses",
> except_publications? If we choose a message like that then we don't
> need a hint. I suggest you can refer to the following column list
> message to form a message for the except clause.
>
> ereport(ERROR,
> errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
> errmsg("cannot use different column lists for table \"%s.%s\" in
> different publications",
> nspname, relname));
>

Based on the above, the following message should also be changed:
+ ereport(ERROR,
+ errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot use multiple publications with EXCEPT TABLE lists"),
+ errdetail("The following publications have exceptions: %s.",
+ pub_names_str.data));

Few more minor comments:
1.
+ elog(LOG, "fetch_relation_list: executing query to fetch
effectiverelations: \n%s",
+ cmd.data);

space is required between effective and relations.

2.
@@ -10858,6 +10862,7 @@ PublicationObjSpec:
$$->pubtable->relation = $2;
$$->pubtable->columns = $3;
$$->pubtable->whereClause = $4;
+ $$->location = @1;
what is purpose of this change in PublicationObjSpec?

3.
+ elog(LOG, "Executing query to get the tables:\n%s", cmd.data);

This can be more specific. How about "Executing query to get the
partition tables to be copied" or something like that?

--
With Regards,
Amit Kapila.


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-19 04:43:30
Message-ID: CANhcyEXBw0NeCmrbzSEQ3bBHzzEwvyLo-rOx0migTtfm-H4sNw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, 17 Feb 2026 at 17:08, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Tue, Feb 17, 2026 at 12:01 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > On Tue, Feb 17, 2026 at 11:13 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > >
> > > Thanks for the comments. The attached v45 version patch has the
> > > changes for the same.
> > >
> >
> > Thanks Vignesh, please find a few comments from v44 itself. Please
> > ignore if already addressed. Will switch to v45 now.
> >
> >
> > 1)
> > publication_has_any_exception:
> > + ScanKeyInit(&skey,
> > + Anum_pg_publication_rel_prpubid,
> > + BTEqualStrategyNumber, F_OIDEQ,
> > + ObjectIdGetDatum(pubid));
> > +
> > + scan = systable_beginscan(pubRel,
> > + PublicationRelPrrelidPrpubidIndexId,
> > + true, NULL, 1, &skey);
> >
> > PublicationRelPrrelidPrpubidIndexId is index on relid and pubid, I
> > don't think it will be used in this case where we have only pubid key.
> > Shall we use PublicationRelPrpubidIndexId instead?
> >
> > 2)
> > +/*
> > + * is_relid_published_explicitly
> > + *
> > + * Checks if the given relation OID is explicitly part of the publication.
> > + * This corresponds to the 'FOR TABLE' syntax.
> > + */
> > +static bool
> > +is_relid_published_explicitly(Oid relid, Oid pubid)
> > +{
> > + /*
> > + * Search the syscache for pg_publication_rel using the (relid, pubid)
> > + * index.
> > + */
> > + return SearchSysCacheExists2(PUBLICATIONRELMAP,
> > + ObjectIdGetDatum(relid),
> > + ObjectIdGetDatum(pubid));
> > +}
> >
> > How are we ensuring that it is not fetching the one with except-flag
> > as true? Shall we assert when pub is all-tables to rule out that
> > case/mistake? Or if we code-flow is expected to come to this function
> > even for 'all-tables' pub (it appears to me t by looking at the
> > caller), we shall return in such a case instead of Assert.
> >
> >
> > 3)
> > Shall we rename these:
> > 'is_relid_published_as_except' as 'is_relid_excepted'.
> > 'is_relid_published_as_except_with_ancestors' as 'is_relid_or_ancestor_excepted'
> >
> > These will be to match tones of:
> > is_schema_published
> > is_relid_published_explicitly
> >
> > I feel even for 'is_relid_published_explicitly', we can simply say
> > 'is_relid_published'. Comments (and assert/checks) can explain that it
> > is for FOR-TABLE pub.
> >
> > 4)
> > + List *except_leaves = NIL;
> > + List *allowed_leaves = NIL;
> >
> > Similar to allowed_leaves, shall we have excepted_leaves instead of
> > except_leaves?
> >
> > 5)
> > pg_get_publication_effective_tables():
> >
> > +
> > + /*
> > + * Check whether the table itself or its schema is
> > + * included in this publication.
> > + */
> > + if (is_relid_published_explicitly(curr_relid, pubid) ||
> > + is_schema_published(get_rel_namespace(curr_relid), pubid))
> > + {
> > + allowed_leaves = lappend_oid(allowed_leaves, curr_relid);
> > + }
> > + else
> > + {
> > + List *ancestors = get_partition_ancestors(curr_relid);
> > +
> > + /*
> > + * Check whether any ancestor, or its schema, is
> > + * included in this publication.
> > + */
> > + foreach_oid(anc_oid, ancestors)
> > + {
> > + if (is_relid_published_explicitly(anc_oid, pubid) ||
> > + is_schema_published(get_rel_namespace(anc_oid), pubid))
> > + allowed_leaves = lappend_oid(allowed_leaves, curr_relid);
> > + }
> > + }
> >
> > Do you think we can convert this code part to
> > is_relid_or_ancestor_published(), similar to
> > is_relid_published_as_except_with_ancestors()?
> >
> > is_relid_or_ancestor_published() can check both pg_publication_rel and
> > pg_publication_namespace. I do not see individual use-case scenarios
> > for is_relid_published_explicitly() and is_schema_published() and thus
> > it is better to club these in one function. So at the end we will be
> > left with 2 such functions:
> >
> > is_relid_or_ancestor_published
> > is_relid_or_ancestor_excepted/excluded (choose the name based on
> > others comments too)
> >
>
> A few more:
>
> 6)
> postgres=# CREATE PUBLICATION pub4 for ALL TABLES EXCEPT TABLE (tab1);
> ERROR: cannot add relation "tab1" to publication
> DETAIL: This operation is not supported for temporary tables.
>
> postgres=# CREATE PUBLICATION pub4 for ALL TABLES EXCEPT TABLE (tab2);
> ERROR: cannot add relation "tab2" to publication
> DETAIL: This operation is not supported for unlogged tables.
>
> Shall we change the error message here as we are not trying to add
> relation here.
>
Based on the discussion in [1]. We are still analysing this change.
Will address it in the next version of patch.

> 7)
> Currently the error i s:
>
> postgres=# create subscription sub1 connection '...' publication pub1,pub2,pub3;
> ERROR: publications "pub1", "pub2", "pub3" are defined with EXCEPT TABLE
> HINT: Subscription cannot be created using multiple publications that
> specify EXCEPT TABLE.
>
> Hint looks more like DETAIL. Shall we have this:
>
> ERROR: cannot create subscription with multiple publications that
> specify EXCEPT TABLE
> DETAIL: The publications "pub1", "pub2", and "pub3" define EXCEPT
> TABLE clauses.
>
Modified it as per Amit's suggestion in [2].

> 8)
> pg_get_publication_effective_tables():
>
> + /* Return root immediately if no filtering logic is needed */
> + if (has_clean_all_tables_pub || !has_any_except)
>
> I think we do not need any additional boolean 'has_any_except' for
> this purpose. We can simply rely on 'except_pub_names' being Nil.
>
> 9)
> + /* Return root immediately if no filtering logic is needed */
> + if (has_clean_all_tables_pub || !has_any_except)
> + {
> + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
> + final_output = list_make1_oid(root_relid);
> + MemoryContextSwitchTo(oldcontext);
> + }
> + else
>
> Can we please write a comment atop 'else' block to say what it is
> going to attempt? This is because there is a big chunk of code in
> 'else' block and it is difficult to construct our logic by reading
> each part of it.
>
> 10)
> CreatePublication() has changed the way we process publications.
> Earlier, we had explicit checks for publication types such as
> 'for_all_tables' and 'for_all_sequences' etc, which made the code
> easier to follow. That differentiation based on publication type is no
> longer there. As an example,
> we now invoke functions like TransformPubWhereClauses() and
> CheckPubRelationColumnList() even for FOR ALL TABLES ... EXCEPT
> publications, which are not needed. We could consider restoring the
> previous structure, where logic was clearly separated based on
> publication type.
>

Thanks for reviewing the patch. I have addressed the remaining
comments in the v46 patch..

[1]: https://www.postgresql.org/message-id/CAA4eK1J%3D41eienWGzgAnB_-fAGjZdB2daP_N%3D84NSm1QT56YVQ%40mail.gmail.com
[2]: https://www.postgresql.org/message-id/CAA4eK1KWqttt3UMdR8P0wYyqDO6cuLhuvGb5cDpuctG8F10EFA%40mail.gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v46-0002-Extended-tests-for-EXCEPT-TABLE-patch.patch application/octet-stream 4.9 KB
v46-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 109.7 KB

From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-19 04:45:06
Message-ID: CANhcyEXJ_wTbpb74CCeXbXnPtM=yimUC1MXpD8PCJ6mBr1QzHw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 18 Feb 2026 at 16:34, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Wed, Feb 18, 2026 at 11:41 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> > On Tue, Feb 17, 2026 at 5:08 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> > >
> >
> > > 7)
> > > Currently the error i s:
> > >
> > > postgres=# create subscription sub1 connection '...' publication pub1,pub2,pub3;
> > > ERROR: publications "pub1", "pub2", "pub3" are defined with EXCEPT TABLE
> > > HINT: Subscription cannot be created using multiple publications that
> > > specify EXCEPT TABLE.
> > >
> > > Hint looks more like DETAIL. Shall we have this:
> > >
> > > ERROR: cannot create subscription with multiple publications that
> > > specify EXCEPT TABLE
> > > DETAIL: The publications "pub1", "pub2", and "pub3" define EXCEPT
> > > TABLE clauses.
> > >
> >
> > So, you are talking about below error:
> > + ereport(ERROR,
> > + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> > + errmsg("publications %s are defined with EXCEPT TABLE", pubnames.data),
> > + errhint("Subscription cannot be created using multiple publications
> > that specify EXCEPT TABLE."));
> >
> > Apart from the message, the error code here should be
> > ERRCODE_FEATURE_NOT_SUPPORTED. How about an errmsg like: "cannot
> > combine publications %s with EXCEPT TABLE clauses",
> > except_publications? If we choose a message like that then we don't
> > need a hint. I suggest you can refer to the following column list
> > message to form a message for the except clause.
> >
> > ereport(ERROR,
> > errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
> > errmsg("cannot use different column lists for table \"%s.%s\" in
> > different publications",
> > nspname, relname));
> >
>
> Based on the above, the following message should also be changed:
> + ereport(ERROR,
> + errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
> + errmsg("cannot use multiple publications with EXCEPT TABLE lists"),
> + errdetail("The following publications have exceptions: %s.",
> + pub_names_str.data));
>
> Few more minor comments:
> 1.
> + elog(LOG, "fetch_relation_list: executing query to fetch
> effectiverelations: \n%s",
> + cmd.data);
>
> space is required between effective and relations.
>
> 2.
> @@ -10858,6 +10862,7 @@ PublicationObjSpec:
> $$->pubtable->relation = $2;
> $$->pubtable->columns = $3;
> $$->pubtable->whereClause = $4;
> + $$->location = @1;
> what is purpose of this change in PublicationObjSpec?
>
> 3.
> + elog(LOG, "Executing query to get the tables:\n%s", cmd.data);
>
> This can be more specific. How about "Executing query to get the
> partition tables to be copied" or something like that?
>
Hi Amit,

Thanks for reviewing the patch. I have addressed the above comments
and the minor comments in [1] in v46 patch.
I have shared v46 patch in [2].

[1]: https://www.postgresql.org/message-id/CAA4eK1KWqttt3UMdR8P0wYyqDO6cuLhuvGb5cDpuctG8F10EFA%40mail.gmail.com
[2]: https://www.postgresql.org/message-id/CANhcyEXBw0NeCmrbzSEQ3bBHzzEwvyLo-rOx0migTtfm-H4sNw%40mail.gmail.com

Thanks,
Shlok Kyal


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-19 04:45:24
Message-ID: CANhcyEVWy9jer3vqeiP5hQa3R_Zv_L98r1mmMhwSmeOancdjKg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 18 Feb 2026 at 12:20, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Tue, Feb 17, 2026 at 5:08 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > 10)
> > CreatePublication() has changed the way we process publications.
> > Earlier, we had explicit checks for publication types such as
> > 'for_all_tables' and 'for_all_sequences' etc, which made the code
> > easier to follow. That differentiation based on publication type is no
> > longer there. As an example,
> > we now invoke functions like TransformPubWhereClauses() and
> > CheckPubRelationColumnList() even for FOR ALL TABLES ... EXCEPT
> > publications, which are not needed. We could consider restoring the
> > previous structure, where logic was clearly separated based on
> > publication type.
> >
>
> Yeah, we can do that if it doesn't add more complexity w.r.t except
> clause because the proposed approach tries to unify the code path
> where we need to add relations to pg_publication_rel. I think we are
> doing some of the new stuff even for all sequences case as well which
> is not required for the patch. If we want we can keep a flag
> indicating the presence of the except flag in CreatePublicationStmt to
> simplify the handling. BTW, the patch doesn't implement EXCEPT clause
> for ALL SEQUENCES, is it because we want to deal with that separately
> to avoid additional complexity in the patch? Otherwise, I think that
> is a natural extension of this work.
>
I have made the change as per Shveta's suggestion in the v46 patch [1].

We did not implement the EXCEPT clause for ALL SEQUENCES to avoid
additional complexity in the patch. And thought of implementing it
after this patch gets committed.
What do you suggest? Is it ok or should we also implement EXCEPT
clause for ALL SEQUENCES for this patch itself?

[1]: https://www.postgresql.org/message-id/CANhcyEXBw0NeCmrbzSEQ3bBHzzEwvyLo-rOx0migTtfm-H4sNw%40mail.gmail.com

Thanks,
Shlok Kyal


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-19 04:52:56
Message-ID: CAA4eK1JWz=+-zEhQRszrGEbOzYKReXtsS9hGycWubHV8v2U-QA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Feb 19, 2026 at 10:15 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> We did not implement the EXCEPT clause for ALL SEQUENCES to avoid
> additional complexity in the patch.
>

Fair enough.

> And thought of implementing it
> after this patch gets committed.
> What do you suggest? Is it ok or should we also implement EXCEPT
> clause for ALL SEQUENCES for this patch itself?
>

I am fine with doing it as a separate patch but let's try to get that
done immediately after the main patch (FOR ALL TABLES EXCEPT ...) is
committed.

--
With Regards,
Amit Kapila.


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-19 10:36:46
Message-ID: CAA4eK1JcrqPi7Pa9eQqj-=NFPAdzMhfVD=1jbwRWXT6tGtRyEw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Feb 19, 2026 at 10:13 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> Thanks for reviewing the patch. I have addressed the remaining
> comments in the v46 patch..
>

Can we think of some ideas to split this patch? One possibility is
that in the first patch we give an ERROR, if a non-root partitioned
table is present in EXCEPT Clause. I see that a lot of code is written
to handle partitions in EXCEPT clause. I feel such a split will make
code easier to review and validate.

Few other comments:
=================
1.
if (stmt->for_all_tables)
{
+ /* Process EXCEPT table list */
+ if (relations != NIL)
+ {
+ Assert(rels != NIL);
+ PublicationAddTables(puboid, rels, true, NULL);
+ }
+
/*
* Invalidate relcache so that publication info is rebuilt. Sequences
* publication doesn't require invalidation, as replica identity
CacheInvalidateRelcacheAll();

Here, the relations listed in the except table list will be
invalidated twice, once inside
PublicationAddTables->publication_add_relation, and second time via
CacheInvalidateRelcacheAll. Can we avoid that by adding a parameter to
PublicationAddTables?

2.
- root_relids = GetPublicationRelations(pubform->oid,
- PUBLICATION_PART_ROOT);
+ root_relids = GetIncludedRelationsByPub(pubform->oid,
+ PUBLICATION_PART_ROOT);

To follow the previous function naming pattern, can we rename
GetIncludedRelationsByPub to GetIncludedPublicationRelations? If we
agree to this then rename the excluded version of the function as
well.

3.
+/*
+ * Return the list of relation Oids for a publication.
+ *
+ * For a FOR TABLE publication, this returns the list of relations explicitly
+ * included in the publication.
+ *
+ * Publications declared with FOR ALL TABLES/SEQUENCES should use
+ * GetAllPublicationRelations() to obtain the complete set of tables/sequences
+ * covered by the publication.
+ */
+List *
+GetIncludedRelationsByPub(Oid pubid, PublicationPartOpt pub_partopt)

This is equivalent to the existing function GetPublicationRelations()
which has more precise comments atop. We can use the same comments
unless there is any functionality difference.

4.
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -29,6 +29,7 @@
#include "catalog/pg_publication.h"
#include "catalog/pg_publication_namespace.h"
#include "catalog/pg_publication_rel.h"
+#include "catalog/pg_subscription.h"

It appears odd to include pg_subscription.h in the publication code.
Is there a reason for the same? If not then avoid it.

Apart from above, a few cosmetic changes are attached.

--
With Regards,
Amit Kapila.

Attachment Content-Type Size
v46_amit_1.patch.txt text/plain 1.0 KB

From: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-19 10:38:01
Message-ID: CAFiTN-t2is4AOsNMw6iUcn-9cRTSUyQgivkbVjAE-6LjuVHC2w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Feb 19, 2026 at 10:13 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> Thanks for reviewing the patch. I have addressed the remaining
> comments in the v46 patch..
>
I am looking at the latest version some questions/comments

1.
GetRelationPublications()
{
..
for (int i = 0; i < pubrellist->n_members; i++)
{
+ if (pubrel->prexcept)
+ {
+ if (except_pubids)
+ *except_pubids = lappend_oid(*except_pubids, pubid);
+ }
+ else
+ {
+ if (pubids)
+ *pubids = lappend_oid(*pubids, pubid);
+ found = true;
+ }
}

Can we simplify this multi-level check to something simple by using
some temporary variable?
Suggestions:

for (int i = 0; i < pubrellist->n_members; i++)
{
List **target_list = pubrel->prexcept ? except_pubids : pubids;

if (target_list)
*target_list = lappend_oid(*target_list, pubid);
if (!pubrel->prexcept)
found = true;
}

2.
-extern List *GetPublicationRelations(Oid pubid, PublicationPartOpt
pub_partopt);
+extern List *GetIncludedRelationsByPub(Oid pubid,
+ PublicationPartOpt pub_partopt);

I don't really like renaming this function, IMHO the
GetPublicationRelations() means all the published relation, we don't
need to be explicit about *Included* relation. Then I see we have
another function to fetch the excluded relation i.e.
GetExcludedTablesByPub() so maybe this makes sense considering we have
a requirement for fetching included as well as excluded.

3. Question, what would be the behavior of
pg_get_publication_tables(), if we have created PUBLICATION FOR ALL
TABLES with EXCEPT, I assume it will give all table even in the EXCEPT
list as we have another function to get effective tables i.e.
pg_get_publication_effective_tables(), so my question is are we
planning to add an additional field in pg_get_publication_tables() to
explicitly mention that the table is EXCLUDED?

--
Regards,
Dilip Kumar
Google


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-19 11:51:50
Message-ID: CAJpy0uAg85aP8E+WfmoDPZOCF7_h-Pd=+ww0G17i9FZSFExYUQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Feb 19, 2026 at 10:13 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
>
> Thanks for reviewing the patch. I have addressed the remaining
> comments in the v46 patch..
>

Thanks. Please find a few comments:

1)
pg_get_publication_effective_tables has
+ ereport(ERROR,
+ errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot use multiple publications with EXCEPT TABLE lists"),
+ errdetail("The following publications have exceptions: %s.",
+ pub_names->data));

LoadPublications has:
+ ereport(ERROR,
+ errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot use multiple publications with EXCEPT TABLE lists"),
+ errdetail("Publications (%s) define EXCEPT TABLE clauses.",
+ pub_names_str.data));

check_publications_except_list has:
+ ereport(ERROR,
+ errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot combine publications %s with EXCEPT TABLE clauses",
pubnames.data));

Can we make all three messages the same based on which format was
decided earlier.

2)
+/* Helper: Check syscache for prexcept flag */
+bool
+is_relid_excepted(Oid relid, Oid pubid)

Can we move this function just before 'is_relid_or_ancestor_excepted'
as they are related functions? Can we also change the comments as well
similar to other functions?

3)
I see that is_schema_published() is only needed by
is_relid_or_ancestor_published() which calls is_relid_published()
already. Shall we make logic of 'is_schema_published' as part of
'is_relid_published' itself i.e. we will consider relid published if
it is published explicitly or as part of schema? Thoughts? This will
help us to avoid having 'is_schema_published' function separately when
its usage is quite limited.

4)
pg_get_publication_effective_tables() has neighboring comments:

+ /* Check whether this publication defines any EXCEPT entries */

+ /*
+ * This publication includes all tables without except.
+ */

We can choose the same comment style at both places. Please check the
rest of the function too.

thanks
Shveta


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-19 12:24:00
Message-ID: CAA4eK1L2D0mvSEKLNTvjD1JX_K1_WPkXXZ3wB2Q5UJ3iRyOxPw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Feb 19, 2026 at 4:08 PM Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:
>
> 3. Question, what would be the behavior of
> pg_get_publication_tables(), if we have created PUBLICATION FOR ALL
> TABLES with EXCEPT, I assume it will give all table even in the EXCEPT
> list
>

No, it won't return the tables mentioned in the except list and I
think that is what we expect from this function.

> as we have another function to get effective tables i.e.
> pg_get_publication_effective_tables(),
>

This function is for a different purpose and I think its name can be
improved, how about pg_get_publication_partitions() or something on
those lines?

--
With Regards,
Amit Kapila.


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-20 00:28:56
Message-ID: CAHut+PtbpKn4CUbUg11VdtzOBnu-NhZVCiVfHqZRaPaw4b=cRw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

A few of the recent function name change suggestions have originated
from my internal review comments. But, these changes are not very
effective unless they are done across existing functions as well to
keep everything consistent.

Background
----------
TBH, I always found many of the current HEAD names to be confusing. I
am often having to double-check back with the function comment to find
what was the intention.

e.g. Here is a list of some existing function names of pg_publication.c.
GetPubPartitionOptionRelations
GetRelationPublications
GetPublicationRelations
GetAllTablesPublications
GetAllPublicationRelations
GetPublicationSchemas
GetSchemaPublications
GetSchemaPublicationRelations
GetAllSchemaPublicationRelations
GetPublication
GetPublicationByName

At the core of my confusion is that the pattern GetYyyyXxxx means 2
different things:

- Sometimes the Yyyy is a search condition or "criteria" for what you
are getting. e.g. GetRelationPublications means "Get publications that
the specified relid is a member of"

- sometimes the Yyyy is more like an "attribute" for what you are
getting. e.g. GetAllTablesPublications means "Get all of the FOR ALL
TABLES publications"

Often there is some ambiguity:

e.g GetAllPublicationRelations
- does it mean "Get relations list equivalent to a FOR ALL TABLES publication"?
- does it mean "Get relations that are members of all the specified
publications"?

e.g. GetSchemaPublications
- does it mean "Get publications marked as FOR TABLES IN SCHEMA"?
- does it mean "Get publications for the specified schemaid"?

etc.

~~~

This thread's EXCEPT patch is not causing new problems, it's just
adding yet more functions to the long list of those that I felt are
ambiguous.

IMO, when a function returns XXX, then the function name should be
prefixed GetXXX.

So, I would advocate for existing function names to change; something
like below.

GetPubPartitionOptionRelations -> GetRelsByRelidAndPartitionOpt
GetRelationPublications -> GetPubsByRelid
GetPublicationRelations -> GetRelsByPubidMarkedForTable
GetAllTablesPublications -> GetPubsMarkedForAllTables
GetAllPublicationRelations -> GetRelsOfPubsMarkedForAll
GetPublicationSchemas -> GetSchemasByPubidMarkedForTablesInSchema
GetSchemaPublications -> GetPubsMarkedForTablesInSchemaBySchemaid
GetSchemaPublicationRelations -> GetPublishedRelsBySchemaid
GetAllSchemaPublicationRelations -> GetRelsOfPubsMarkedForTablesInSchema
GetPublication -> GetPubByPubid
GetPublicationByName -> GetPubByName

Then, any new (non-static) functions for this EXCEPT patch would be
named similarly.

~

I understand that maybe everyone else feels the current names are fine
as-is and not confusing at all.
Or, maybe the confusion is recognised, but now is just not a good time
of year to change everything.

Anyway, I just wanted to give the background, and explain reasons for
those function name suggestions.

======
Kind Regards,
Peter Smith.
Fujitsu Australia.


From: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-20 05:16:02
Message-ID: CAFiTN-vVFbzNQ__CppQdB6hJ3r+bLuy1XYUL0gou=UY4aeR5wg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Feb 19, 2026 at 5:54 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Thu, Feb 19, 2026 at 4:08 PM Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:
> >
> > 3. Question, what would be the behavior of
> > pg_get_publication_tables(), if we have created PUBLICATION FOR ALL
> > TABLES with EXCEPT, I assume it will give all table even in the EXCEPT
> > list
> >
>
> No, it won't return the tables mentioned in the except list and I
> think that is what we expect from this function.

Yeah logically that makes sense, I got confused because of the another
function with name 'pg_get_publication_effective_tables'

> > as we have another function to get effective tables i.e.
> > pg_get_publication_effective_tables(),
> >
>
> This function is for a different purpose and I think its name can be
> improved, how about pg_get_publication_partitions() or something on
> those lines?

I think the current name is confusing, not sure about what would be a
better name, IMHO pg_get_publication_partitions() is not confusing at
least.

And also ,regarding the naming of is_relid_excepted() and
is_relid_or_ancestor_excepted(), although they accurately reflect the
EXCEPT keyword, "excepted" feels a bit awkward in code. I'd suggest
changing these to is_relid_excluded() and
is_relid_or_ancestor_excluded() for better readability. But if others
think excepted also looks fine and it's just me who doesn't like it
then feel free to ignore this suggestion.

--
Regards,
Dilip Kumar
Google


From: Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-20 05:26:09
Message-ID: CAE9k0P=SfawUYBoSmK9Zxwey774OJw5g4Gb7+fA3CQ22j83a7Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Feb 20, 2026 at 5:59 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> A few of the recent function name change suggestions have originated
> from my internal review comments. But, these changes are not very
> effective unless they are done across existing functions as well to
> keep everything consistent.
>
> Background
> ----------
> TBH, I always found many of the current HEAD names to be confusing. I
> am often having to double-check back with the function comment to find
> what was the intention.
>
> e.g. Here is a list of some existing function names of pg_publication.c.
> GetPubPartitionOptionRelations
> GetRelationPublications
> GetPublicationRelations
> GetAllTablesPublications
> GetAllPublicationRelations
> GetPublicationSchemas
> GetSchemaPublications
> GetSchemaPublicationRelations
> GetAllSchemaPublicationRelations
> GetPublication
> GetPublicationByName
>
> At the core of my confusion is that the pattern GetYyyyXxxx means 2
> different things:
>
> - Sometimes the Yyyy is a search condition or "criteria" for what you
> are getting. e.g. GetRelationPublications means "Get publications that
> the specified relid is a member of"
>
> - sometimes the Yyyy is more like an "attribute" for what you are
> getting. e.g. GetAllTablesPublications means "Get all of the FOR ALL
> TABLES publications"
>
> Often there is some ambiguity:
>
> e.g GetAllPublicationRelations
> - does it mean "Get relations list equivalent to a FOR ALL TABLES publication"?
> - does it mean "Get relations that are members of all the specified
> publications"?
>
> e.g. GetSchemaPublications
> - does it mean "Get publications marked as FOR TABLES IN SCHEMA"?
> - does it mean "Get publications for the specified schemaid"?
>
> etc.
>
> ~~~
>
> This thread's EXCEPT patch is not causing new problems, it's just
> adding yet more functions to the long list of those that I felt are
> ambiguous.
>
> IMO, when a function returns XXX, then the function name should be
> prefixed GetXXX.
>
> So, I would advocate for existing function names to change; something
> like below.
>
> GetPubPartitionOptionRelations -> GetRelsByRelidAndPartitionOpt
> GetRelationPublications -> GetPubsByRelid
> GetPublicationRelations -> GetRelsByPubidMarkedForTable
> GetAllTablesPublications -> GetPubsMarkedForAllTables
> GetAllPublicationRelations -> GetRelsOfPubsMarkedForAll
> GetPublicationSchemas -> GetSchemasByPubidMarkedForTablesInSchema
> GetSchemaPublications -> GetPubsMarkedForTablesInSchemaBySchemaid
> GetSchemaPublicationRelations -> GetPublishedRelsBySchemaid
> GetAllSchemaPublicationRelations -> GetRelsOfPubsMarkedForTablesInSchema
> GetPublication -> GetPubByPubid
> GetPublicationByName -> GetPubByName
>
> Then, any new (non-static) functions for this EXCEPT patch would be
> named similarly.
>
> ~
>
> I understand that maybe everyone else feels the current names are fine
> as-is and not confusing at all.
> Or, maybe the confusion is recognised, but now is just not a good time
> of year to change everything.
>
> Anyway, I just wanted to give the background, and explain reasons for
> those function name suggestions.
>

Few more comments on top of these:

+ elog(LOG, "fetch_relation_list: executing query to fetch
effectiverelations: \n%s",
+ cmd.data);

This looks like a debugging log message, did you add it for debugging
purposes but later forgot to change its elevel or probably clean up?

--

+relation_is_effectively_excluded(Oid relid, List *exceptlist)
+{
+ List *leaftables = NIL;
+
+ if (exceptlist == NIL)
+ return false;
+
+ /* Explicitly excluded */
+ if (list_member_oid(exceptlist, relid))
+ return true;
+
+ /* Get all leaf partitions of relid */
+ leaftables = GetPubPartitionOptionRelations(leaftables,
+ PUBLICATION_PART_LEAF,
+

"leaftables" are never freed on either return path. Since this
function is called in a loop from GetAllPublicationRelations() during
catalog scans, this has the potential to accumulate memory.

--

+ res = walrcv_exec(LogRepWorkerWalRcvConn, cmd.data,
+ lengthof(filtertableRow), filtertableRow);

Seems like we are missing "walrcv_clear_result()" for this.

--

+/* Helper: Check syscache for prexcept flag */
+bool
+is_relid_excepted(Oid relid, Oid pubid)

The comment atop this function needs some improvement it seems. It is
trying to explain how it is implemented, rather than its purpose.

--
With Regards,
Ashutosh Sharma,


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-20 08:38:21
Message-ID: CALDaNm3X24fJznRUFh6NVhY1SDzgY9Aie1Ks=b6YqmAx-Z4H7Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 19 Feb 2026 at 16:06, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Thu, Feb 19, 2026 at 10:13 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > Thanks for reviewing the patch. I have addressed the remaining
> > comments in the v46 patch..
> >
>
> Can we think of some ideas to split this patch? One possibility is
> that in the first patch we give an ERROR, if a non-root partitioned
> table is present in EXCEPT Clause. I see that a lot of code is written
> to handle partitions in EXCEPT clause. I feel such a split will make
> code easier to review and validate.

Split it accordingly.

> Few other comments:
> =================
> 1.
> if (stmt->for_all_tables)
> {
> + /* Process EXCEPT table list */
> + if (relations != NIL)
> + {
> + Assert(rels != NIL);
> + PublicationAddTables(puboid, rels, true, NULL);
> + }
> +
> /*
> * Invalidate relcache so that publication info is rebuilt. Sequences
> * publication doesn't require invalidation, as replica identity
> CacheInvalidateRelcacheAll();
>
> Here, the relations listed in the except table list will be
> invalidated twice, once inside
> PublicationAddTables->publication_add_relation, and second time via
> CacheInvalidateRelcacheAll. Can we avoid that by adding a parameter to
> PublicationAddTables?

Fixed this

> 2.
> - root_relids = GetPublicationRelations(pubform->oid,
> - PUBLICATION_PART_ROOT);
> + root_relids = GetIncludedRelationsByPub(pubform->oid,
> + PUBLICATION_PART_ROOT);
>
> To follow the previous function naming pattern, can we rename
> GetIncludedRelationsByPub to GetIncludedPublicationRelations? If we
> agree to this then rename the excluded version of the function as
> well.

Modified

> 3.
> +/*
> + * Return the list of relation Oids for a publication.
> + *
> + * For a FOR TABLE publication, this returns the list of relations explicitly
> + * included in the publication.
> + *
> + * Publications declared with FOR ALL TABLES/SEQUENCES should use
> + * GetAllPublicationRelations() to obtain the complete set of tables/sequences
> + * covered by the publication.
> + */
> +List *
> +GetIncludedRelationsByPub(Oid pubid, PublicationPartOpt pub_partopt)
>
> This is equivalent to the existing function GetPublicationRelations()
> which has more precise comments atop. We can use the same comments
> unless there is any functionality difference.

Updated it

> 4.
> --- a/src/backend/catalog/pg_publication.c
> +++ b/src/backend/catalog/pg_publication.c
> @@ -29,6 +29,7 @@
> #include "catalog/pg_publication.h"
> #include "catalog/pg_publication_namespace.h"
> #include "catalog/pg_publication_rel.h"
> +#include "catalog/pg_subscription.h"
>
> It appears odd to include pg_subscription.h in the publication code.
> Is there a reason for the same? If not then avoid it.

This was required because we now started using GetPublicationsStr. I
have moved GetPublicationsStr to logical.c from pg_subscription which
is common to both pub and sub.

> Apart from above, a few cosmetic changes are attached.

Merged them.

The attached v47 version patch has the changes for the same.

Regards,
Vignesh

Attachment Content-Type Size
v47-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 81.7 KB
v47-0002-Support-specifying-partition-tables-in-EXCEPT-cl.patch application/octet-stream 41.2 KB

From: vignesh C <vignesh21(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-20 09:08:03
Message-ID: CALDaNm1x+ZrcVY3V37oPocSDeOcL05Wdr6MGrOdb_5WVrt+uWg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 19 Feb 2026 at 17:22, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Thu, Feb 19, 2026 at 10:13 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> >
> > Thanks for reviewing the patch. I have addressed the remaining
> > comments in the v46 patch..
> >
>
> Thanks. Please find a few comments:
>
> 1)
> pg_get_publication_effective_tables has
> + ereport(ERROR,
> + errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
> + errmsg("cannot use multiple publications with EXCEPT TABLE lists"),
> + errdetail("The following publications have exceptions: %s.",
> + pub_names->data));
>
> LoadPublications has:
> + ereport(ERROR,
> + errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
> + errmsg("cannot use multiple publications with EXCEPT TABLE lists"),
> + errdetail("Publications (%s) define EXCEPT TABLE clauses.",
> + pub_names_str.data));
>
> check_publications_except_list has:
> + ereport(ERROR,
> + errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
> + errmsg("cannot combine publications %s with EXCEPT TABLE clauses",
> pubnames.data));
>
> Can we make all three messages the same based on which format was
> decided earlier.
>
> 2)
> +/* Helper: Check syscache for prexcept flag */
> +bool
> +is_relid_excepted(Oid relid, Oid pubid)
>
> Can we move this function just before 'is_relid_or_ancestor_excepted'
> as they are related functions? Can we also change the comments as well
> similar to other functions?
>
> 3)
> I see that is_schema_published() is only needed by
> is_relid_or_ancestor_published() which calls is_relid_published()
> already. Shall we make logic of 'is_schema_published' as part of
> 'is_relid_published' itself i.e. we will consider relid published if
> it is published explicitly or as part of schema? Thoughts? This will
> help us to avoid having 'is_schema_published' function separately when
> its usage is quite limited.
>
> 4)
> pg_get_publication_effective_tables() has neighboring comments:
>
> + /* Check whether this publication defines any EXCEPT entries */
>
> + /*
> + * This publication includes all tables without except.
> + */
>
> We can choose the same comment style at both places. Please check the
> rest of the function too.

Thanks for the comments. These comments are addressed in the v47
version patch posted at [1].
[1] - https://www.postgresql.org/message-id/CALDaNm3X24fJznRUFh6NVhY1SDzgY9Aie1Ks%3Db6YqmAx-Z4H7Q%40mail.gmail.com

Regards,
Vignesh


From: Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-20 12:46:53
Message-ID: CAE9k0PkuG-gr8aBRs5jOUSqLkr_pdNmn0enBWjfp=RC8+De3PQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi,

On Fri, Feb 20, 2026 at 2:08 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Thu, 19 Feb 2026 at 16:06, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> > On Thu, Feb 19, 2026 at 10:13 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > >
> > > Thanks for reviewing the patch. I have addressed the remaining
> > > comments in the v46 patch..
> > >
> >
> > Can we think of some ideas to split this patch? One possibility is
> > that in the first patch we give an ERROR, if a non-root partitioned
> > table is present in EXCEPT Clause. I see that a lot of code is written
> > to handle partitions in EXCEPT clause. I feel such a split will make
> > code easier to review and validate.
>
> Split it accordingly.
>
> > Few other comments:
> > =================
> > 1.
> > if (stmt->for_all_tables)
> > {
> > + /* Process EXCEPT table list */
> > + if (relations != NIL)
> > + {
> > + Assert(rels != NIL);
> > + PublicationAddTables(puboid, rels, true, NULL);
> > + }
> > +
> > /*
> > * Invalidate relcache so that publication info is rebuilt. Sequences
> > * publication doesn't require invalidation, as replica identity
> > CacheInvalidateRelcacheAll();
> >
> > Here, the relations listed in the except table list will be
> > invalidated twice, once inside
> > PublicationAddTables->publication_add_relation, and second time via
> > CacheInvalidateRelcacheAll. Can we avoid that by adding a parameter to
> > PublicationAddTables?
>
> Fixed this
>
> > 2.
> > - root_relids = GetPublicationRelations(pubform->oid,
> > - PUBLICATION_PART_ROOT);
> > + root_relids = GetIncludedRelationsByPub(pubform->oid,
> > + PUBLICATION_PART_ROOT);
> >
> > To follow the previous function naming pattern, can we rename
> > GetIncludedRelationsByPub to GetIncludedPublicationRelations? If we
> > agree to this then rename the excluded version of the function as
> > well.
>
> Modified
>
> > 3.
> > +/*
> > + * Return the list of relation Oids for a publication.
> > + *
> > + * For a FOR TABLE publication, this returns the list of relations explicitly
> > + * included in the publication.
> > + *
> > + * Publications declared with FOR ALL TABLES/SEQUENCES should use
> > + * GetAllPublicationRelations() to obtain the complete set of tables/sequences
> > + * covered by the publication.
> > + */
> > +List *
> > +GetIncludedRelationsByPub(Oid pubid, PublicationPartOpt pub_partopt)
> >
> > This is equivalent to the existing function GetPublicationRelations()
> > which has more precise comments atop. We can use the same comments
> > unless there is any functionality difference.
>
> Updated it
>
> > 4.
> > --- a/src/backend/catalog/pg_publication.c
> > +++ b/src/backend/catalog/pg_publication.c
> > @@ -29,6 +29,7 @@
> > #include "catalog/pg_publication.h"
> > #include "catalog/pg_publication_namespace.h"
> > #include "catalog/pg_publication_rel.h"
> > +#include "catalog/pg_subscription.h"
> >
> > It appears odd to include pg_subscription.h in the publication code.
> > Is there a reason for the same? If not then avoid it.
>
> This was required because we now started using GetPublicationsStr. I
> have moved GetPublicationsStr to logical.c from pg_subscription which
> is common to both pub and sub.
>
> > Apart from above, a few cosmetic changes are attached.
>
> Merged them.
>
> The attached v47 version patch has the changes for the same.
>

SIGABRT with normal tables:
--------------------------------------

ashutosh(at)test=# select
pg_get_publication_effective_tables('t1'::regclass,
'{all_pub}'::text[]);
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.

Since the function is user-facing, I think we should have test coverage for it.

--
With Regards,
Ashutosh Sharma.


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-22 11:20:57
Message-ID: CAA4eK1KESu4=W6j4CQkKv5nzNJgtJyYBsg3E5K+LcwOr3t0WKw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Feb 20, 2026 at 2:08 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> The attached v47 version patch has the changes for the same.
>

Few comments on 0001:
1.
- * publish the child tables when the parent table is published.
+ * No need to invalidate the tables listed in the EXCEPT clause, because
+ * in that case all tables are invalidated anyway.

Give the reference of a function where all tables are invalidated.

2.
List *
-GetAllPublicationRelations(char relkind, bool pubviaroot)
+GetAllPublicationRelations(Publication *pub, char relkind)
...
+ if (relkind == RELKIND_RELATION)
+ exceptlist = GetExcludedPublicationTables(pubid, pubviaroot ?
+ PUBLICATION_PART_ROOT :
+ PUBLICATION_PART_LEAF);

Can you add a comment why the patch forms exceptlist only for RELKIND_RELATION?

3.
+ errmsg("cannot combine publications that define EXCEPT TABLE clauses"),
+ errdetail("The following publications define EXCEPT TABLE clauses: %s.",

Can you see a similar style of error message formation at any other
place in code? As per my understanding, in such cases, we display
required objects in errmsg itself. For example, "publications %s do
not exist on the publisher". Also, I think the errmsg should end with
a clause instead of caluses.

--
With Regards,
Amit Kapila.


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-23 06:07:35
Message-ID: CANhcyEUK_L+2Y+QX44Gkf+TCyz8YBCCT4zp1mVqizqYKkx4RVw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 20 Feb 2026 at 18:17, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com> wrote:
>
> Hi,
>
> On Fri, Feb 20, 2026 at 2:08 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > On Thu, 19 Feb 2026 at 16:06, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> > >
> > > On Thu, Feb 19, 2026 at 10:13 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > > >
> > > > Thanks for reviewing the patch. I have addressed the remaining
> > > > comments in the v46 patch..
> > > >
> > >
> > > Can we think of some ideas to split this patch? One possibility is
> > > that in the first patch we give an ERROR, if a non-root partitioned
> > > table is present in EXCEPT Clause. I see that a lot of code is written
> > > to handle partitions in EXCEPT clause. I feel such a split will make
> > > code easier to review and validate.
> >
> > Split it accordingly.
> >
> > > Few other comments:
> > > =================
> > > 1.
> > > if (stmt->for_all_tables)
> > > {
> > > + /* Process EXCEPT table list */
> > > + if (relations != NIL)
> > > + {
> > > + Assert(rels != NIL);
> > > + PublicationAddTables(puboid, rels, true, NULL);
> > > + }
> > > +
> > > /*
> > > * Invalidate relcache so that publication info is rebuilt. Sequences
> > > * publication doesn't require invalidation, as replica identity
> > > CacheInvalidateRelcacheAll();
> > >
> > > Here, the relations listed in the except table list will be
> > > invalidated twice, once inside
> > > PublicationAddTables->publication_add_relation, and second time via
> > > CacheInvalidateRelcacheAll. Can we avoid that by adding a parameter to
> > > PublicationAddTables?
> >
> > Fixed this
> >
> > > 2.
> > > - root_relids = GetPublicationRelations(pubform->oid,
> > > - PUBLICATION_PART_ROOT);
> > > + root_relids = GetIncludedRelationsByPub(pubform->oid,
> > > + PUBLICATION_PART_ROOT);
> > >
> > > To follow the previous function naming pattern, can we rename
> > > GetIncludedRelationsByPub to GetIncludedPublicationRelations? If we
> > > agree to this then rename the excluded version of the function as
> > > well.
> >
> > Modified
> >
> > > 3.
> > > +/*
> > > + * Return the list of relation Oids for a publication.
> > > + *
> > > + * For a FOR TABLE publication, this returns the list of relations explicitly
> > > + * included in the publication.
> > > + *
> > > + * Publications declared with FOR ALL TABLES/SEQUENCES should use
> > > + * GetAllPublicationRelations() to obtain the complete set of tables/sequences
> > > + * covered by the publication.
> > > + */
> > > +List *
> > > +GetIncludedRelationsByPub(Oid pubid, PublicationPartOpt pub_partopt)
> > >
> > > This is equivalent to the existing function GetPublicationRelations()
> > > which has more precise comments atop. We can use the same comments
> > > unless there is any functionality difference.
> >
> > Updated it
> >
> > > 4.
> > > --- a/src/backend/catalog/pg_publication.c
> > > +++ b/src/backend/catalog/pg_publication.c
> > > @@ -29,6 +29,7 @@
> > > #include "catalog/pg_publication.h"
> > > #include "catalog/pg_publication_namespace.h"
> > > #include "catalog/pg_publication_rel.h"
> > > +#include "catalog/pg_subscription.h"
> > >
> > > It appears odd to include pg_subscription.h in the publication code.
> > > Is there a reason for the same? If not then avoid it.
> >
> > This was required because we now started using GetPublicationsStr. I
> > have moved GetPublicationsStr to logical.c from pg_subscription which
> > is common to both pub and sub.
> >
> > > Apart from above, a few cosmetic changes are attached.
> >
> > Merged them.
> >
> > The attached v47 version patch has the changes for the same.
> >
>
> SIGABRT with normal tables:
> --------------------------------------
>
> ashutosh(at)test=# select
> pg_get_publication_effective_tables('t1'::regclass,
> '{all_pub}'::text[]);
> server closed the connection unexpectedly
> This probably means the server terminated abnormally
> before or while processing the request.
> The connection to the server was lost. Attempting reset: Failed.
>
> Since the function is user-facing, I think we should have test coverage for it.
>
Hi Ashutosh,
Thanks for reviewing the patch.

We have fixed this issue.
This function is not user facing. We have a similar function
'pg_get_publication_tables'. We do not have documentation and test
coverage for this function.
I think 'pg_get_publication_effective_tables' is a similar function,
so we should not add documentation or tests for it.

We have also addressed the comments in [1]. I have also done minor
code and comment modifications
I have also modified the error message as suggested by Shveta in [2].
Attached the latest v48 patch.

[1]: https://www.postgresql.org/message-id/CAE9k0P=SfawUYBoSmK9Zxwey774OJw5g4Gb7+fA3CQ22j83a7Q@mail.gmail.com
[2]: https://www.postgresql.org/message-id/CAJpy0uAHr8=YUKSyEBs8G4P0zGGb6mcUr-YJdB56tdYMF9yoKA@mail.gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v48-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 84.0 KB
v48-0002-Support-specifying-partition-tables-in-EXCEPT-cl.patch application/octet-stream 43.3 KB

From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-23 11:16:10
Message-ID: CAA4eK1+GuzCJZ80pAKZbqtMtr3RTPABtUQdvNvzn8RsCw+rQ6Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Feb 23, 2026 at 11:37 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> I have also modified the error message as suggested by Shveta in [2].
> Attached the latest v48 patch.
>

I see that the second patch (0002) brings complexity in the patch to
deal with following points: (a) The first complexity is if one of the
partitions is specified then how to compute the initial set of
relations to copy when pubviaroot is true. This is complex because we
need to exclude the partitions specified. (b) The other complexity is
combining Except list containing partitions and other publications
specifying partitions or partitioned tables both during replication
and probably during initial sync.

I think it will be better if for the first version, we allow only root
partitioned table to be specified in the Except Table list. This would
mean that if the user tries to attach that root partition table to
another root then we should give an error. If we go via this route, it
will be important to allow users to remove some tables from the Except
list, so we can provide Alter Publication <pub_name> Set Except Table
(table_names).

I think excluding specific partitions may also have some use cases but
adding additional complexity and maintenance effort is worth, if there
is a real field demand for such a feature.

Thoughts?

--
With Regards,
Amit Kapila.


From: Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-23 11:26:46
Message-ID: CAE9k0P=wzzOXykzgj-7Dw7E9r8k0PX633RY3TEVDpwLue004tg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi,

On Mon, Feb 23, 2026 at 11:37 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> On Fri, 20 Feb 2026 at 18:17, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com> wrote:
> >
> > Hi,
> >
> > On Fri, Feb 20, 2026 at 2:08 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > >
> > > On Thu, 19 Feb 2026 at 16:06, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> > > >
> > > > On Thu, Feb 19, 2026 at 10:13 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > > > >
> > > > > Thanks for reviewing the patch. I have addressed the remaining
> > > > > comments in the v46 patch..
> > > > >
> > > >
> > > > Can we think of some ideas to split this patch? One possibility is
> > > > that in the first patch we give an ERROR, if a non-root partitioned
> > > > table is present in EXCEPT Clause. I see that a lot of code is written
> > > > to handle partitions in EXCEPT clause. I feel such a split will make
> > > > code easier to review and validate.
> > >
> > > Split it accordingly.
> > >
> > > > Few other comments:
> > > > =================
> > > > 1.
> > > > if (stmt->for_all_tables)
> > > > {
> > > > + /* Process EXCEPT table list */
> > > > + if (relations != NIL)
> > > > + {
> > > > + Assert(rels != NIL);
> > > > + PublicationAddTables(puboid, rels, true, NULL);
> > > > + }
> > > > +
> > > > /*
> > > > * Invalidate relcache so that publication info is rebuilt. Sequences
> > > > * publication doesn't require invalidation, as replica identity
> > > > CacheInvalidateRelcacheAll();
> > > >
> > > > Here, the relations listed in the except table list will be
> > > > invalidated twice, once inside
> > > > PublicationAddTables->publication_add_relation, and second time via
> > > > CacheInvalidateRelcacheAll. Can we avoid that by adding a parameter to
> > > > PublicationAddTables?
> > >
> > > Fixed this
> > >
> > > > 2.
> > > > - root_relids = GetPublicationRelations(pubform->oid,
> > > > - PUBLICATION_PART_ROOT);
> > > > + root_relids = GetIncludedRelationsByPub(pubform->oid,
> > > > + PUBLICATION_PART_ROOT);
> > > >
> > > > To follow the previous function naming pattern, can we rename
> > > > GetIncludedRelationsByPub to GetIncludedPublicationRelations? If we
> > > > agree to this then rename the excluded version of the function as
> > > > well.
> > >
> > > Modified
> > >
> > > > 3.
> > > > +/*
> > > > + * Return the list of relation Oids for a publication.
> > > > + *
> > > > + * For a FOR TABLE publication, this returns the list of relations explicitly
> > > > + * included in the publication.
> > > > + *
> > > > + * Publications declared with FOR ALL TABLES/SEQUENCES should use
> > > > + * GetAllPublicationRelations() to obtain the complete set of tables/sequences
> > > > + * covered by the publication.
> > > > + */
> > > > +List *
> > > > +GetIncludedRelationsByPub(Oid pubid, PublicationPartOpt pub_partopt)
> > > >
> > > > This is equivalent to the existing function GetPublicationRelations()
> > > > which has more precise comments atop. We can use the same comments
> > > > unless there is any functionality difference.
> > >
> > > Updated it
> > >
> > > > 4.
> > > > --- a/src/backend/catalog/pg_publication.c
> > > > +++ b/src/backend/catalog/pg_publication.c
> > > > @@ -29,6 +29,7 @@
> > > > #include "catalog/pg_publication.h"
> > > > #include "catalog/pg_publication_namespace.h"
> > > > #include "catalog/pg_publication_rel.h"
> > > > +#include "catalog/pg_subscription.h"
> > > >
> > > > It appears odd to include pg_subscription.h in the publication code.
> > > > Is there a reason for the same? If not then avoid it.
> > >
> > > This was required because we now started using GetPublicationsStr. I
> > > have moved GetPublicationsStr to logical.c from pg_subscription which
> > > is common to both pub and sub.
> > >
> > > > Apart from above, a few cosmetic changes are attached.
> > >
> > > Merged them.
> > >
> > > The attached v47 version patch has the changes for the same.
> > >
> >
> > SIGABRT with normal tables:
> > --------------------------------------
> >
> > ashutosh(at)test=# select
> > pg_get_publication_effective_tables('t1'::regclass,
> > '{all_pub}'::text[]);
> > server closed the connection unexpectedly
> > This probably means the server terminated abnormally
> > before or while processing the request.
> > The connection to the server was lost. Attempting reset: Failed.
> >
> > Since the function is user-facing, I think we should have test coverage for it.
> >
> Hi Ashutosh,
> Thanks for reviewing the patch.
>
> We have fixed this issue.
> This function is not user facing. We have a similar function
> 'pg_get_publication_tables'. We do not have documentation and test
> coverage for this function.
> I think 'pg_get_publication_effective_tables' is a similar function,
> so we should not add documentation or tests for it.
>
> We have also addressed the comments in [1]. I have also done minor
> code and comment modifications
> I have also modified the error message as suggested by Shveta in [2].
> Attached the latest v48 patch.
>
> [1]: https://www.postgresql.org/message-id/CAE9k0P=SfawUYBoSmK9Zxwey774OJw5g4Gb7+fA3CQ22j83a7Q@mail.gmail.com
> [2]: https://www.postgresql.org/message-id/CAJpy0uAHr8=YUKSyEBs8G4P0zGGb6mcUr-YJdB56tdYMF9yoKA@mail.gmail.com
>

Thanks for the fix. A couple of quick observations:

+ list_free_deep(pubnames_with_except);
+ pfree(except_publications);

The memory cleanup is inconsistent - some lists are freed with
list_free_deep while others use a plain pfree. Could you clarify the
reasoning, or make this consistent?
--

+ /* walrcv_clear_result(res); */
+ ExecDropSingleTupleTableSlot(slot);

walrcv_clear_result(res) appears to have been commented out — was this
intentional? If so, what's the reason?

--

There are multiple places (at least 3) where we have multi-pub
conflict checks to ensure not more than one pub with except clause
exist, it doesn't seem like we can make them common, but since they
are somewhat duplicate its possible that when we make changes at one
place, some other place where the similar change is required gets
missed. So if possible (and if it makes sense to you) I think it would
be good to have some kind of comments saying "this is one of N places
that enforces this constraint, see also X and Y.

--
With Regards,
Ashutosh Sharma.


From: "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Skipping schema changes in publication
Date: 2026-02-25 06:33:10
Message-ID: TY4PR01MB169075BC5D58A363746C842569475A@TY4PR01MB16907.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Monday, February 23, 2026 7:16 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Mon, Feb 23, 2026 at 11:37 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
> wrote:
> >
> > I have also modified the error message as suggested by Shveta in [2].
> > Attached the latest v48 patch.
> >
>
> I see that the second patch (0002) brings complexity in the patch to
> deal with following points: (a) The first complexity is if one of the
> partitions is specified then how to compute the initial set of
> relations to copy when pubviaroot is true. This is complex because we
> need to exclude the partitions specified. (b) The other complexity is
> combining Except list containing partitions and other publications
> specifying partitions or partitioned tables both during replication
> and probably during initial sync.
>
> I think it will be better if for the first version, we allow only root
> partitioned table to be specified in the Except Table list. This would
> mean that if the user tries to attach that root partition table to
> another root then we should give an error. If we go via this route, it
> will be important to allow users to remove some tables from the Except
> list, so we can provide Alter Publication <pub_name> Set Except Table
> (table_names).
>
> I think excluding specific partitions may also have some use cases but
> adding additional complexity and maintenance effort is worth, if there
> is a real field demand for such a feature.

I agree that supporting exclusion of a partition while publishing its
parent would add significant complexity and could be achieved independently.

Another perspective I saw this is that the ability to exclude only a specific
partition from a partition tree while continuing to publish changes via the root
table introduces an entirely new mode that users couldn't achieve before this
patch. Previously, once a parent table was added to a publication, all its
partitions were published regardless of their schema, so users cannot exclude a
partition either via FOR TABLE or FOR TABLES IN SCHEMA. Therefore, disallowing
partition exclusion doesn't remove any existing capability, which seems
acceptable.

The original use case in this thread also doesn't mention partitioned tables, so
I think EXCEPT TABLE provides value even without implementing this new ability.
Given the amount of code required to support partition exclusion, it makes sense
to me to treat this as an independent feature that can be pursued later based
on user feedback.

Best Regards,
Hou zj


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-25 07:04:41
Message-ID: CALDaNm3jjGo2uUpxprEmZCsTbk_HnuPhVu_cHh=6CeQTWCyuEw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 23 Feb 2026 at 16:46, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Mon, Feb 23, 2026 at 11:37 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > I have also modified the error message as suggested by Shveta in [2].
> > Attached the latest v48 patch.
> >
>
> I see that the second patch (0002) brings complexity in the patch to
> deal with following points: (a) The first complexity is if one of the
> partitions is specified then how to compute the initial set of
> relations to copy when pubviaroot is true. This is complex because we
> need to exclude the partitions specified. (b) The other complexity is
> combining Except list containing partitions and other publications
> specifying partitions or partitioned tables both during replication
> and probably during initial sync.
>
> I think it will be better if for the first version, we allow only root
> partitioned table to be specified in the Except Table list. This would
> mean that if the user tries to attach that root partition table to
> another root then we should give an error. If we go via this route, it
> will be important to allow users to remove some tables from the Except
> list, so we can provide Alter Publication <pub_name> Set Except Table
> (table_names).

The attached patch has the changes for the same i.e.a) Raises an error
when attempting to attach a partition to a root partitioned table if
that table is referenced in an EXCEPT clause of any publication. b)
Adds support for dropping excluded tables using: ALTER PUBLICATION ...
DROP EXCEPT TABLE. c) Adds support for replacing the exclusion list
using ALTER PUBLICATION ... SET EXCEPT TABLE.
The changes related to DROP EXCEPT TABLE and SET EXCEPT TABLE have
been kept separately into patch 0002 for easier review.

The comments from [1] are also addressed in the attached patch.
[1] - https://www.postgresql.org/message-id/CAA4eK1KESu4%3DW6j4CQkKv5nzNJgtJyYBsg3E5K%2BLcwOr3t0WKw%40mail.gmail.com

Regards,
Vignesh

Attachment Content-Type Size
v49-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 85.8 KB
v49-0002-Support-DROP-and-SET-EXCEPT-TABLE-in-ALTER-PUBLI.patch application/octet-stream 25.6 KB

From: Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-25 08:22:37
Message-ID: 0DDF38E7-3033-47E1-98C1-49A1378526B3@gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

> On Feb 25, 2026, at 15:04, vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Mon, 23 Feb 2026 at 16:46, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>>
>> On Mon, Feb 23, 2026 at 11:37 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>>>
>>> I have also modified the error message as suggested by Shveta in [2].
>>> Attached the latest v48 patch.
>>>
>>
>> I see that the second patch (0002) brings complexity in the patch to
>> deal with following points: (a) The first complexity is if one of the
>> partitions is specified then how to compute the initial set of
>> relations to copy when pubviaroot is true. This is complex because we
>> need to exclude the partitions specified. (b) The other complexity is
>> combining Except list containing partitions and other publications
>> specifying partitions or partitioned tables both during replication
>> and probably during initial sync.
>>
>> I think it will be better if for the first version, we allow only root
>> partitioned table to be specified in the Except Table list. This would
>> mean that if the user tries to attach that root partition table to
>> another root then we should give an error. If we go via this route, it
>> will be important to allow users to remove some tables from the Except
>> list, so we can provide Alter Publication <pub_name> Set Except Table
>> (table_names).
>
> The attached patch has the changes for the same i.e.a) Raises an error
> when attempting to attach a partition to a root partitioned table if
> that table is referenced in an EXCEPT clause of any publication. b)
> Adds support for dropping excluded tables using: ALTER PUBLICATION ...
> DROP EXCEPT TABLE. c) Adds support for replacing the exclusion list
> using ALTER PUBLICATION ... SET EXCEPT TABLE.
> The changes related to DROP EXCEPT TABLE and SET EXCEPT TABLE have
> been kept separately into patch 0002 for easier review.
>
> The comments from [1] are also addressed in the attached patch.
> [1] - https://www.postgresql.org/message-id/CAA4eK1KESu4%3DW6j4CQkKv5nzNJgtJyYBsg3E5K%2BLcwOr3t0WKw%40mail.gmail.com
>
> Regards,
> Vignesh
> <v49-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch><v49-0002-Support-DROP-and-SET-EXCEPT-TABLE-in-ALTER-PUBLI.patch>

I quickly went through the code change and haven’t actually played the new feature yet. A few small comments:

1 - 0001 - subscriptioncmds.c
```
+ GetPublicationsStr(except_publications, &pubnames, false);
+
+ pfree(except_publications);
```

except_publications is a list, so we should use list_free(except_publications) instead of pfree().

2 - 0002
```
+ will be removed. The <literal>ADD</literal> clauses will add one or more
+ tables/schemas from the publication. The <literal>DROP</literal> clauses
```

I guess “from the publication” should be “to the publication”.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-25 10:31:34
Message-ID: CAJpy0uAoKeDCc8PLc+f5Kjnd4Jt1KkCXK2bgKMWxCXSFu-jy7Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Feb 23, 2026 at 4:46 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Mon, Feb 23, 2026 at 11:37 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > I have also modified the error message as suggested by Shveta in [2].
> > Attached the latest v48 patch.
> >
>
> I see that the second patch (0002) brings complexity in the patch to
> deal with following points: (a) The first complexity is if one of the
> partitions is specified then how to compute the initial set of
> relations to copy when pubviaroot is true. This is complex because we
> need to exclude the partitions specified. (b) The other complexity is
> combining Except list containing partitions and other publications
> specifying partitions or partitioned tables both during replication
> and probably during initial sync.
>
> I think it will be better if for the first version, we allow only root
> partitioned table to be specified in the Except Table list. This would
> mean that if the user tries to attach that root partition table to
> another root then we should give an error. If we go via this route, it
> will be important to allow users to remove some tables from the Except
> list, so we can provide Alter Publication <pub_name> Set Except Table
> (table_names).
>
> I think excluding specific partitions may also have some use cases but
> adding additional complexity and maintenance effort is worth, if there
> is a real field demand for such a feature.
>
> Thoughts?
>

I fully agree. The additional complexity does not appear to be worth
the value right now, unless we receive meaningful user feedback that
justifies implementing it.

Thanks Vignesh for the patch supporting this approach. Please find a
few comments on v49-001:

1)
+ in <literal>EXCEPT TABLE</literal>. Doing so excludes the root table and
+ all of its partitions from replication, regardless of the value of
+ <literal>publish_via_partition_root</literal>. The optional
+ <literal>*</literal> has no effect for partitioned tables.
+ </para>

a)
I feel it is not needed to mention 'regardless of
publish_via_partition_root' as generally that never decides what is
included and what is not. Same is the case here.

b)
We shall mention both ONLY and *. Infact it is 'ONLY' which has no
effect. * is the default in this case. But still to make it a more
generic statement, we shall mention both for partitioned tables.

2)
+ <para>
+ Create a publication that publishes all sequences for synchronization, and
+ all changes in all tables except <structname>users</structname> and
+ <structname>departments</structname>:
+<programlisting>
+CREATE PUBLICATION all_sequences_tables_except FOR ALL SEQUENCES, ALL
TABLES EXCEPT (users, departments);

If I run the command given in example, it asserts.

TRAP: failed Assert("!stmt->for_all_sequences"), File:
"publicationcmds.c", Line: 942, PID: 70620
postgres: shveta postgres [local] CREATE
PUBLICATION(ExceptionalCondition+0xbb)[0x611280ed8c48]

3)
-check_publication_add_relation(Relation targetrel)
+check_publication_add_relation(Relation targetrel, PublicationRelInfo *pri)

We can avoid passing 'targetrel' now. PublicationRelInfo has that info inside.

4)
postgres=# create publication pub2 for all tables except (tab_part_1);
ERROR: partition "tab_part_1" cannot be excluded using EXCEPT TABLE

Other errors are in active voice (eg: cannot use system column \"%s\"
in publication column list, cannot use publication EXCEPT clause for
relation \"%s\).

Shall we also keep this the same way? I think we can mimic the error
for tmp and unlogged tables which is:

postgres=# create publication pub2 for all tables except (tmp1);
ERROR: cannot use publication EXCEPT clause for relation "tmp1"
DETAIL: This operation is not supported for temporary tables.

We can convert concerned one to:

postgres=# create publication pub2 for all tables except (tab_part_1);
ERROR: cannot use publication EXCEPT clause for partition "tab_part_1"
DETAIL: This operation is not supported for individual partitions.

5)
+ if (pub->alltables && pri->except && targetrel->rd_rel->relispartition)
+ ereport(ERROR,
+ errmsg("partition \"%s\" cannot be excluded using EXCEPT TABLE",
+ RelationGetRelationName(targetrel)));
+
+ check_publication_add_relation(targetrel, pri);

I feel we can push the partition check and error to
check_publication_add_relation() itself. If we do so, we can retain
the exactly same errormsg for parition case as well which is:
errormsg = gettext_noop("cannot use publication EXCEPT clause for
relation \"%s\"");

And we can just change DETAIL as suggested in pt 4.

6)
+++ b/src/backend/catalog/pg_subscription.c
-/*
- * Add a comma-separated list of publication names to the 'dest' string.
- */
-void
-GetPublicationsStr(List *publications, StringInfo dest, bool quote_literal)
-{

Do we still need to move GetPublicationsStr() to logical.c? I see the
only extra call is now in pgoutput.c which already includes
catalog/pg_subscription.h
~~

Reviewing further.

thanks
Shveta


From: Andrei Lepikhov <lepihov(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-25 13:39:18
Message-ID: CAMMNXX=nFgcPc5_zes3MU7kwuCx8xsuBDHVBYF6LCsT1kHU_Nw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On 25/2/26 08:04, vignesh C wrote:
> On Mon, 23 Feb 2026 at 16:46, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> The attached patch has the changes for the same i.e.a) Raises an error
> when attempting to attach a partition to a root partitioned table if
> that table is referenced in an EXCEPT clause of any publication. b)
> Adds support for dropping excluded tables using: ALTER PUBLICATION ...
> DROP EXCEPT TABLE. c) Adds support for replacing the exclusion list
> using ALTER PUBLICATION ... SET EXCEPT TABLE.
> The changes related to DROP EXCEPT TABLE and SET EXCEPT TABLE have
> been kept separately into patch 0002 for easier review.

I discovered this patch, maybe not deeply enough. But one question raised.

I usually work with multiple tables (sometimes hundreds, if not
thousands). EXCEPT clause might be quite rare. Some commands want to
extract only excepted tables from the publication using the following
pattern:

'SELECT ... FROM pg_publication_rel WHERE prpubid = <X> AND pr.prexcept'

- check_publications_except_list()
- describePublications()
- getPublications()
- LoadPublications() / publication_has_any_except_table()

That means pass through all the publication tables to find (usually)
nothing. It might be a costly operation, especially in the
LoadPublications routine. Maybe slightly change index
pg_publication_rel_prpubid_index a little and add 'prexcept' as a second
column there? It might avoid performance issues that may arise during
the upgrade.

--
regards, Andrei Lepikhov,
pgEdge


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-25 17:13:10
Message-ID: CANhcyEUur4fH9cB0NgiBHcV7Q0aoL+cC8qB2DCAJVcsdOJ+nqg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 25 Feb 2026 at 16:01, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Mon, Feb 23, 2026 at 4:46 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> > On Mon, Feb 23, 2026 at 11:37 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > >
> > > I have also modified the error message as suggested by Shveta in [2].
> > > Attached the latest v48 patch.
> > >
> >
> > I see that the second patch (0002) brings complexity in the patch to
> > deal with following points: (a) The first complexity is if one of the
> > partitions is specified then how to compute the initial set of
> > relations to copy when pubviaroot is true. This is complex because we
> > need to exclude the partitions specified. (b) The other complexity is
> > combining Except list containing partitions and other publications
> > specifying partitions or partitioned tables both during replication
> > and probably during initial sync.
> >
> > I think it will be better if for the first version, we allow only root
> > partitioned table to be specified in the Except Table list. This would
> > mean that if the user tries to attach that root partition table to
> > another root then we should give an error. If we go via this route, it
> > will be important to allow users to remove some tables from the Except
> > list, so we can provide Alter Publication <pub_name> Set Except Table
> > (table_names).
> >
> > I think excluding specific partitions may also have some use cases but
> > adding additional complexity and maintenance effort is worth, if there
> > is a real field demand for such a feature.
> >
> > Thoughts?
> >
>
> I fully agree. The additional complexity does not appear to be worth
> the value right now, unless we receive meaningful user feedback that
> justifies implementing it.
>
> Thanks Vignesh for the patch supporting this approach. Please find a
> few comments on v49-001:
>
> 1)
> + in <literal>EXCEPT TABLE</literal>. Doing so excludes the root table and
> + all of its partitions from replication, regardless of the value of
> + <literal>publish_via_partition_root</literal>. The optional
> + <literal>*</literal> has no effect for partitioned tables.
> + </para>
>
> a)
> I feel it is not needed to mention 'regardless of
> publish_via_partition_root' as generally that never decides what is
> included and what is not. Same is the case here.
>
> b)
> We shall mention both ONLY and *. Infact it is 'ONLY' which has no
> effect. * is the default in this case. But still to make it a more
> generic statement, we shall mention both for partitioned tables.
>
> 2)
> + <para>
> + Create a publication that publishes all sequences for synchronization, and
> + all changes in all tables except <structname>users</structname> and
> + <structname>departments</structname>:
> +<programlisting>
> +CREATE PUBLICATION all_sequences_tables_except FOR ALL SEQUENCES, ALL
> TABLES EXCEPT (users, departments);
>
> If I run the command given in example, it asserts.
>
> TRAP: failed Assert("!stmt->for_all_sequences"), File:
> "publicationcmds.c", Line: 942, PID: 70620
> postgres: shveta postgres [local] CREATE
> PUBLICATION(ExceptionalCondition+0xbb)[0x611280ed8c48]
>
> 3)
> -check_publication_add_relation(Relation targetrel)
> +check_publication_add_relation(Relation targetrel, PublicationRelInfo *pri)
>
> We can avoid passing 'targetrel' now. PublicationRelInfo has that info inside.
>
> 4)
> postgres=# create publication pub2 for all tables except (tab_part_1);
> ERROR: partition "tab_part_1" cannot be excluded using EXCEPT TABLE
>
> Other errors are in active voice (eg: cannot use system column \"%s\"
> in publication column list, cannot use publication EXCEPT clause for
> relation \"%s\).
>
> Shall we also keep this the same way? I think we can mimic the error
> for tmp and unlogged tables which is:
>
> postgres=# create publication pub2 for all tables except (tmp1);
> ERROR: cannot use publication EXCEPT clause for relation "tmp1"
> DETAIL: This operation is not supported for temporary tables.
>
> We can convert concerned one to:
>
> postgres=# create publication pub2 for all tables except (tab_part_1);
> ERROR: cannot use publication EXCEPT clause for partition "tab_part_1"
> DETAIL: This operation is not supported for individual partitions.
>
>
> 5)
> + if (pub->alltables && pri->except && targetrel->rd_rel->relispartition)
> + ereport(ERROR,
> + errmsg("partition \"%s\" cannot be excluded using EXCEPT TABLE",
> + RelationGetRelationName(targetrel)));
> +
> + check_publication_add_relation(targetrel, pri);
>
> I feel we can push the partition check and error to
> check_publication_add_relation() itself. If we do so, we can retain
> the exactly same errormsg for parition case as well which is:
> errormsg = gettext_noop("cannot use publication EXCEPT clause for
> relation \"%s\"");
>
> And we can just change DETAIL as suggested in pt 4.
>
> 6)
> +++ b/src/backend/catalog/pg_subscription.c
> -/*
> - * Add a comma-separated list of publication names to the 'dest' string.
> - */
> -void
> -GetPublicationsStr(List *publications, StringInfo dest, bool quote_literal)
> -{
>
> Do we still need to move GetPublicationsStr() to logical.c? I see the
> only extra call is now in pgoutput.c which already includes
> catalog/pg_subscription.h
> ~~
Hi Shveta, Ashutosh, Chao-san,

Thanks for reviewing the patch.
I have addressed the above comments and the comments in [1] and [2].
Attached is the latest v50 version.

I have also split the patch 0002 to 0002 and 0003
0001 - Support CREATE PUBLICATION ... EXCEPT TABLE syntax
0002 - Support ALTER PUBLICATION ... SET EXCEPT TABLE .. syntax
0003 - Support ALTER PUBLICATION ... DROP EXCEPT TABLE .. syntax

[1]: https://www.postgresql.org/message-id/CAE9k0P=wzzOXykzgj-7Dw7E9r8k0PX633RY3TEVDpwLue004tg@mail.gmail.com
[2]: https://www.postgresql.org/message-id/0DDF38E7-3033-47E1-98C1-49A1378526B3@gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v50-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 83.1 KB
v50-0003-Support-DROP-EXCEPT-TABLE-in-ALTER-PUBLICATION.patch application/octet-stream 10.4 KB
v50-0002-Support-SET-EXCEPT-TABLE-in-ALTER-PUBLICATION.patch application/octet-stream 23.0 KB

From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Andrei Lepikhov <lepihov(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-26 02:56:38
Message-ID: CAA4eK1Lxp8_HJv3sZNPx-oM1CUUi5p2UYa1PoVTe-QOEEp+3Ww@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Feb 25, 2026 at 7:09 PM Andrei Lepikhov <lepihov(at)gmail(dot)com> wrote:
>
> On 25/2/26 08:04, vignesh C wrote:
> > On Mon, 23 Feb 2026 at 16:46, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> > The attached patch has the changes for the same i.e.a) Raises an error
> > when attempting to attach a partition to a root partitioned table if
> > that table is referenced in an EXCEPT clause of any publication. b)
> > Adds support for dropping excluded tables using: ALTER PUBLICATION ...
> > DROP EXCEPT TABLE. c) Adds support for replacing the exclusion list
> > using ALTER PUBLICATION ... SET EXCEPT TABLE.
> > The changes related to DROP EXCEPT TABLE and SET EXCEPT TABLE have
> > been kept separately into patch 0002 for easier review.
>
> I discovered this patch, maybe not deeply enough. But one question raised.
>
> I usually work with multiple tables (sometimes hundreds, if not
> thousands). EXCEPT clause might be quite rare.
>

I think it will be useful for users using ALL TABLES IN SCHEMA and ALL
TABLES publications where they don't want to replicate the entire
schema or database.

> Some commands want to
> extract only excepted tables from the publication using the following
> pattern:
>
> 'SELECT ... FROM pg_publication_rel WHERE prpubid = <X> AND pr.prexcept'
>
> - check_publications_except_list()
> - describePublications()
> - getPublications()
> - LoadPublications() / publication_has_any_except_table()
>
> That means pass through all the publication tables to find (usually)
> nothing. It might be a costly operation, especially in the
> LoadPublications routine. Maybe slightly change index
> pg_publication_rel_prpubid_index a little and add 'prexcept' as a second
> column there? It might avoid performance issues that may arise during
> the upgrade.
>

Why do you think it can hurt when used via LoadPublications? That is
done only one time when the first relsync entry is built, after that
it is reused unless there is some DDL on the publication. Also, we are
not expecting thousands of tables in the except list for a
publication. So can traversing that few entries and that too first
time when cache is built can impact performance in a noticeable way?
If you think so, we can modify the index as you are suggesting but I
was thinking if the number of entries is not large per-publication
then why to permanently increase the size of the index.

--
With Regards,
Amit Kapila.


From: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-26 04:14:47
Message-ID: CAFiTN-tYF31VaceBzoWHqXz-7osj3_fBZBqEk+8N_2iJRbgP1Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Feb 25, 2026 at 4:01 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Mon, Feb 23, 2026 at 4:46 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> > On Mon, Feb 23, 2026 at 11:37 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > >
> > > I have also modified the error message as suggested by Shveta in [2].
> > > Attached the latest v48 patch.
> > >
> >
> > I see that the second patch (0002) brings complexity in the patch to
> > deal with following points: (a) The first complexity is if one of the
> > partitions is specified then how to compute the initial set of
> > relations to copy when pubviaroot is true. This is complex because we
> > need to exclude the partitions specified. (b) The other complexity is
> > combining Except list containing partitions and other publications
> > specifying partitions or partitioned tables both during replication
> > and probably during initial sync.
> >
> > I think it will be better if for the first version, we allow only root
> > partitioned table to be specified in the Except Table list. This would
> > mean that if the user tries to attach that root partition table to
> > another root then we should give an error. If we go via this route, it
> > will be important to allow users to remove some tables from the Except
> > list, so we can provide Alter Publication <pub_name> Set Except Table
> > (table_names).
> >
> > I think excluding specific partitions may also have some use cases but
> > adding additional complexity and maintenance effort is worth, if there
> > is a real field demand for such a feature.
> >
> > Thoughts?
> >
>
> I fully agree. The additional complexity does not appear to be worth
> the value right now, unless we receive meaningful user feedback that
> justifies implementing it.
>

I’m on the same page. The benefit probably doesn't justify the added
complexity and the long-term code maintenance overhead this would
introduce.

--
Regards,
Dilip Kumar
Google


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Andrei Lepikhov <lepihov(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-26 04:56:46
Message-ID: CAJpy0uBeNJb0iw89ASvMpkg-42nhffpsjOK7EMK=F3rLEdaXJg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Feb 26, 2026 at 8:26 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Wed, Feb 25, 2026 at 7:09 PM Andrei Lepikhov <lepihov(at)gmail(dot)com> wrote:
> >
> > On 25/2/26 08:04, vignesh C wrote:
> > > On Mon, 23 Feb 2026 at 16:46, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> > > The attached patch has the changes for the same i.e.a) Raises an error
> > > when attempting to attach a partition to a root partitioned table if
> > > that table is referenced in an EXCEPT clause of any publication. b)
> > > Adds support for dropping excluded tables using: ALTER PUBLICATION ...
> > > DROP EXCEPT TABLE. c) Adds support for replacing the exclusion list
> > > using ALTER PUBLICATION ... SET EXCEPT TABLE.
> > > The changes related to DROP EXCEPT TABLE and SET EXCEPT TABLE have
> > > been kept separately into patch 0002 for easier review.
> >
> > I discovered this patch, maybe not deeply enough. But one question raised.
> >
> > I usually work with multiple tables (sometimes hundreds, if not
> > thousands). EXCEPT clause might be quite rare.
> >
>
> I think it will be useful for users using ALL TABLES IN SCHEMA and ALL
> TABLES publications where they don't want to replicate the entire
> schema or database.
>
> > Some commands want to
> > extract only excepted tables from the publication using the following
> > pattern:
> >
> > 'SELECT ... FROM pg_publication_rel WHERE prpubid = <X> AND pr.prexcept'
> >

I agree with Amit's point. I would like to add one more point here.

pg_publication_rel will not contain any regular table entries for a
given pubid when EXCEPT is used. Except is for ALL-TABLES pub alone
for which base-table entries are stored in pg_publication_tables. Thus
for an EXCEPT pub, anything we fetch from pg_publication_rel using the
pubid index
would necessarily be an EXCEPT entry. The scenario where we retrieve,
say, 1000 table entries for a pubid and only 1–2 of them are EXCEPT
entries will not occur. Given this, the need for a composite index on
(prpubid, prexcept) does not appear to be strongly justified to me.
Please ignore my comment if you are already aware of this situation.

thanks
Shveta


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Andrei Lepikhov <lepihov(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-26 06:08:42
Message-ID: CAJpy0uAfxYAWi_Gr4B_7LFmimwN_BJ9KYeAzkgMjWVy4ZAm+8Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Feb 26, 2026 at 10:26 AM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Thu, Feb 26, 2026 at 8:26 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> > On Wed, Feb 25, 2026 at 7:09 PM Andrei Lepikhov <lepihov(at)gmail(dot)com> wrote:
> > >
> > > On 25/2/26 08:04, vignesh C wrote:
> > > > On Mon, 23 Feb 2026 at 16:46, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> > > > The attached patch has the changes for the same i.e.a) Raises an error
> > > > when attempting to attach a partition to a root partitioned table if
> > > > that table is referenced in an EXCEPT clause of any publication. b)
> > > > Adds support for dropping excluded tables using: ALTER PUBLICATION ...
> > > > DROP EXCEPT TABLE. c) Adds support for replacing the exclusion list
> > > > using ALTER PUBLICATION ... SET EXCEPT TABLE.
> > > > The changes related to DROP EXCEPT TABLE and SET EXCEPT TABLE have
> > > > been kept separately into patch 0002 for easier review.
> > >
> > > I discovered this patch, maybe not deeply enough. But one question raised.
> > >
> > > I usually work with multiple tables (sometimes hundreds, if not
> > > thousands). EXCEPT clause might be quite rare.
> > >
> >
> > I think it will be useful for users using ALL TABLES IN SCHEMA and ALL
> > TABLES publications where they don't want to replicate the entire
> > schema or database.
> >
> > > Some commands want to
> > > extract only excepted tables from the publication using the following
> > > pattern:
> > >
> > > 'SELECT ... FROM pg_publication_rel WHERE prpubid = <X> AND pr.prexcept'
> > >
>
> I agree with Amit's point. I would like to add one more point here.
>
> pg_publication_rel will not contain any regular table entries for a
> given pubid when EXCEPT is used. Except is for ALL-TABLES pub alone
> for which base-table entries are stored in pg_publication_tables.

One correction here: Except is for ALL-TABLES pub alone for which
base-table entries are "fetched" from pg_publication_tables view
instead of catalog pg_publication_rel.

> Thus
> for an EXCEPT pub, anything we fetch from pg_publication_rel using the
> pubid index
> would necessarily be an EXCEPT entry. The scenario where we retrieve,
> say, 1000 table entries for a pubid and only 1–2 of them are EXCEPT
> entries will not occur. Given this, the need for a composite index on
> (prpubid, prexcept) does not appear to be strongly justified to me.
> Please ignore my comment if you are already aware of this situation.
>
> thanks
> Shveta


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-26 06:12:01
Message-ID: CAJpy0uD4Hhx3aOgjR_AEk++gY0vknsnNd6+qdLPPS3QoS7y2uw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Feb 25, 2026 at 10:43 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> Hi Shveta, Ashutosh, Chao-san,
>
> Thanks for reviewing the patch.
> I have addressed the above comments and the comments in [1] and [2].
> Attached is the latest v50 version.
>

Thank You Shlok. Please find a few comments on v50-001.

1)
-check_publication_add_relation(Relation targetrel)
+check_publication_add_relation(PublicationRelInfo *pri, bool puballtables)

Why do we need argument puballtables? I think we can give partition
related error even without checking 'puballtables', like we are giving
for temp and unlogged table error in EXCEPT list without checking
puballtables. Or let me know if I am missing the point here?

2)
publication_has_any_except_table(): Shall we optimize it:
a) if it is not all-table pub, return false there itself.
b) if it is all table, proceed with fetching tuples. At first tuple we
can break the loop irrespective of check 'pubrel->prexcept', as there
is no other feasibility. But we shall Assert (pubrel->prexcept) .
Thoughts?

3)
+ /* Process EXCEPT table list */
+ if (relations != NIL)
+ {
+ Assert(rels != NIL);
+ PublicationAddTables(puboid, rels, true, NULL);
+ }

We can remove Assert from here too as we don't have it in the later
part of code where we use rels. I feel it is okay to not have Assert
as we are fetching rels in nearby logic only.

4)
CheckPublicationsForExceptClauses() frees except_publications list
only in case where it has to emit ERROR. It does not free it for a
case where there is only one element in it. Also one of the callers
free the list while another does not. Is it by design? Shall we make
the behaviour more consistent for callers?

5)
postgres=# ALTER TABLE tab_top_root ATTACH PARTITION tab_root FOR
VALUES FROM (0) TO (2000);
ERROR: cannot attach table "tab_root" as partition because it is
referenced in a publication EXCEPT clause
DETAIL: Tables excluded from publications cannot be attached as partitions.
HINT: Remove the table from the publication EXCEPT list before attaching it.

a) It will be good to list pubnames here for which we are referring EXCEPT list.

b) Also I feel, instead of emphasising on 'cannot attach table as
partition' in DETAIL, we should emphasise on 'partition cannot be part
of EXCEPT'. How about?
DETAIL: The publication EXCEPT clause cannot contain tables that are partitions.

6)
I see a few error-messages mentioning EXCEPT 'clause' while others
mention EXCEPT 'list'. We can make the wording the same throughout.

7)
+ /*
+ * Check that the table is not part of any publication when changing to
+ * UNLOGGED, as UNLOGGED tables can't be published.
+ */
+ GetRelationPublications(RelationGetRelid(attachrel), NULL, &exceptpuboids);
+ if (exceptpuboids != NIL)
+ ereport(ERROR,
+ errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot attach table \"%s\" as partition because it is
referenced in a publication EXCEPT clause",

Comments need to be corrected. Copy/paste issue.

8)
tablesync.c:
+#include "replication/logical.h"

This inclusion is not needed now.

Reviewing further.

thanks
Shveta


From: Andrei Lepikhov <lepihov(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-26 09:38:33
Message-ID: 3f2555bf-8deb-4164-a888-e7a52447c79b@gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On 26/2/26 05:56, shveta malik wrote:
> On Thu, Feb 26, 2026 at 8:26 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>> On Wed, Feb 25, 2026 at 7:09 PM Andrei Lepikhov <lepihov(at)gmail(dot)com> wrote:
> pg_publication_rel will not contain any regular table entries for a
> given pubid when EXCEPT is used. Except is for ALL-TABLES pub alone
> for which base-table entries are stored in pg_publication_tables. Thus
> for an EXCEPT pub, anything we fetch from pg_publication_rel using the
> pubid index
> would necessarily be an EXCEPT entry. The scenario where we retrieve,
> say, 1000 table entries for a pubid and only 1–2 of them are EXCEPT
> entries will not occur. Given this, the need for a composite index on
> (prpubid, prexcept) does not appear to be strongly justified to me.
> Please ignore my comment if you are already aware of this situation.
Thanks, I missed the fact that pg_publication_rel doesn't contain
records for each table in the ALL-TABLES case. Case solved.

--
regards, Andrei Lepikhov,
pgEdge


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-26 09:52:41
Message-ID: CAJpy0uDRv=VuG439QTVaX6pgBSvpzAQd5Px9qH+E-XAnwpMuDQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Feb 26, 2026 at 11:42 AM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Wed, Feb 25, 2026 at 10:43 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > Hi Shveta, Ashutosh, Chao-san,
> >
> > Thanks for reviewing the patch.
> > I have addressed the above comments and the comments in [1] and [2].
> > Attached is the latest v50 version.
> >
>
> Thank You Shlok. Please find a few comments on v50-001.
>
> 1)
> -check_publication_add_relation(Relation targetrel)
> +check_publication_add_relation(PublicationRelInfo *pri, bool puballtables)
>
> Why do we need argument puballtables? I think we can give partition
> related error even without checking 'puballtables', like we are giving
> for temp and unlogged table error in EXCEPT list without checking
> puballtables. Or let me know if I am missing the point here?
>
> 2)
> publication_has_any_except_table(): Shall we optimize it:
> a) if it is not all-table pub, return false there itself.
> b) if it is all table, proceed with fetching tuples. At first tuple we
> can break the loop irrespective of check 'pubrel->prexcept', as there
> is no other feasibility. But we shall Assert (pubrel->prexcept) .
> Thoughts?
>
> 3)
> + /* Process EXCEPT table list */
> + if (relations != NIL)
> + {
> + Assert(rels != NIL);
> + PublicationAddTables(puboid, rels, true, NULL);
> + }
>
> We can remove Assert from here too as we don't have it in the later
> part of code where we use rels. I feel it is okay to not have Assert
> as we are fetching rels in nearby logic only.
>
> 4)
> CheckPublicationsForExceptClauses() frees except_publications list
> only in case where it has to emit ERROR. It does not free it for a
> case where there is only one element in it. Also one of the callers
> free the list while another does not. Is it by design? Shall we make
> the behaviour more consistent for callers?
>
> 5)
> postgres=# ALTER TABLE tab_top_root ATTACH PARTITION tab_root FOR
> VALUES FROM (0) TO (2000);
> ERROR: cannot attach table "tab_root" as partition because it is
> referenced in a publication EXCEPT clause
> DETAIL: Tables excluded from publications cannot be attached as partitions.
> HINT: Remove the table from the publication EXCEPT list before attaching it.
>
> a) It will be good to list pubnames here for which we are referring EXCEPT list.
>
> b) Also I feel, instead of emphasising on 'cannot attach table as
> partition' in DETAIL, we should emphasise on 'partition cannot be part
> of EXCEPT'. How about?
> DETAIL: The publication EXCEPT clause cannot contain tables that are partitions.
>
> 6)
> I see a few error-messages mentioning EXCEPT 'clause' while others
> mention EXCEPT 'list'. We can make the wording the same throughout.
>
> 7)
> + /*
> + * Check that the table is not part of any publication when changing to
> + * UNLOGGED, as UNLOGGED tables can't be published.
> + */
> + GetRelationPublications(RelationGetRelid(attachrel), NULL, &exceptpuboids);
> + if (exceptpuboids != NIL)
> + ereport(ERROR,
> + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> + errmsg("cannot attach table \"%s\" as partition because it is
> referenced in a publication EXCEPT clause",
>
> Comments need to be corrected. Copy/paste issue.
>
> 8)
> tablesync.c:
> +#include "replication/logical.h"
>
> This inclusion is not needed now.
>
> Reviewing further.
>

Few more comments on v50-001:

9)
+ * pub1:
+ * FOR ALL TABLES EXCEPT (part1, part2)
+ * WITH (publish_via_partition_root = true)

This example atop check_publications_except_list() needs to be changed
as now we can not specify partitions in EXCEPT.

10)
In get_rel_sync_entry(), for the code under:
/*
* If this is a FOR ALL TABLES publication, pick the partition
* root and set the ancestor level accordingly.
*/

Earlier when 'if (pub->alltables)' was true, 'publish=true' was set
unconditionally, that means it will never go to the subsequent 'if
(!publish)' block. I think that subsequent block was implicitly meant
for a pub which is not for alltables. But now it will go to that block
even for all-tables if we set publish as false because ROOT was
excluded. This unnecessary work should be avoided. A pub can either be
ALL-TABLE (with or without EXCEPT) or schema-pub at a time, but not
both.

11)
get_rel_sync_entry():

+ GetRelationPublications(pub_relid, NULL, &exceptpubids);
+
+ if (!list_member_oid(exceptpubids, pub->oid))
+ publish = true;
+
+ list_free(exceptpubids);

We should add a brief comment as to why we are checking only the last
ancestor in exclude-list. How about this:

Check exclusion of top-most ancestor. Currently, only the top-most
ancestor can be added to the EXCEPT list, which means a partition will
not be published if its top-most ancestor is excluded.

<please rephrase if needed>

12) pg_dump dumped "ONLY" along with ROOT name in EXCEPT. I think it
should be avoided.
pg_dump output:
CREATE PUBLICATION pub4 FOR ALL TABLES EXCEPT TABLE (ONLY
public.tab_root) WITH (publish = 'insert, update, delete, truncate');

13)
pg_dump did not dump EXCEPT list for combination of allseq, all tables pub.

original:
CREATE PUBLICATION pub0 FOR ALL SEQUENCES, ALL TABLES EXCEPT (users,
departments);
postgres=# \dRp+ pub0
Owner | All tables | All sequences |
--------+------------+---------------
shveta | t | t |
Except tables:
"public.departments"
"public. Users"

pg_dump output:
CREATE PUBLICATION pub0 FOR ALL TABLES, ALL SEQUENCES WITH (publish =
'insert, update, delete, truncate');

~~

Reviewing further.

thanks
Shveta


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-26 10:37:10
Message-ID: CAA4eK1+V0-HaxqiEJShTOh5+SGw1p4kurK327n8w3WwLV9DD4Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Feb 26, 2026 at 3:22 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Thu, Feb 26, 2026 at 11:42 AM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > On Wed, Feb 25, 2026 at 10:43 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > >
> > > Hi Shveta, Ashutosh, Chao-san,
> > >
> > > Thanks for reviewing the patch.
> > > I have addressed the above comments and the comments in [1] and [2].
> > > Attached is the latest v50 version.
> > >
> >
> > Thank You Shlok. Please find a few comments on v50-001.
> >
> > 1)
> > -check_publication_add_relation(Relation targetrel)
> > +check_publication_add_relation(PublicationRelInfo *pri, bool puballtables)
> >
> > Why do we need argument puballtables? I think we can give partition
> > related error even without checking 'puballtables', like we are giving
> > for temp and unlogged table error in EXCEPT list without checking
> > puballtables. Or let me know if I am missing the point here?
> >

One more point related to this part of code:
+ if (pri->except)
+ errormsg = gettext_noop("cannot use publication EXCEPT clause for
relation \"%s\"");
+ else
+ errormsg = gettext_noop("cannot add relation \"%s\" to publication");
+
+ /* If in EXCEPT clause, must be root partitioned table */
+ if (puballtables && pri->except && targetrel->rd_rel->relispartition)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg(errormsg, RelationGetRelationName(targetrel)),
+ errdetail("This operation is not supported for individual partitions.")));
+

Why can't we directly use the required error message in errmsg?

> > 2)
> > publication_has_any_except_table(): Shall we optimize it:
> > a) if it is not all-table pub, return false there itself.
> > b) if it is all table, proceed with fetching tuples. At first tuple we
> > can break the loop irrespective of check 'pubrel->prexcept', as there
> > is no other feasibility. But we shall Assert (pubrel->prexcept) .
> > Thoughts?
> >

Hmm, let's not add such optimization checks here. It's not worth
making it specific to all_tables because tomorrow we will need to
support all_tables_in_schema case as well and we won't gain much with
such optimizations.
...

> >
> > 4)
> > CheckPublicationsForExceptClauses() frees except_publications list
> > only in case where it has to emit ERROR. It does not free it for a
> > case where there is only one element in it. Also one of the callers
> > free the list while another does not. Is it by design? Shall we make
> > the behaviour more consistent for callers?
> >

It should be consistent. I think in the ERROR case, most probably, it
will be freed by the containing memory context. I suggest check which
memory context's are used in all cases including when the
LoadPuclications() could be invoked via decoding APIs.

> > 5)
> > postgres=# ALTER TABLE tab_top_root ATTACH PARTITION tab_root FOR
> > VALUES FROM (0) TO (2000);
> > ERROR: cannot attach table "tab_root" as partition because it is
> > referenced in a publication EXCEPT clause
> > DETAIL: Tables excluded from publications cannot be attached as partitions.
> > HINT: Remove the table from the publication EXCEPT list before attaching it.
> >
> > a) It will be good to list pubnames here for which we are referring EXCEPT list.
> >
> > b) Also I feel, instead of emphasising on 'cannot attach table as
> > partition' in DETAIL, we should emphasise on 'partition cannot be part
> > of EXCEPT'. How about?
> > DETAIL: The publication EXCEPT clause cannot contain tables that are partitions.
> >

+1.

--
With Regards,
Amit Kapila.


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-26 14:11:31
Message-ID: CAA4eK1+bBvo3_qE+Y=zLmR+E97KhVseuWrxako=dhzWtVyouXg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Feb 25, 2026 at 10:43 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> I have also split the patch 0002 to 0002 and 0003
> 0001 - Support CREATE PUBLICATION ... EXCEPT TABLE syntax
>

Few comments:
=============
*
* pub_all_obj_type is one of:
*
- * TABLES
+ * TABLES [EXCEPT [TABLE] ( table [, ...] )]
As per above syntax in gram.y, [TABLE] is optional but won't it be
confusing when we also support sequences? Then we need to identify
whether the object given in EXCEPT list is table or sequence. So, I
think it is better to keep TABLE as non-optional.

* Can we have one test related to INHERITS for actual replication
unless it is already there?

--
With Regards,
Amit Kapila.


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-27 05:33:33
Message-ID: CAA4eK1JrqoPvrFxZEO2rB=-jXK1BQdJZz2_2oeZqCQR3GRWC2g@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Feb 26, 2026 at 3:22 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> Few more comments on v50-001:
>
> 9)
> + * pub1:
> + * FOR ALL TABLES EXCEPT (part1, part2)
> + * WITH (publish_via_partition_root = true)
>
> This example atop check_publications_except_list() needs to be changed
> as now we can not specify partitions in EXCEPT.
>

Now that we don't support partitions in EXCEPT clauses, won't it be
possible to allow combining two publications with except clauses?

Few other comments:
=================
1.
+/*
+ * Get the list of publication oids associated with a specified relation.
+ *
+ * 'pubids' returns the Oids of the publications the relation is part of.
+ *
+ * 'except_pubids' returns the Oids of publications the relation is excluded
+ * from.
+ *
+ * This function returns true if the relation is part of any publication.
+ */
+bool
+GetRelationPublications(Oid relid, List **pubids, List **except_pubids)

Isn't it better to have two wrapper functions for included and
excluded RelationPublications? The current API signature doesn't look
clean to me as it combines two different things.

2.
The following is from 0001
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -198,7 +198,12 @@ ObjectsInPublicationToOids(List *pubobjspec_list,
ParseState *pstate,

switch (pubobj->pubobjtype)
{
+ case PUBLICATIONOBJ_EXCEPT_TABLE:
+ pubobj->pubtable->except = true;
+ *rels = lappend(*rels, pubobj->pubtable);
+ break;
case PUBLICATIONOBJ_TABLE:
+ pubobj->pubtable->except = false;
*rels = lappend(*rels, pubobj->pubtable);
....

The following is from 0002:
static void
ObjectsInPublicationToOids(List *pubobjspec_list, ParseState *pstate,
- List **rels, List **schemas)
+ List **rels, List **exceptrels, List **schemas)
{
ListCell *cell;
PublicationObjSpec *pubobj;
@@ -200,7 +200,7 @@ ObjectsInPublicationToOids(List *pubobjspec_list,
ParseState *pstate,
{
case PUBLICATIONOBJ_EXCEPT_TABLE:
pubobj->pubtable->except = true;
- *rels = lappend(*rels, pubobj->pubtable);
+ *exceptrels = lappend(*exceptrels, pubobj->pubtable);

I think it is better to have a separate exceptlist from patch-1 itself
as that keeps code easier to understand for 0001.

3.
+$node_publisher->safe_psql('postgres',
+ "SELECT slot_name FROM pg_replication_slot_advance('test_slot',
pg_current_wal_lsn());"
+);

At above and other places where it uses slot_advance, write a comment
to explain why the same is required.

4.
+ # When the root partitioned table is listed in the EXCEPT clause,
+ # all its partitions are not published.
+ $node_publisher->safe_psql(

Can we change the comment to the following: "If the root partitioned
table is in the EXCEPT clause, all its partitions are excluded from
publication, regardless of the publish_via_partition_root setting."?

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-27 06:39:59
Message-ID: CALDaNm02BrFzWK+uhR2RA8LLQsYgD99-qDzyshOFpKg220VP_Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 26 Feb 2026 at 11:42, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Wed, Feb 25, 2026 at 10:43 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > Hi Shveta, Ashutosh, Chao-san,
> >
> > Thanks for reviewing the patch.
> > I have addressed the above comments and the comments in [1] and [2].
> > Attached is the latest v50 version.
> >
>
> Thank You Shlok. Please find a few comments on v50-001.
>
> 1)
> -check_publication_add_relation(Relation targetrel)
> +check_publication_add_relation(PublicationRelInfo *pri, bool puballtables)
>
> Why do we need argument puballtables? I think we can give partition
> related error even without checking 'puballtables', like we are giving
> for temp and unlogged table error in EXCEPT list without checking
> puballtables. Or let me know if I am missing the point here?

This is required as this is a common function used by both all tables
and table publication, since we allow child tables in case of table
publication, alltables check is required.

> 2)
> publication_has_any_except_table(): Shall we optimize it:
> a) if it is not all-table pub, return false there itself.
> b) if it is all table, proceed with fetching tuples. At first tuple we
> can break the loop irrespective of check 'pubrel->prexcept', as there
> is no other feasibility. But we shall Assert (pubrel->prexcept) .
> Thoughts?

As Amit is also not in favor of this at [1], I'm not doing any change for this.

Rest of the comments are addressed in the attached v51 version.

Regarding the 12 comment from [2]:
> 12) pg_dump dumped "ONLY" along with ROOT name in EXCEPT. I think it
> should be avoided.
> pg_dump output:
> CREATE PUBLICATION pub4 FOR ALL TABLES EXCEPT TABLE (ONLY
> public.tab_root) WITH (publish = 'insert, update, delete, truncate');

I felt this is ok, we dump similarly in case of table publications too
like for the below publication:
create publication pub1 for table tab_root ;

Dump adds only here too:
--
-- Name: pub1 tab_root; Type: PUBLICATION TABLE; Schema: public; Owner: vignesh
--

ALTER PUBLICATION pub1 ADD TABLE ONLY public.tab_root;

Rest of the comments from [2] have been addressed.

[1] - https://www.postgresql.org/message-id/CAA4eK1%2BV0-HaxqiEJShTOh5%2BSGw1p4kurK327n8w3WwLV9DD4Q%40mail.gmail.com
[2] - https://www.postgresql.org/message-id/CAJpy0uDRv%3DVuG439QTVaX6pgBSvpzAQd5Px9qH%2BE-XAnwpMuDQ%40mail.gmail.com

Regards,
Vignesh

Attachment Content-Type Size
v51-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 85.0 KB
v51-0002-Support-SET-EXCEPT-TABLE-in-ALTER-PUBLICATION.patch application/octet-stream 23.0 KB
v51-0003-Support-DROP-EXCEPT-TABLE-in-ALTER-PUBLICATION.patch application/octet-stream 10.4 KB

From: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-27 11:31:14
Message-ID: CABdArM6Wc2QtubTm2BAnmqtZqQSA16GsEMRZgbpa66kyLDy_AQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Feb 27, 2026 at 12:10 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> Rest of the comments are addressed in the attached v51 version.

Thanks for the patches, I am still testing the patches, but sharing a
few initial review comments.

1) v51-0001: Bug in testcase - /t/037_rep_changes_except_table.pl
The test_except_root_partition() is invoked twice with values true and
false. However, from the logs it appears that both executions use
publish_via_partition_root = 1.
LOG output:
138 2026-02-27 12:26:51.167 IST client backend[72317]
037_rep_changes_except_table.pl LOG: statement: CREATE PUBLICATION
tap_pub_part FOR ALL TABLES EXCEPT TABLE (sch1.t1) WITH
(publish_via_partition_root = 1);
...
...
238 2026-02-27 12:26:51.600 IST client backend[72369]
037_rep_changes_except_table.pl LOG: statement: CREATE PUBLICATION
tap_pub_part FOR ALL TABLES EXCEPT TABLE (sch1.t1) WITH
(publish_via_partition_root = 1);

It seems $pubviaroot is assigned using the argument count instead of
the argument value, which causes both runs to behave the same.
Fix is to replace the assignment as:
27 - my $pubviaroot = @_;
27 + my ($pubviaroot) = @_;
~~~

2) v51-0001: File: src/backend/commands/tablecmds.c

+ ereport(ERROR,
+ errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot attach table \"%s\" as partition because it is
referenced in publication \"%s\" EXCEPT clause",
+ RelationGetRelationName(attachrel), pubnames.data),
+ errdetail("The publication EXCEPT clause cannot contain tables that
are partitions.");
+ errhint("Remove the table from the publication EXCEPT clause before
attaching it."));
+ }

In the ereport() call, there appears to be a small typo. A comma
should follow errdetail() instead of a semicolon.
~~~

3) v51-0002: File: src/backend/commands/publicationcmds.c
+
+ /* Check that user is allowed to manipulate the publication tables. */
+ if (excepttables && !pubform->puballtables)
+ ereport(ERROR,
+ errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("publication \"%s\" is defined as NON FOR ALL TABLES",
+ NameStr(pubform->pubname)),
+ errdetail("EXCEPT Tables cannot be added to or dropped from non FOR
ALL TABLES publications."));
}

It seems the check is for both SET and DROP cases, but this patch is
only for SET. Also, I find it a bit confusing, could be made clearer.
Suggestion:
- errmsg("publication \"%s\" is defined as NON FOR ALL TABLES",
+ errmsg("publication \"%s\" is not defined as FOR ALL TABLES",
NameStr(pubform->pubname)),
- errdetail("EXCEPT Tables cannot be added to or dropped from non FOR
ALL TABLES publications."));
+ errdetail("EXCEPT TABLE cannot be used with publications that are
not defined as FOR ALL TABLES."));
~~~

4) v51-0002 and v51-003:
File: doc/src/sgml/ref/alter_publication.sgml
...
- remove one or more tables/schemas from the publication. Note that adding
- tables/schemas to a publication that is already subscribed to will
require an
+ except tables/tables/schemas in the publication with the specified list; the
+ existing except tables/ tables/schemas that were present in the publication
...
4a) After adding “except tables” as a third option, the slash based
formatting may be slightly confusing. It may be clearer to write as:
... the existing except tables, tables, or schemas that were present in ....
... The <literal>DROP</literal> clauses will remove one or more except
tables, tables, or schemas from the publication....

If the existing slash format is retained, there is a typo in "except
tables/ tables/schemas", extra space after tables/.

4b) Should we add examples for SET/DROP EXCEPT TABLE as well?
~~~

5) Inconsistency in EXCEPT TABLE syntax
In CREATE PUBLICATION, the syntax requires parentheses, for example
EXCEPT TABLE (t1, t2), whereas in SET and DROP it is accepted only
without parentheses, like - EXCEPT TABLE t1, t2;

Should we keep the syntax consistent across all commands?
~~~

--
Thanks,
Nisha


From: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-27 15:14:18
Message-ID: CABdArM5zR5GUGquoyAeVJgRoQXzjXNa6WuF724Mfbt1RJ5cZ6Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Feb 27, 2026 at 5:01 PM Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
>
> Thanks for the patches, I am still testing the patches, but sharing a
> few initial review comments.
>

I did few tests on v51 all patches, please find further comments -

1. Partition Related Behavior
-----------------------------
Setup:
CREATE TABLE t_part (id int) PARTITION BY RANGE (id);
CREATE TABLE t_part_p1 PARTITION OF t_part FOR VALUES FROM (0) TO (100);
CREATE TABLE t_part_p2 (id int);
ALTER TABLE t_part ATTACH PARTITION t_part_p2 FOR VALUES FROM (100) TO (200);

t_part
|_> t_part_p1
|_> t_part_p2

Publication:
create publication pubp1 for ALL TABLES EXCEPT TABLE (t_part);
-- No data from all three tables is replicated, which is expected.

1a) DETACH t_part_p2 from parent
ALTER TABLE t_part DETACH PARTITION t_part_p2;

When t_part_p2 is detached, it becomes a standalone table and is no
longer part of the EXCEPT hierarchy. But, replication does not start
automatically. It requires REFRESH PUBLICATION on the subscriber.
Should we add a warning/hint during DETACH command to inform users
that REFRESH PUBLICATION is required?
It may also help to update the related documentation.
~~
1b): Attach the partition again
ALTER TABLE t_part ATTACH PARTITION t_part_p2 FOR VALUES FROM (100) TO (200);
When the partition is attached back, replication stops immediately as
it becomes part of the excluded parent again. No REFRESH PUBLICATION
is required on the subscriber. In this case, users may not realize
that replication has stopped. Should we consider adding a warning
during ATTACH in such scenarios?
~~~~

2. Inherited Tables Behavior
Setup:
CREATE TABLE t_inh (id int);
CREATE TABLE t_inh_c1 (c1 int) INHERITS (t_inh);
CREATE TABLE t_inh_c2 (c2 int) INHERITS (t_inh);
t_inh
|_> t_inh_c1
|_> t_inh_c2

Publication:
create publication pubi1 for ALL TABLES EXCEPT TABLE (t_inh);
--All three tables are not replicated.

2a): Remove child from parent
alter table t_inh_c1 NO INHERIT t_inh;

\d+ t_inh shows:
Except Publications:
"pubi1"
Child tables: t_inh_c2

But the publication still shows:
Except tables:
"public.t_inh"
"public.t_inh_c1"
"public.t_inh_c2"

t_inh_c1 is no longer part of the excluded hierarchy, yet it remains
in the EXCEPT list and replication does not start for it.
This appears inconsistent and may be a bug.

2b): Add inheritance to excluded parent
alter table t_inh_c1 inherit t_inh;

Publication:
Except tables:
"public.t_inh"
"public.t_inh_c2"

\d+ t_inh shows:
Except Publications:
"pubi1"
Child tables: t_inh_c1,
t_inh_c2

Here, the table hierarchy is updated, but the publication EXCEPT list
is not updated. Replication continues for t_inh_c1 even though its
parent is excluded.
From a user perspective, this appears incorrect.

I am not sure whether we can determine if the publication was created
for ONLY parent or for parent including children once it is created.
If this behavior is unavoidable, it should be documented.
~~~~

3. SET EXCEPT TABLE Behavior
Publication created with:
create publication pubi5 for ALL TABLES EXCEPT TABLE (ONLY t_inh);
-- Replicates t_inh_c1 and t_inh_c2, as expected.
Now:
alter publication pubi5 SET EXCEPT TABLE t_inh;

Publication pubi5
Except tables:
"public.t_inh"
"public.t_inh_c1"
"public.t_inh_c2"

But, replication continues on the subscriber for both t_inh_c1 and
t_inh_c2 even after REFRESH PUBLICATION. This seems like a bug.
Note: The opposite works correctly. If SET EXCEPT removes previous
tables, replication starts/resumes immediately for these tables.
~~~~

--
Thanks,
Nisha


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-28 08:13:15
Message-ID: CALDaNm11zmAdSg2vOrGJ6KnB3hX34Pd1r2NU7nTXJpN6f-7tqQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 26 Feb 2026 at 19:41, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Wed, Feb 25, 2026 at 10:43 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > I have also split the patch 0002 to 0002 and 0003
> > 0001 - Support CREATE PUBLICATION ... EXCEPT TABLE syntax
> >
>
> Few comments:
> =============
> *
> * pub_all_obj_type is one of:
> *
> - * TABLES
> + * TABLES [EXCEPT [TABLE] ( table [, ...] )]
> As per above syntax in gram.y, [TABLE] is optional but won't it be
> confusing when we also support sequences? Then we need to identify
> whether the object given in EXCEPT list is table or sequence. So, I
> think it is better to keep TABLE as non-optional.
>
> * Can we have one test related to INHERITS for actual replication
> unless it is already there?

Thanks for the comments, these comments are addressed in the v52
version patch attached.
Also the comments from [1] are addressed in the same.
[1] - https://www.postgresql.org/message-id/CAA4eK1JrqoPvrFxZEO2rB%3D-jXK1BQdJZz2_2oeZqCQR3GRWC2g%40mail.gmail.com

Regards,
Vignesh

Attachment Content-Type Size
v52-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 77.5 KB
v52-0003-Support-DROP-EXCEPT-TABLE-in-ALTER-PUBLICATION.patch application/octet-stream 10.5 KB
v52-0002-Support-SET-EXCEPT-TABLE-in-ALTER-PUBLICATION.patch application/octet-stream 20.4 KB

From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-28 11:57:16
Message-ID: CAA4eK1L2LDps5AdtRYySQhmqSbKeUG2GinOKJCn7bvLEdKOoPg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Feb 27, 2026 at 8:44 PM Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
>
> On Fri, Feb 27, 2026 at 5:01 PM Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
> >
> > Thanks for the patches, I am still testing the patches, but sharing a
> > few initial review comments.
> >
>
> I did few tests on v51 all patches, please find further comments -
>
> 1. Partition Related Behavior
> -----------------------------
> Setup:
> CREATE TABLE t_part (id int) PARTITION BY RANGE (id);
> CREATE TABLE t_part_p1 PARTITION OF t_part FOR VALUES FROM (0) TO (100);
> CREATE TABLE t_part_p2 (id int);
> ALTER TABLE t_part ATTACH PARTITION t_part_p2 FOR VALUES FROM (100) TO (200);
>
> t_part
> |_> t_part_p1
> |_> t_part_p2
>
> Publication:
> create publication pubp1 for ALL TABLES EXCEPT TABLE (t_part);
> -- No data from all three tables is replicated, which is expected.
>
> 1a) DETACH t_part_p2 from parent
> ALTER TABLE t_part DETACH PARTITION t_part_p2;
>
> When t_part_p2 is detached, it becomes a standalone table and is no
> longer part of the EXCEPT hierarchy. But, replication does not start
> automatically. It requires REFRESH PUBLICATION on the subscriber.
> Should we add a warning/hint during DETACH command to inform users
> that REFRESH PUBLICATION is required?
> It may also help to update the related documentation.
>

This is required even when a regular (non-partitioned table) is
created to let the corresponding entry populated in
pg_subscription_rel. See docs[1] (REFRESH PUBLICATION ..).

> ~~
> 1b): Attach the partition again
> ALTER TABLE t_part ATTACH PARTITION t_part_p2 FOR VALUES FROM (100) TO (200);
> When the partition is attached back, replication stops immediately as
> it becomes part of the excluded parent again. No REFRESH PUBLICATION
> is required on the subscriber. In this case, users may not realize
> that replication has stopped. Should we consider adding a warning
> during ATTACH in such scenarios?
> ~~~~
>

This is worth considering but my opinion is that we don't need it as
users should be aware of such behavior. For example, today, if a
publication has published a root table say tab_root and one of its
partitions is detached, we should stop that partition's replication
but do we give WARNING for such cases?

> 2. Inherited Tables Behavior
> Setup:
> CREATE TABLE t_inh (id int);
> CREATE TABLE t_inh_c1 (c1 int) INHERITS (t_inh);
> CREATE TABLE t_inh_c2 (c2 int) INHERITS (t_inh);
> t_inh
> |_> t_inh_c1
> |_> t_inh_c2
>
> Publication:
> create publication pubi1 for ALL TABLES EXCEPT TABLE (t_inh);
> --All three tables are not replicated.
>
> 2a): Remove child from parent
> alter table t_inh_c1 NO INHERIT t_inh;
>
> \d+ t_inh shows:
> Except Publications:
> "pubi1"
> Child tables: t_inh_c2
>
> But the publication still shows:
> Except tables:
> "public.t_inh"
> "public.t_inh_c1"
> "public.t_inh_c2"
>
> t_inh_c1 is no longer part of the excluded hierarchy, yet it remains
> in the EXCEPT list and replication does not start for it.
> This appears inconsistent and may be a bug.
>

I think after removal, it shouldn't have been shown here, so, we
should see why it is happening. OTOH, won't replication requires user
to perform REFRESH PUBLICATION as in the previous case?

Few other comments:
1.
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -37,6 +37,7 @@
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "pgstat.h"
+#include "replication/logical.h"
#include "replication/logicallauncher.h"
#include "replication/logicalworker.h"
#include "replication/origin.h"

There is no other change in this file, so do we even need this header included?

2.
+ foreach_oid(pubid, exceptpuboids)
+ {
+ char *pubname = get_publication_name(pubid, false);
+
+ if (!first)
+ appendStringInfoString(&pubnames, ", ");
+
+ first = false;
+
+ appendStringInfoString(&pubnames, quote_literal_cstr(pubname));
+ }
+
+ ereport(ERROR,
+ errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot attach table \"%s\" as partition because it is
referenced in publication \"%s\" EXCEPT clause",
+ RelationGetRelationName(attachrel), pubnames.data),
+ errdetail("The publication EXCEPT clause cannot contain tables that
are partitions."),
+ errhint("Remove the table from the publication EXCEPT clause before
attaching it."));

A. As there could be multiple publications, so errmsg_plural form
should be used, refer to other places.
B. I think errhint should be removed from 0001 and added back by 0002
where you can say how user can remove it by using SET CLAUSE

[1] - https://www.postgresql.org/docs/devel/sql-altersubscription.html

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-02-28 14:07:14
Message-ID: CALDaNm1gwuOgdeffd5yUOe=kP6QCq8uSkX1YFMjx8=5PbCvt-Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, 28 Feb 2026 at 17:27, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Fri, Feb 27, 2026 at 8:44 PM Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
> >
> > On Fri, Feb 27, 2026 at 5:01 PM Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
> > >
> > > Thanks for the patches, I am still testing the patches, but sharing a
> > > few initial review comments.
> > >
> >
> > I did few tests on v51 all patches, please find further comments -
> >
> > 1. Partition Related Behavior
> > -----------------------------
> > Setup:
> > CREATE TABLE t_part (id int) PARTITION BY RANGE (id);
> > CREATE TABLE t_part_p1 PARTITION OF t_part FOR VALUES FROM (0) TO (100);
> > CREATE TABLE t_part_p2 (id int);
> > ALTER TABLE t_part ATTACH PARTITION t_part_p2 FOR VALUES FROM (100) TO (200);
> >
> > t_part
> > |_> t_part_p1
> > |_> t_part_p2
> >
> > Publication:
> > create publication pubp1 for ALL TABLES EXCEPT TABLE (t_part);
> > -- No data from all three tables is replicated, which is expected.
> >
> > 1a) DETACH t_part_p2 from parent
> > ALTER TABLE t_part DETACH PARTITION t_part_p2;
> >
> > When t_part_p2 is detached, it becomes a standalone table and is no
> > longer part of the EXCEPT hierarchy. But, replication does not start
> > automatically. It requires REFRESH PUBLICATION on the subscriber.
> > Should we add a warning/hint during DETACH command to inform users
> > that REFRESH PUBLICATION is required?
> > It may also help to update the related documentation.
> >
>
> This is required even when a regular (non-partitioned table) is
> created to let the corresponding entry populated in
> pg_subscription_rel. See docs[1] (REFRESH PUBLICATION ..).
>
> > ~~
> > 1b): Attach the partition again
> > ALTER TABLE t_part ATTACH PARTITION t_part_p2 FOR VALUES FROM (100) TO (200);
> > When the partition is attached back, replication stops immediately as
> > it becomes part of the excluded parent again. No REFRESH PUBLICATION
> > is required on the subscriber. In this case, users may not realize
> > that replication has stopped. Should we consider adding a warning
> > during ATTACH in such scenarios?
> > ~~~~
> >
>
> This is worth considering but my opinion is that we don't need it as
> users should be aware of such behavior. For example, today, if a
> publication has published a root table say tab_root and one of its
> partitions is detached, we should stop that partition's replication
> but do we give WARNING for such cases?
>
> > 2. Inherited Tables Behavior
> > Setup:
> > CREATE TABLE t_inh (id int);
> > CREATE TABLE t_inh_c1 (c1 int) INHERITS (t_inh);
> > CREATE TABLE t_inh_c2 (c2 int) INHERITS (t_inh);
> > t_inh
> > |_> t_inh_c1
> > |_> t_inh_c2
> >
> > Publication:
> > create publication pubi1 for ALL TABLES EXCEPT TABLE (t_inh);
> > --All three tables are not replicated.
> >
> > 2a): Remove child from parent
> > alter table t_inh_c1 NO INHERIT t_inh;
> >
> > \d+ t_inh shows:
> > Except Publications:
> > "pubi1"
> > Child tables: t_inh_c2
> >
> > But the publication still shows:
> > Except tables:
> > "public.t_inh"
> > "public.t_inh_c1"
> > "public.t_inh_c2"
> >
> > t_inh_c1 is no longer part of the excluded hierarchy, yet it remains
> > in the EXCEPT list and replication does not start for it.
> > This appears inconsistent and may be a bug.
> >
>
> I think after removal, it shouldn't have been shown here, so, we
> should see why it is happening.

I believe this is existing behavior, and the same applies to
table-level publications as well.
For example:
-- Create table publication
create publication pubi1 for table t_inh;
\d+ t_inh
Table "public.t_inh"
Column | Type | Collation | Nullable | Default | Storage |
Compression | Stats target | Description
--------+---------+-----------+----------+---------+---------+-------------+--------------+-------------
id | integer | | | | plain |
| |
Publications:
"pubi1"
Child tables: t_inh_c1,
t_inh_c2

postgres=# \dRp+
Publication pubi1
Owner | All tables | All sequences | Inserts | Updates | Deletes |
Truncates | Generated columns | Via root
---------+------------+---------------+---------+---------+---------+-----------+-------------------+----------
vignesh | f | f | t | t | t |
t | none | f
Tables:
"public.t_inh"
"public.t_inh_c1"
"public.t_inh_c2"

--- Remove the inherits for one of the child table
postgres=# alter table t_inh_c1 NO INHERIT t_inh;
ALTER TABLE

--- Publication will still have t_inh_c1 table in case of table publication too
postgres=# \dRp+
Publication pubi1
Owner | All tables | All sequences | Inserts | Updates | Deletes |
Truncates | Generated columns | Via root
---------+------------+---------------+---------+---------+---------+-----------+-------------------+----------
vignesh | f | f | t | t | t |
t | none | f
Tables:
"public.t_inh"
"public.t_inh_c1"
"public.t_inh_c2"

This occurs because when ONLY is not specified, the table t_inh and
all its descendant tables (t_inh_c1 and t_inh_c2) are added to
pg_publication_rel at the time the publication is created. Replication
then proceeds strictly based on the entries in pg_publication_rel.
There is no explicit parent child mapping maintained for these
relations in the publication catalog; each table is treated as an
independent entry.
When "ALTER TABLE t_inh_c1 NO INHERIT t_inh;" is executed later,
t_inh_c1 is not automatically removed from the publication. Since it
was added as a separate entry in pg_publication_rel, removing the
inheritance relationship does not affect its publication membership.
I'm not sure whether this is the intended design or an unintended side
effect. If this behavior is not expected, we can address it separately
and adjust the implementation accordingly.

Regards,
Vignesh


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-01 03:11:30
Message-ID: CALDaNm32g7c323M4mgZ5Wn8sbYp_=uQ6G_u0f9qfBCzuHP8jgQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 27 Feb 2026 at 17:01, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
>
> On Fri, Feb 27, 2026 at 12:10 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > Rest of the comments are addressed in the attached v51 version.
>
> Thanks for the patches, I am still testing the patches, but sharing a
> few initial review comments.
>
> 1) v51-0001: Bug in testcase - /t/037_rep_changes_except_table.pl
> The test_except_root_partition() is invoked twice with values true and
> false. However, from the logs it appears that both executions use
> publish_via_partition_root = 1.
> LOG output:
> 138 2026-02-27 12:26:51.167 IST client backend[72317]
> 037_rep_changes_except_table.pl LOG: statement: CREATE PUBLICATION
> tap_pub_part FOR ALL TABLES EXCEPT TABLE (sch1.t1) WITH
> (publish_via_partition_root = 1);
> ...
> ...
> 238 2026-02-27 12:26:51.600 IST client backend[72369]
> 037_rep_changes_except_table.pl LOG: statement: CREATE PUBLICATION
> tap_pub_part FOR ALL TABLES EXCEPT TABLE (sch1.t1) WITH
> (publish_via_partition_root = 1);
>
> It seems $pubviaroot is assigned using the argument count instead of
> the argument value, which causes both runs to behave the same.
> Fix is to replace the assignment as:
> 27 - my $pubviaroot = @_;
> 27 + my ($pubviaroot) = @_;

Fixed

> 2) v51-0001: File: src/backend/commands/tablecmds.c
>
> + ereport(ERROR,
> + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> + errmsg("cannot attach table \"%s\" as partition because it is
> referenced in publication \"%s\" EXCEPT clause",
> + RelationGetRelationName(attachrel), pubnames.data),
> + errdetail("The publication EXCEPT clause cannot contain tables that
> are partitions.");
> + errhint("Remove the table from the publication EXCEPT clause before
> attaching it."));
> + }
>
> In the ereport() call, there appears to be a small typo. A comma
> should follow errdetail() instead of a semicolon.

Fixed

> 3) v51-0002: File: src/backend/commands/publicationcmds.c
> +
> + /* Check that user is allowed to manipulate the publication tables. */
> + if (excepttables && !pubform->puballtables)
> + ereport(ERROR,
> + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> + errmsg("publication \"%s\" is defined as NON FOR ALL TABLES",
> + NameStr(pubform->pubname)),
> + errdetail("EXCEPT Tables cannot be added to or dropped from non FOR
> ALL TABLES publications."));
> }
>
> It seems the check is for both SET and DROP cases, but this patch is
> only for SET. Also, I find it a bit confusing, could be made clearer.
> Suggestion:
> - errmsg("publication \"%s\" is defined as NON FOR ALL TABLES",
> + errmsg("publication \"%s\" is not defined as FOR ALL TABLES",
> NameStr(pubform->pubname)),
> - errdetail("EXCEPT Tables cannot be added to or dropped from non FOR
> ALL TABLES publications."));
> + errdetail("EXCEPT TABLE cannot be used with publications that are
> not defined as FOR ALL TABLES."));

Modified with slight changes to keep it inline with other error messages there.

> 4) v51-0002 and v51-003:
> File: doc/src/sgml/ref/alter_publication.sgml
> ...
> - remove one or more tables/schemas from the publication. Note that adding
> - tables/schemas to a publication that is already subscribed to will
> require an
> + except tables/tables/schemas in the publication with the specified list; the
> + existing except tables/ tables/schemas that were present in the publication
> ...
> 4a) After adding “except tables” as a third option, the slash based
> formatting may be slightly confusing. It may be clearer to write as:
> ... the existing except tables, tables, or schemas that were present in ....
> ... The <literal>DROP</literal> clauses will remove one or more except
> tables, tables, or schemas from the publication....
>
> If the existing slash format is retained, there is a typo in "except
> tables/ tables/schemas", extra space after tables/.

Existing format was used, the typo issue was fixed.

> 4b) Should we add examples for SET/DROP EXCEPT TABLE as well?

Added them

> 5) Inconsistency in EXCEPT TABLE syntax
> In CREATE PUBLICATION, the syntax requires parentheses, for example
> EXCEPT TABLE (t1, t2), whereas in SET and DROP it is accepted only
> without parentheses, like - EXCEPT TABLE t1, t2;
>
> Should we keep the syntax consistent across all commands?

I’ll look into this separately and share my analysis soon.

The attached v53 version patch has the changes for the same.

Also the comments from [1] have been addressed.
[1] - https://www.postgresql.org/message-id/CAA4eK1L2LDps5AdtRYySQhmqSbKeUG2GinOKJCn7bvLEdKOoPg%40mail.gmail.com

Regards,
Vignesh

Attachment Content-Type Size
v53-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 77.0 KB
v53-0003-Support-DROP-EXCEPT-TABLE-in-ALTER-PUBLICATION.patch application/octet-stream 14.0 KB
v53-0002-Support-SET-EXCEPT-TABLE-in-ALTER-PUBLICATION.patch application/octet-stream 24.7 KB

From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-01 12:22:42
Message-ID: CAA4eK1Lqbsv2i5WuKhMHRvwHG6-jW+LzH+tB+qzWhmgpy_yWsg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, Feb 28, 2026 at 7:37 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Sat, 28 Feb 2026 at 17:27, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> > On Fri, Feb 27, 2026 at 8:44 PM Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
> > >
> > > On Fri, Feb 27, 2026 at 5:01 PM Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
> > > >
> > > > Thanks for the patches, I am still testing the patches, but sharing a
> > > > few initial review comments.
> > > >
> > >
> > > I did few tests on v51 all patches, please find further comments -
> > >
> > > 1. Partition Related Behavior
> > > -----------------------------
> > > Setup:
> > > CREATE TABLE t_part (id int) PARTITION BY RANGE (id);
> > > CREATE TABLE t_part_p1 PARTITION OF t_part FOR VALUES FROM (0) TO (100);
> > > CREATE TABLE t_part_p2 (id int);
> > > ALTER TABLE t_part ATTACH PARTITION t_part_p2 FOR VALUES FROM (100) TO (200);
> > >
> > > t_part
> > > |_> t_part_p1
> > > |_> t_part_p2
> > >
> > > Publication:
> > > create publication pubp1 for ALL TABLES EXCEPT TABLE (t_part);
> > > -- No data from all three tables is replicated, which is expected.
> > >
> > > 1a) DETACH t_part_p2 from parent
> > > ALTER TABLE t_part DETACH PARTITION t_part_p2;
> > >
> > > When t_part_p2 is detached, it becomes a standalone table and is no
> > > longer part of the EXCEPT hierarchy. But, replication does not start
> > > automatically. It requires REFRESH PUBLICATION on the subscriber.
> > > Should we add a warning/hint during DETACH command to inform users
> > > that REFRESH PUBLICATION is required?
> > > It may also help to update the related documentation.
> > >
> >
> > This is required even when a regular (non-partitioned table) is
> > created to let the corresponding entry populated in
> > pg_subscription_rel. See docs[1] (REFRESH PUBLICATION ..).
> >
> > > ~~
> > > 1b): Attach the partition again
> > > ALTER TABLE t_part ATTACH PARTITION t_part_p2 FOR VALUES FROM (100) TO (200);
> > > When the partition is attached back, replication stops immediately as
> > > it becomes part of the excluded parent again. No REFRESH PUBLICATION
> > > is required on the subscriber. In this case, users may not realize
> > > that replication has stopped. Should we consider adding a warning
> > > during ATTACH in such scenarios?
> > > ~~~~
> > >
> >
> > This is worth considering but my opinion is that we don't need it as
> > users should be aware of such behavior. For example, today, if a
> > publication has published a root table say tab_root and one of its
> > partitions is detached, we should stop that partition's replication
> > but do we give WARNING for such cases?
> >
> > > 2. Inherited Tables Behavior
> > > Setup:
> > > CREATE TABLE t_inh (id int);
> > > CREATE TABLE t_inh_c1 (c1 int) INHERITS (t_inh);
> > > CREATE TABLE t_inh_c2 (c2 int) INHERITS (t_inh);
> > > t_inh
> > > |_> t_inh_c1
> > > |_> t_inh_c2
> > >
> > > Publication:
> > > create publication pubi1 for ALL TABLES EXCEPT TABLE (t_inh);
> > > --All three tables are not replicated.
> > >
> > > 2a): Remove child from parent
> > > alter table t_inh_c1 NO INHERIT t_inh;
> > >
> > > \d+ t_inh shows:
> > > Except Publications:
> > > "pubi1"
> > > Child tables: t_inh_c2
> > >
> > > But the publication still shows:
> > > Except tables:
> > > "public.t_inh"
> > > "public.t_inh_c1"
> > > "public.t_inh_c2"
> > >
> > > t_inh_c1 is no longer part of the excluded hierarchy, yet it remains
> > > in the EXCEPT list and replication does not start for it.
> > > This appears inconsistent and may be a bug.
> > >
> >
> > I think after removal, it shouldn't have been shown here, so, we
> > should see why it is happening.
>
> I believe this is existing behavior, and the same applies to
> table-level publications as well.
> For example:
> -- Create table publication
> create publication pubi1 for table t_inh;
> \d+ t_inh
> Table "public.t_inh"
> Column | Type | Collation | Nullable | Default | Storage |
> Compression | Stats target | Description
> --------+---------+-----------+----------+---------+---------+-------------+--------------+-------------
> id | integer | | | | plain |
> | |
> Publications:
> "pubi1"
> Child tables: t_inh_c1,
> t_inh_c2
>
> postgres=# \dRp+
> Publication pubi1
> Owner | All tables | All sequences | Inserts | Updates | Deletes |
> Truncates | Generated columns | Via root
> ---------+------------+---------------+---------+---------+---------+-----------+-------------------+----------
> vignesh | f | f | t | t | t |
> t | none | f
> Tables:
> "public.t_inh"
> "public.t_inh_c1"
> "public.t_inh_c2"
>
> --- Remove the inherits for one of the child table
> postgres=# alter table t_inh_c1 NO INHERIT t_inh;
> ALTER TABLE
>
> --- Publication will still have t_inh_c1 table in case of table publication too
> postgres=# \dRp+
> Publication pubi1
> Owner | All tables | All sequences | Inserts | Updates | Deletes |
> Truncates | Generated columns | Via root
> ---------+------------+---------------+---------+---------+---------+-----------+-------------------+----------
> vignesh | f | f | t | t | t |
> t | none | f
> Tables:
> "public.t_inh"
> "public.t_inh_c1"
> "public.t_inh_c2"
>
> This occurs because when ONLY is not specified, the table t_inh and
> all its descendant tables (t_inh_c1 and t_inh_c2) are added to
> pg_publication_rel at the time the publication is created. Replication
> then proceeds strictly based on the entries in pg_publication_rel.
> There is no explicit parent child mapping maintained for these
> relations in the publication catalog; each table is treated as an
> independent entry.
> When "ALTER TABLE t_inh_c1 NO INHERIT t_inh;" is executed later,
> t_inh_c1 is not automatically removed from the publication. Since it
> was added as a separate entry in pg_publication_rel, removing the
> inheritance relationship does not affect its publication membership.
> I'm not sure whether this is the intended design or an unintended side
> effect. If this behavior is not expected, we can address it separately
> and adjust the implementation accordingly.
>

So, the similar case for partitioned table works because there we add
only root partitioned table in pg_publication_rel. I understand that
current behaviour for inherited tables (each inherited table is
considered separately after being added to the publication) is because
of the existing design and should be changed separately, if required.
I haven't checked whether it is possible to change this behavior but
it appears that we should try to investigate and see the possibility
of fixing it separately.

Nisha, what do you think based on this analysis?

--
With Regards,
Amit Kapila.


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-01 12:24:43
Message-ID: CAJpy0uBEzVzcgvKcnHNsFeRkg7sWuZGkLgfmZMj-zcKEKCiEKw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, Feb 28, 2026 at 5:27 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Fri, Feb 27, 2026 at 8:44 PM Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
> >
> > On Fri, Feb 27, 2026 at 5:01 PM Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
> > >
> > > Thanks for the patches, I am still testing the patches, but sharing a
> > > few initial review comments.
> > >
> >
> > I did few tests on v51 all patches, please find further comments -
> >
> > 1. Partition Related Behavior
> > -----------------------------
> > Setup:
> > CREATE TABLE t_part (id int) PARTITION BY RANGE (id);
> > CREATE TABLE t_part_p1 PARTITION OF t_part FOR VALUES FROM (0) TO (100);
> > CREATE TABLE t_part_p2 (id int);
> > ALTER TABLE t_part ATTACH PARTITION t_part_p2 FOR VALUES FROM (100) TO (200);
> >
> > t_part
> > |_> t_part_p1
> > |_> t_part_p2
> >
> > Publication:
> > create publication pubp1 for ALL TABLES EXCEPT TABLE (t_part);
> > -- No data from all three tables is replicated, which is expected.
> >
> > 1a) DETACH t_part_p2 from parent
> > ALTER TABLE t_part DETACH PARTITION t_part_p2;
> >
> > When t_part_p2 is detached, it becomes a standalone table and is no
> > longer part of the EXCEPT hierarchy. But, replication does not start
> > automatically. It requires REFRESH PUBLICATION on the subscriber.
> > Should we add a warning/hint during DETACH command to inform users
> > that REFRESH PUBLICATION is required?
> > It may also help to update the related documentation.
> >
>
> This is required even when a regular (non-partitioned table) is
> created to let the corresponding entry populated in
> pg_subscription_rel. See docs[1] (REFRESH PUBLICATION ..).
>
> > ~~
> > 1b): Attach the partition again
> > ALTER TABLE t_part ATTACH PARTITION t_part_p2 FOR VALUES FROM (100) TO (200);
> > When the partition is attached back, replication stops immediately as
> > it becomes part of the excluded parent again. No REFRESH PUBLICATION
> > is required on the subscriber. In this case, users may not realize
> > that replication has stopped. Should we consider adding a warning
> > during ATTACH in such scenarios?
> > ~~~~
> >
>
> This is worth considering but my opinion is that we don't need it as
> users should be aware of such behavior. For example, today, if a
> publication has published a root table say tab_root and one of its
> partitions is detached, we should stop that partition's replication
> but do we give WARNING for such cases?
>

I tried, we do not give WARNING for such cases during ATTACH/DETACH on
HEAD. I also feel that a warning for this EXCEPT case (and the
previous one) is not needed.

> > 2. Inherited Tables Behavior
> > Setup:
> > CREATE TABLE t_inh (id int);
> > CREATE TABLE t_inh_c1 (c1 int) INHERITS (t_inh);
> > CREATE TABLE t_inh_c2 (c2 int) INHERITS (t_inh);
> > t_inh
> > |_> t_inh_c1
> > |_> t_inh_c2
> >
> > Publication:
> > create publication pubi1 for ALL TABLES EXCEPT TABLE (t_inh);
> > --All three tables are not replicated.
> >
> > 2a): Remove child from parent
> > alter table t_inh_c1 NO INHERIT t_inh;
> >
> > \d+ t_inh shows:
> > Except Publications:
> > "pubi1"
> > Child tables: t_inh_c2
> >
> > But the publication still shows:
> > Except tables:
> > "public.t_inh"
> > "public.t_inh_c1"
> > "public.t_inh_c2"
> >
> > t_inh_c1 is no longer part of the excluded hierarchy, yet it remains
> > in the EXCEPT list and replication does not start for it.
> > This appears inconsistent and may be a bug.
> >
>
> I think after removal, it shouldn't have been shown here, so, we
> should see why it is happening. OTOH, won't replication requires user
> to perform REFRESH PUBLICATION as in the previous case?
>
> Few other comments:
> 1.
> --- a/src/backend/commands/subscriptioncmds.c
> +++ b/src/backend/commands/subscriptioncmds.c
> @@ -37,6 +37,7 @@
> #include "miscadmin.h"
> #include "nodes/makefuncs.h"
> #include "pgstat.h"
> +#include "replication/logical.h"
> #include "replication/logicallauncher.h"
> #include "replication/logicalworker.h"
> #include "replication/origin.h"
>
> There is no other change in this file, so do we even need this header included?
>
> 2.
> + foreach_oid(pubid, exceptpuboids)
> + {
> + char *pubname = get_publication_name(pubid, false);
> +
> + if (!first)
> + appendStringInfoString(&pubnames, ", ");
> +
> + first = false;
> +
> + appendStringInfoString(&pubnames, quote_literal_cstr(pubname));
> + }
> +
> + ereport(ERROR,
> + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> + errmsg("cannot attach table \"%s\" as partition because it is
> referenced in publication \"%s\" EXCEPT clause",
> + RelationGetRelationName(attachrel), pubnames.data),
> + errdetail("The publication EXCEPT clause cannot contain tables that
> are partitions."),
> + errhint("Remove the table from the publication EXCEPT clause before
> attaching it."));
>
> A. As there could be multiple publications, so errmsg_plural form
> should be used, refer to other places.
> B. I think errhint should be removed from 0001 and added back by 0002
> where you can say how user can remove it by using SET CLAUSE
>
> [1] - https://www.postgresql.org/docs/devel/sql-altersubscription.html
>
> --
> With Regards,
> Amit Kapila.


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-01 12:51:09
Message-ID: CAJpy0uBzHj_ChUPrQx59Xx6=e1bP2LjYWPTt4e9jWHALyUCdaw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sun, Mar 1, 2026 at 5:52 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Sat, Feb 28, 2026 at 7:37 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > On Sat, 28 Feb 2026 at 17:27, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> > >
> > > On Fri, Feb 27, 2026 at 8:44 PM Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
> > > >
> > > > On Fri, Feb 27, 2026 at 5:01 PM Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
> > > > >
> > > > > Thanks for the patches, I am still testing the patches, but sharing a
> > > > > few initial review comments.
> > > > >
> > > >
> > > > I did few tests on v51 all patches, please find further comments -
> > > >
> > > > 1. Partition Related Behavior
> > > > -----------------------------
> > > > Setup:
> > > > CREATE TABLE t_part (id int) PARTITION BY RANGE (id);
> > > > CREATE TABLE t_part_p1 PARTITION OF t_part FOR VALUES FROM (0) TO (100);
> > > > CREATE TABLE t_part_p2 (id int);
> > > > ALTER TABLE t_part ATTACH PARTITION t_part_p2 FOR VALUES FROM (100) TO (200);
> > > >
> > > > t_part
> > > > |_> t_part_p1
> > > > |_> t_part_p2
> > > >
> > > > Publication:
> > > > create publication pubp1 for ALL TABLES EXCEPT TABLE (t_part);
> > > > -- No data from all three tables is replicated, which is expected.
> > > >
> > > > 1a) DETACH t_part_p2 from parent
> > > > ALTER TABLE t_part DETACH PARTITION t_part_p2;
> > > >
> > > > When t_part_p2 is detached, it becomes a standalone table and is no
> > > > longer part of the EXCEPT hierarchy. But, replication does not start
> > > > automatically. It requires REFRESH PUBLICATION on the subscriber.
> > > > Should we add a warning/hint during DETACH command to inform users
> > > > that REFRESH PUBLICATION is required?
> > > > It may also help to update the related documentation.
> > > >
> > >
> > > This is required even when a regular (non-partitioned table) is
> > > created to let the corresponding entry populated in
> > > pg_subscription_rel. See docs[1] (REFRESH PUBLICATION ..).
> > >
> > > > ~~
> > > > 1b): Attach the partition again
> > > > ALTER TABLE t_part ATTACH PARTITION t_part_p2 FOR VALUES FROM (100) TO (200);
> > > > When the partition is attached back, replication stops immediately as
> > > > it becomes part of the excluded parent again. No REFRESH PUBLICATION
> > > > is required on the subscriber. In this case, users may not realize
> > > > that replication has stopped. Should we consider adding a warning
> > > > during ATTACH in such scenarios?
> > > > ~~~~
> > > >
> > >
> > > This is worth considering but my opinion is that we don't need it as
> > > users should be aware of such behavior. For example, today, if a
> > > publication has published a root table say tab_root and one of its
> > > partitions is detached, we should stop that partition's replication
> > > but do we give WARNING for such cases?
> > >
> > > > 2. Inherited Tables Behavior
> > > > Setup:
> > > > CREATE TABLE t_inh (id int);
> > > > CREATE TABLE t_inh_c1 (c1 int) INHERITS (t_inh);
> > > > CREATE TABLE t_inh_c2 (c2 int) INHERITS (t_inh);
> > > > t_inh
> > > > |_> t_inh_c1
> > > > |_> t_inh_c2
> > > >
> > > > Publication:
> > > > create publication pubi1 for ALL TABLES EXCEPT TABLE (t_inh);
> > > > --All three tables are not replicated.
> > > >
> > > > 2a): Remove child from parent
> > > > alter table t_inh_c1 NO INHERIT t_inh;
> > > >
> > > > \d+ t_inh shows:
> > > > Except Publications:
> > > > "pubi1"
> > > > Child tables: t_inh_c2
> > > >
> > > > But the publication still shows:
> > > > Except tables:
> > > > "public.t_inh"
> > > > "public.t_inh_c1"
> > > > "public.t_inh_c2"
> > > >
> > > > t_inh_c1 is no longer part of the excluded hierarchy, yet it remains
> > > > in the EXCEPT list and replication does not start for it.
> > > > This appears inconsistent and may be a bug.
> > > >
> > >
> > > I think after removal, it shouldn't have been shown here, so, we
> > > should see why it is happening.
> >
> > I believe this is existing behavior, and the same applies to
> > table-level publications as well.
> > For example:
> > -- Create table publication
> > create publication pubi1 for table t_inh;
> > \d+ t_inh
> > Table "public.t_inh"
> > Column | Type | Collation | Nullable | Default | Storage |
> > Compression | Stats target | Description
> > --------+---------+-----------+----------+---------+---------+-------------+--------------+-------------
> > id | integer | | | | plain |
> > | |
> > Publications:
> > "pubi1"
> > Child tables: t_inh_c1,
> > t_inh_c2
> >
> > postgres=# \dRp+
> > Publication pubi1
> > Owner | All tables | All sequences | Inserts | Updates | Deletes |
> > Truncates | Generated columns | Via root
> > ---------+------------+---------------+---------+---------+---------+-----------+-------------------+----------
> > vignesh | f | f | t | t | t |
> > t | none | f
> > Tables:
> > "public.t_inh"
> > "public.t_inh_c1"
> > "public.t_inh_c2"
> >
> > --- Remove the inherits for one of the child table
> > postgres=# alter table t_inh_c1 NO INHERIT t_inh;
> > ALTER TABLE
> >
> > --- Publication will still have t_inh_c1 table in case of table publication too
> > postgres=# \dRp+
> > Publication pubi1
> > Owner | All tables | All sequences | Inserts | Updates | Deletes |
> > Truncates | Generated columns | Via root
> > ---------+------------+---------------+---------+---------+---------+-----------+-------------------+----------
> > vignesh | f | f | t | t | t |
> > t | none | f
> > Tables:
> > "public.t_inh"
> > "public.t_inh_c1"
> > "public.t_inh_c2"
> >
> > This occurs because when ONLY is not specified, the table t_inh and
> > all its descendant tables (t_inh_c1 and t_inh_c2) are added to
> > pg_publication_rel at the time the publication is created. Replication
> > then proceeds strictly based on the entries in pg_publication_rel.
> > There is no explicit parent child mapping maintained for these
> > relations in the publication catalog; each table is treated as an
> > independent entry.
> > When "ALTER TABLE t_inh_c1 NO INHERIT t_inh;" is executed later,
> > t_inh_c1 is not automatically removed from the publication. Since it
> > was added as a separate entry in pg_publication_rel, removing the
> > inheritance relationship does not affect its publication membership.
> > I'm not sure whether this is the intended design or an unintended side
> > effect. If this behavior is not expected, we can address it separately
> > and adjust the implementation accordingly.
> >
>
> So, the similar case for partitioned table works because there we add
> only root partitioned table in pg_publication_rel. I understand that
> current behaviour for inherited tables (each inherited table is
> considered separately after being added to the publication) is because
> of the existing design and should be changed separately, if required.
> I haven't checked whether it is possible to change this behavior but
> it appears that we should try to investigate and see the possibility
> of fixing it separately.
>

IMO, we do not need any change in behaviour here.

For inherited tables, publication membership is materialized at the
time the publication is created and is not dynamically derived from
the current inheritance hierarchy. Once inherited tables are added to
a publication, each table is treated as an independent publication
member going forward, regardless of subsequent changes to the
inheritance relationship.
This differs from partitioned tables in PostgreSQL. In the case of
partitioning, publication membership is derived dynamically from the
partition hierarchy. Partitions are not independent logical tables;
they are structural components of a single logical table. Thus
attaching or detaching a partition automatically impacts publication
behavior. IMO, this distinction between inherited and partitioned
tables is fundamental to their design, and thus should be preserved
as-is, including in the context of publications. Or let me know if my
understanding is not correct here.

thanks
Shveta


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-02 04:46:25
Message-ID: CAJpy0uCr15=dxg+bmGeJUoNfKOHU2xZd2Wa6hg=YNTnQzz2fcA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sun, Mar 1, 2026 at 8:41 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
>
> The attached v53 version patch has the changes for the same.
>

Thanks. Please find a few comments on 001:

1)
pg_get_publication_sequences():
- sequences = GetAllPublicationRelations(RELKIND_SEQUENCE, false);
+ sequences = GetAllPublicationRelations(publication, RELKIND_SEQUENCE);

This could be problematic. Earlier we were passing 'false' always for
sequences, now we are letting it extracted from publication which can
be true as well and thus we may hit Assert inside
GetAllPublicationRelations() :

Assert(!(relkind == RELKIND_SEQUENCE && pubviaroot));

As an example, this will assert:
create sequence seq1;
create publication pub1 for all sequences with
(publish_via_partition_root=true);
select * from pg_publication_sequences ;

2)
get_rel_sync_entry():

+ if (pub->pubviaroot)
+ {
+ pub_relid = llast_oid(ancestors);
+ ancestor_level = list_length(ancestors);
+ }
+ else
+ {
+ /*
+ * When publishing partitions individually, we must
+ * still check whether the top-most ancestor is
+ * excluded. If the root is excluded, none of its
+ * partitions should be published.
+ */
+ ancestorexceptpubids = GetRelationExcludedPublications(llast_oid(ancestors));
+ }
+
+ exceptpubids = GetRelationExcludedPublications(pub_relid);

Bot pub->pubviaroot=On/OFF will ultimately end up doing these 2 steps:

---First get llast_oid(ancestors)
-- Then execute GetRelationExcludedPublications(). (outside if-block
but inside else-block)

Why do we need an if-else block at all, as both are doing the same steps?

And why do we need 2 variables except pubids and ancestorexceptpubids?

3)
+bool
+publication_has_any_except_table(Oid pubid)

I do not see its usage anywhere now. Shall we remove it?

4)
+static List *
+GetRelationPublications(Oid relid, bool except_flag)

Since it is static function, we shall rename it to
get_relation_publications() similar to get_publication_relations()

5)
+/* Gets list of publication oids for a relation */
+List *
+GetRelationIncludedPublications(Oid relid)

+/* Gets list of publication oids which has relation in EXCEPT clause */
+List *
+GetRelationExcludedPublications(Oid relid)

We can make comment format multi-line similar to other functions in
this file. See GetAllTablesPublications, GetSchemaPublications etc.

~~
Reviewing further.

thanks
Shveta


From: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-02 07:37:44
Message-ID: CABdArM63hFeqPTqA+ybqrFL3dg4NcdUq1fLKgom=-UW1sjVvJw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, Feb 28, 2026 at 5:27 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Fri, Feb 27, 2026 at 8:44 PM Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
> >
> > On Fri, Feb 27, 2026 at 5:01 PM Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
> > >
> > > Thanks for the patches, I am still testing the patches, but sharing a
> > > few initial review comments.
> > >
> >
> > I did few tests on v51 all patches, please find further comments -
> >
> > 1. Partition Related Behavior
> > -----------------------------
> > Setup:
> > CREATE TABLE t_part (id int) PARTITION BY RANGE (id);
> > CREATE TABLE t_part_p1 PARTITION OF t_part FOR VALUES FROM (0) TO (100);
> > CREATE TABLE t_part_p2 (id int);
> > ALTER TABLE t_part ATTACH PARTITION t_part_p2 FOR VALUES FROM (100) TO (200);
> >
> > t_part
> > |_> t_part_p1
> > |_> t_part_p2
> >
> > Publication:
> > create publication pubp1 for ALL TABLES EXCEPT TABLE (t_part);
> > -- No data from all three tables is replicated, which is expected.
> >
> > 1a) DETACH t_part_p2 from parent
> > ALTER TABLE t_part DETACH PARTITION t_part_p2;
> >
> > When t_part_p2 is detached, it becomes a standalone table and is no
> > longer part of the EXCEPT hierarchy. But, replication does not start
> > automatically. It requires REFRESH PUBLICATION on the subscriber.
> > Should we add a warning/hint during DETACH command to inform users
> > that REFRESH PUBLICATION is required?
> > It may also help to update the related documentation.
> >
>
> This is required even when a regular (non-partitioned table) is
> created to let the corresponding entry populated in
> pg_subscription_rel. See docs[1] (REFRESH PUBLICATION ..).
>

Thanks for the doc link. The expectation seems that when a user adds a
table to a publication, replication of that table will begin after
running REFRESH PUBLICATION. But, in this case, the table is added
indirectly (e.g., via a partition detach), which may not make it
obvious to userthat a refresh is required.

That said, I agree that users can handle it if they are aware of this behavior.

> > ~~
> > 2. Inherited Tables Behavior
> > Setup:
> > CREATE TABLE t_inh (id int);
> > CREATE TABLE t_inh_c1 (c1 int) INHERITS (t_inh);
> > CREATE TABLE t_inh_c2 (c2 int) INHERITS (t_inh);
> > t_inh
> > |_> t_inh_c1
> > |_> t_inh_c2
> >
> > Publication:
> > create publication pubi1 for ALL TABLES EXCEPT TABLE (t_inh);
> > --All three tables are not replicated.
> >
> > 2a): Remove child from parent
> > alter table t_inh_c1 NO INHERIT t_inh;
> >
> > \d+ t_inh shows:
> > Except Publications:
> > "pubi1"
> > Child tables: t_inh_c2
> >
> > But the publication still shows:
> > Except tables:
> > "public.t_inh"
> > "public.t_inh_c1"
> > "public.t_inh_c2"
> >
> > t_inh_c1 is no longer part of the excluded hierarchy, yet it remains
> > in the EXCEPT list and replication does not start for it.
> > This appears inconsistent and may be a bug.
> >
>
> I think after removal, it shouldn't have been shown here, so, we
> should see why it is happening. OTOH, won't replication requires user
> to perform REFRESH PUBLICATION as in the previous case?
>

Yes, this requires the user to run REFRESH PUBLICATION, but
replication still does not start in this case. The user must reset the
EXCEPT TABLE list to start replication for t_inh_c1.

--
Thanks,
Nisha


From: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-02 07:39:07
Message-ID: CABdArM4SR7X4yggWv1MN5O_8JJ=ig8aDsDx=ToxYOFR31ZcCog@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sun, Mar 1, 2026 at 6:21 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Sun, Mar 1, 2026 at 5:52 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> > On Sat, Feb 28, 2026 at 7:37 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > >
> > > This occurs because when ONLY is not specified, the table t_inh and
> > > all its descendant tables (t_inh_c1 and t_inh_c2) are added to
> > > pg_publication_rel at the time the publication is created. Replication
> > > then proceeds strictly based on the entries in pg_publication_rel.
> > > There is no explicit parent child mapping maintained for these
> > > relations in the publication catalog; each table is treated as an
> > > independent entry.
> > > When "ALTER TABLE t_inh_c1 NO INHERIT t_inh;" is executed later,
> > > t_inh_c1 is not automatically removed from the publication. Since it
> > > was added as a separate entry in pg_publication_rel, removing the
> > > inheritance relationship does not affect its publication membership.
> > > I'm not sure whether this is the intended design or an unintended side
> > > effect. If this behavior is not expected, we can address it separately
> > > and adjust the implementation accordingly.
> > >
> >
> > So, the similar case for partitioned table works because there we add
> > only root partitioned table in pg_publication_rel. I understand that
> > current behaviour for inherited tables (each inherited table is
> > considered separately after being added to the publication) is because
> > of the existing design and should be changed separately, if required.
> > I haven't checked whether it is possible to change this behavior but
> > it appears that we should try to investigate and see the possibility
> > of fixing it separately.
> >
>
> IMO, we do not need any change in behaviour here.
>
> For inherited tables, publication membership is materialized at the
> time the publication is created and is not dynamically derived from
> the current inheritance hierarchy. Once inherited tables are added to
> a publication, each table is treated as an independent publication
> member going forward, regardless of subsequent changes to the
> inheritance relationship.
> This differs from partitioned tables in PostgreSQL. In the case of
> partitioning, publication membership is derived dynamically from the
> partition hierarchy. Partitions are not independent logical tables;
> they are structural components of a single logical table. Thus
> attaching or detaching a partition automatically impacts publication
> behavior. IMO, this distinction between inherited and partitioned
> tables is fundamental to their design, and thus should be preserved
> as-is, including in the context of publications. Or let me know if my
> understanding is not correct here.
>

Okay, noted!
My main concern is that whenever a user attaches or detaches a child
table, they must manually reset the publication EXCEPT list if they
want the table to be replicated. The doc under “For inherited
tables...” --

“If ONLY is not specified, the table and all its descendant tables
(if any) are excluded.”

does not clearly state that this applies only at the time of
CREATE/ALTER PUBLICATION, and that users must explicitly handle
changes if the inheritance hierarchy is modified later.

I am fine with updating the doc accordingly.

--
Thanks,
Nisha


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-02 10:18:14
Message-ID: CAJpy0uB=JxTYXOB7VmrhVLR+1PG0=TtHuGekaqibOPpo2UBLiQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

All,

Currently, the syntax we plan to support in patch001 is:

CREATE PUBLICATION pub for ALL TABLES EXCEPT TABLE (tab1, tab2, ...)

That is:

a) The TABLE keyword is mandatory after EXCEPT.
b) Parentheses around the table list are mandatory.

There has been some confusion regarding the EXCEPT syntax. Below are
the points that help justify the above syntax.

1) TABLE keyword:

Consider the command:
CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT (tab1, tab2);

At first glance, this appears acceptable even without the TABLE
keyword after EXCEPT. However, in the future, if we support excluding
a particular schema, for example:

CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT SCHEMA s1, s2;

then it becomes necessary to explicitly specify whether we are
excluding a TABLE, SCHEMA, or SEQUENCE after EXCEPT.

Similarly, if we extend CREATE PUBLICATION to support something like:
CREATE PUBLICATION pub
FOR TABLES, SEQUENCES IN SCHEMA sch1
EXCEPT TABLE (t1), EXCEPT SEQUENCE (s1);

then also, the TABLE or SEQUENCE keyword after EXCEPT becomes
mandatory for clarity.

2) Parentheses:

Currently, we do not use parentheses around table names in commands such as:
CREATE PUBLICATION pub1 FOR TABLE tab1, tab2;

So it may seem acceptable to allow:
CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT tab1, tab2;

However, if we later support syntax like:

CREATE PUBLICATION pub FOR TABLES IN SCHEMA s1 EXCEPT TABLE t;

the future syntax for pub with tables-in-schema with EXCEPT and a
regular table-inclusion might look like:

CREATE PUBLICATION pub FOR TABLES IN SCHEMA s1 EXCEPT TABLE (t1, t2), TABLE t3;

This is much clearer than a version without parentheses:

CREATE PUBLICATION pub FOR TABLES IN SCHEMA s1 EXCEPT TABLE t1, t2, TABLE t3;

In the first version, it is clearly understood that t1 and t2 are
excluded, while t3 is included. Without parentheses, the intent
becomes ambiguous.

Therefore, making both the TABLE keyword and parentheses mandatory
after EXCEPT ensures clarity and extensibility for future
enhancements.

~~

So we will proceed with this syntax unless there are any objections.

thanks
Shveta


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-02 10:48:13
Message-ID: CAA4eK1KDD4soCSZEPn=cOsoMemj0vPmPyNTbiDMmR+9hs_sU+w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sun, Mar 1, 2026 at 8:41 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> The attached v53 version patch has the changes for the same.
>

Few comments on 0001:
===================
1.
+ appendStringInfoString(&pubnames, quote_literal_cstr(pubname));
+ }
+
+ ereport(ERROR,
+ errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg_plural("cannot attach table \"%s\" as partition because it is
referenced in publication \"%s\" EXCEPT clause",
+ "cannot attach table \"%s\" as partition because it is referenced
in publications \"%s\" EXCEPT clause",

Because of the quoting before the error message, the publication names
in the error message will be displayed in single quotes which are
inside double quotes.
See below examples:
ERROR: cannot attach table "testpub_root" as partition because it is
referenced in publication "'testpub8'" EXCEPT clause
ERROR: cannot attach table "testpub_root" as partition because it is
referenced in publications "'testpub8', 'testpub10'" EXCEPT clause

Do you this type of quoting single/multiple object names in error
messages at other places? What is the rationale behind this?

The other place where I see such names is following but it also
doesn't use the pattern followed above:
A.
postgres=# create subscription sub1 connection 'dbname=postgres'
publication pub9, pub10, pub11;
WARNING: publications "pub9", "pub10", "pub11" do not exist on the publisher
postgres=# create subscription sub2 connection 'dbname=postgres'
publication pub12;
WARNING: publication "pub12" does not exist on the publisher

B.
logical replication target relation "public.t10" is missing replicated
columns: "c2", "c3". For this See logicalrep_get_attrs_str and
following error_message
ereport(ERROR,
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg_plural("logical replication target relation \"%s.%s\" is
missing replicated column: %s",
"logical replication target relation \"%s.%s\" is missing replicated
columns: %s",

I think we should follow what is done in logicalrep_get_attrs_str for
message construction and translation.

2.
* pub_all_obj_type is one of:
*
- * TABLES
+ * TABLES [EXCEPT [TABLE] ( table [, ...] )]

Though the table is no longer optional, the above syntax reference
still shows it as optional.

3.
+ List *ancestor_exceptpuboids = GetRelationExcludedPublications(ancestor);;

One spurious semicolon at the end of above statement

4.
@@ -5838,16 +5841,22 @@ RelationBuildPublicationDesc(Relation
relation, PublicationDesc *pubdesc)
foreach(lc, ancestors)
{
Oid ancestor = lfirst_oid(lc);
+ List *ancestor_puboids = GetRelationIncludedPublications(ancestor);
+ List *ancestor_exceptpuboids = GetRelationExcludedPublications(ancestor);;

- puboids = list_concat_unique_oid(puboids,
- GetRelationPublications(ancestor));
+ puboids = list_concat_unique_oid(puboids, ancestor_puboids);
schemaid = get_rel_namespace(ancestor);
puboids = list_concat_unique_oid(puboids,
GetSchemaPublications(schemaid));
+ exceptpuboids = list_concat_unique_oid(exceptpuboids,
+ ancestor_exceptpuboids);
}

Why do we need to get the exceptpuboids for all ancestors instead of
just the top-one as we are doing in get_rel_sync_entry()?

--
With Regards,
Amit Kapila.


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-02 13:21:21
Message-ID: CANhcyEWg8F2J4vbo7yvsY-vf4rAKodVTj6bq5Afdnt8KRGRvPQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 2 Mar 2026 at 16:18, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Sun, Mar 1, 2026 at 8:41 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > The attached v53 version patch has the changes for the same.
> >
>
> Few comments on 0001:
> ===================
> 1.
> + appendStringInfoString(&pubnames, quote_literal_cstr(pubname));
> + }
> +
> + ereport(ERROR,
> + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> + errmsg_plural("cannot attach table \"%s\" as partition because it is
> referenced in publication \"%s\" EXCEPT clause",
> + "cannot attach table \"%s\" as partition because it is referenced
> in publications \"%s\" EXCEPT clause",
>
> Because of the quoting before the error message, the publication names
> in the error message will be displayed in single quotes which are
> inside double quotes.
> See below examples:
> ERROR: cannot attach table "testpub_root" as partition because it is
> referenced in publication "'testpub8'" EXCEPT clause
> ERROR: cannot attach table "testpub_root" as partition because it is
> referenced in publications "'testpub8', 'testpub10'" EXCEPT clause
>
> Do you this type of quoting single/multiple object names in error
> messages at other places? What is the rationale behind this?
>
> The other place where I see such names is following but it also
> doesn't use the pattern followed above:
> A.
> postgres=# create subscription sub1 connection 'dbname=postgres'
> publication pub9, pub10, pub11;
> WARNING: publications "pub9", "pub10", "pub11" do not exist on the publisher
> postgres=# create subscription sub2 connection 'dbname=postgres'
> publication pub12;
> WARNING: publication "pub12" does not exist on the publisher
>
> B.
> logical replication target relation "public.t10" is missing replicated
> columns: "c2", "c3". For this See logicalrep_get_attrs_str and
> following error_message
> ereport(ERROR,
> errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> errmsg_plural("logical replication target relation \"%s.%s\" is
> missing replicated column: %s",
> "logical replication target relation \"%s.%s\" is missing replicated
> columns: %s",
>
> I think we should follow what is done in logicalrep_get_attrs_str for
> message construction and translation.
>
I agree. Made the changes for the same.

> 2.
> * pub_all_obj_type is one of:
> *
> - * TABLES
> + * TABLES [EXCEPT [TABLE] ( table [, ...] )]
>
> Though the table is no longer optional, the above syntax reference
> still shows it as optional.
>
> 3.
> + List *ancestor_exceptpuboids = GetRelationExcludedPublications(ancestor);;
>
> One spurious semicolon at the end of above statement
>
> 4.
> @@ -5838,16 +5841,22 @@ RelationBuildPublicationDesc(Relation
> relation, PublicationDesc *pubdesc)
> foreach(lc, ancestors)
> {
> Oid ancestor = lfirst_oid(lc);
> + List *ancestor_puboids = GetRelationIncludedPublications(ancestor);
> + List *ancestor_exceptpuboids = GetRelationExcludedPublications(ancestor);;
>
> - puboids = list_concat_unique_oid(puboids,
> - GetRelationPublications(ancestor));
> + puboids = list_concat_unique_oid(puboids, ancestor_puboids);
> schemaid = get_rel_namespace(ancestor);
> puboids = list_concat_unique_oid(puboids,
> GetSchemaPublications(schemaid));
> + exceptpuboids = list_concat_unique_oid(exceptpuboids,
> + ancestor_exceptpuboids);
> }
>
> Why do we need to get the exceptpuboids for all ancestors instead of
> just the top-one as we are doing in get_rel_sync_entry()?
>
I agree we should only check the root partitioned table here. Modified the code

I have also addressed the other comments.
I have addressed the comments shared by Shveta in [1].
Attached the updated v54 patch.

[1]: https://www.postgresql.org/message-id/CAJpy0uCr15=dxg+bmGeJUoNfKOHU2xZd2Wa6hg=YNTnQzz2fcA@mail.gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v54-0001-Skip-publishing-the-tables-specified-in-EXCEPT-T.patch application/octet-stream 75.9 KB

From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-03 04:37:38
Message-ID: CAA4eK1+2mL0N8iUdNTr1baO9kJjDZgRGiNTX6cT=ZoBm-m_Lqg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Mar 2, 2026 at 6:51 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> Attached the updated v54 patch.
>

The patch is getting in shape. I have a few minor comments:

1.
+ if (!first)
+ appendStringInfoString(&pubnames, _(", "));
+
+ first = false;
+
+ appendStringInfo(&pubnames, _("\"%s\""), pubname);

Can we have a comment here like "/* translator: This is a separator in
a list of publication names. */" similar to logicalrep_get_attrs_str.

2.
+ List *ancestor_puboids = GetRelationIncludedPublications(ancestor);

- puboids = list_concat_unique_oid(puboids,
- GetRelationPublications(ancestor));
+ puboids = list_concat_unique_oid(puboids, ancestor_puboids);

Why do you choose to take a variable name instead of changing just a
function name?

3.
src/test/subscription/t/037_rep_changes_except_table.pl

How about naming it as 037_except.pl? We would like to add future
except syntax variations in the same test file, so naming just except
would be better.

4.
+ * EXCEPT TABLES is processed here and output directly by
+ * dumpPublication(). This differs from the approach used in
+ * dumpPublicationTable() and dumpPublicationNamespace(), since that
+ * approach would require EXCEPT TABLE support for ALTER PUBLICATION,
+ * which is not currently supported.

Is this comment accurate as per our current implementation of Alter
Publication in 0002 patch? If not, let's change these comments.

5.
+ * Only the top-most ancestor may appear in the EXCEPT
+ * clause. Therefore, for a partition, exclusion must be
+ * evaluated at the top-most ancestor.

/may/can

--
With Regards,
Amit Kapila.


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-03 09:29:11
Message-ID: CAJpy0uA7SKHvi2uZ=W2VaoGvh_5F_BOOUwvGC22L8+t4NBE8jQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 3, 2026 at 10:07 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Mon, Mar 2, 2026 at 6:51 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > Attached the updated v54 patch.
> >
>
> The patch is getting in shape. I have a few minor comments:
>
> 1.
> + if (!first)
> + appendStringInfoString(&pubnames, _(", "));
> +
> + first = false;
> +
> + appendStringInfo(&pubnames, _("\"%s\""), pubname);
>
> Can we have a comment here like "/* translator: This is a separator in
> a list of publication names. */" similar to logicalrep_get_attrs_str.
>
> 2.
> + List *ancestor_puboids = GetRelationIncludedPublications(ancestor);
>
> - puboids = list_concat_unique_oid(puboids,
> - GetRelationPublications(ancestor));
> + puboids = list_concat_unique_oid(puboids, ancestor_puboids);
>
> Why do you choose to take a variable name instead of changing just a
> function name?
>
> 3.
> src/test/subscription/t/037_rep_changes_except_table.pl
>
> How about naming it as 037_except.pl? We would like to add future
> except syntax variations in the same test file, so naming just except
> would be better.
>

+1

> 4.
> + * EXCEPT TABLES is processed here and output directly by
> + * dumpPublication(). This differs from the approach used in
> + * dumpPublicationTable() and dumpPublicationNamespace(), since that
> + * approach would require EXCEPT TABLE support for ALTER PUBLICATION,
> + * which is not currently supported.
>
> Is this comment accurate as per our current implementation of Alter
> Publication in 0002 patch? If not, let's change these comments.
>
> 5.
> + * Only the top-most ancestor may appear in the EXCEPT
> + * clause. Therefore, for a partition, exclusion must be
> + * evaluated at the top-most ancestor.
>
> /may/can
>
> --
> With Regards,
> Amit Kapila.

The patch looks good. I have a few comments already shared by Amit.
Apart from that, one trivial comment

+ * relation with EXCEPT clause; otherwise, returns the list of publications
with --> in

thanks
Shveta


From: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-03 10:15:19
Message-ID: CABdArM7EigxxYREK4nskcfk6XX1nm4ARDhOJtxnfxQ47hF9i_w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Mar 2, 2026 at 6:51 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> Attached the updated v54 patch.
>

Few comments for v54 patch -
1) The partition description shows the publication name which it is
excluded from.
simple test case:

CREATE TABLE t_part (a int) PARTITION BY RANGE(a);
CREATE TABLE t_part_p1 PARTITION OF t_part FOR VALUES FROM (0) TO (100);
CREATE PUBLICATION pub_p1 FOR ALL TABLES EXCEPT TABLE (t_part);
postgres=# \d t_part_p1
Table "public.t_part_p1"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
a | integer | | |
Partition of: t_part FOR VALUES FROM (0) TO (100)
Publications:
"pub_p1"
~~~

2) File: 037_rep_changes_except_table.pl:147
+# Verify that data inserted into a table listed in the EXCEPT clause is not
+# published.
+$result = $node_publisher->safe_psql('postgres',
+ "SELECT count(*) = 0 FROM
pg_logical_slot_get_binary_changes('test_slot', NULL, NULL,
'proto_version', '1', 'publication_names', 'tap_sub_schema')"
+);

There seems to be a mistake in the publication name in the above call
as tap_sub_schema is a subscription name.
~~~
Couple of minor comments:
3) File: pgouput.c
+ /*
+ * For a parition, changes are published via top-most
+ * ancestor when pubviaroot is true, so populate pub_relid
+ * accordingly
+ */

3a) typo parition -> partition
3b) There should be a full stop (.) at the end i.e. after accordingly
~~~

File: pg_publication.c
+ else
+ errormsg = gettext_noop("cannot add relation \"%s\" to publication");
+
+
+ /* If in EXCEPT clause, must be root partitioned table */

>> there is an extra empty line
~~~

--
Thanks,
Nisha


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-03 15:46:44
Message-ID: CANhcyEUwU_4Zr+z7rAoABFUhn3BTdWk+Pv8LnsRpv40dOrM_UQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, 3 Mar 2026 at 15:45, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
>
> On Mon, Mar 2, 2026 at 6:51 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > Attached the updated v54 patch.
> >
>
> Few comments for v54 patch -
> 1) The partition description shows the publication name which it is
> excluded from.
> simple test case:
>
> CREATE TABLE t_part (a int) PARTITION BY RANGE(a);
> CREATE TABLE t_part_p1 PARTITION OF t_part FOR VALUES FROM (0) TO (100);
> CREATE PUBLICATION pub_p1 FOR ALL TABLES EXCEPT TABLE (t_part);
> postgres=# \d t_part_p1
> Table "public.t_part_p1"
> Column | Type | Collation | Nullable | Default
> --------+---------+-----------+----------+---------
> a | integer | | |
> Partition of: t_part FOR VALUES FROM (0) TO (100)
> Publications:
> "pub_p1"
> ~~~
>
Fixed. Added a test for it as well.

> 2) File: 037_rep_changes_except_table.pl:147
> +# Verify that data inserted into a table listed in the EXCEPT clause is not
> +# published.
> +$result = $node_publisher->safe_psql('postgres',
> + "SELECT count(*) = 0 FROM
> pg_logical_slot_get_binary_changes('test_slot', NULL, NULL,
> 'proto_version', '1', 'publication_names', 'tap_sub_schema')"
> +);
>
> There seems to be a mistake in the publication name in the above call
> as tap_sub_schema is a subscription name.
> ~~~
> Couple of minor comments:
> 3) File: pgouput.c
> + /*
> + * For a parition, changes are published via top-most
> + * ancestor when pubviaroot is true, so populate pub_relid
> + * accordingly
> + */
>
> 3a) typo parition -> partition
> 3b) There should be a full stop (.) at the end i.e. after accordingly
> ~~~
>
> File: pg_publication.c
> + else
> + errormsg = gettext_noop("cannot add relation \"%s\" to publication");
> +
> +
> + /* If in EXCEPT clause, must be root partitioned table */
>
> >> there is an extra empty line
> ~~~
>
I have addressed the remaining comments as well.
I have also addressed the comments by Amit and Shveta in [1] and [2].

Attached the latest v55 patch.

[1]: https://www.postgresql.org/message-id/CAA4eK1+2mL0N8iUdNTr1baO9kJjDZgRGiNTX6cT=ZoBm-m_Lqg@mail.gmail.com
[2]: https://www.postgresql.org/message-id/CAJpy0uA7SKHvi2uZ=W2VaoGvh_5F_BOOUwvGC22L8+t4NBE8jQ@mail.gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v55-0001-Allow-table-exclusions-in-publications-via-EXCEP.patch application/octet-stream 76.2 KB

From: vignesh C <vignesh21(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: 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>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-04 08:24:29
Message-ID: CALDaNm2-Ob9qPR+vqUSVMkxYO8RW4LQ_S1XiB0Y7xa54U=DqbA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, 3 Mar 2026 at 21:17, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> On Tue, 3 Mar 2026 at 15:45, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
> >
> > On Mon, Mar 2, 2026 at 6:51 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> > >
> > > Attached the updated v54 patch.
> > >
> >
> > Few comments for v54 patch -
> > 1) The partition description shows the publication name which it is
> > excluded from.
> > simple test case:
> >
> > CREATE TABLE t_part (a int) PARTITION BY RANGE(a);
> > CREATE TABLE t_part_p1 PARTITION OF t_part FOR VALUES FROM (0) TO (100);
> > CREATE PUBLICATION pub_p1 FOR ALL TABLES EXCEPT TABLE (t_part);
> > postgres=# \d t_part_p1
> > Table "public.t_part_p1"
> > Column | Type | Collation | Nullable | Default
> > --------+---------+-----------+----------+---------
> > a | integer | | |
> > Partition of: t_part FOR VALUES FROM (0) TO (100)
> > Publications:
> > "pub_p1"
> > ~~~
> >
> Fixed. Added a test for it as well.
>
> > 2) File: 037_rep_changes_except_table.pl:147
> > +# Verify that data inserted into a table listed in the EXCEPT clause is not
> > +# published.
> > +$result = $node_publisher->safe_psql('postgres',
> > + "SELECT count(*) = 0 FROM
> > pg_logical_slot_get_binary_changes('test_slot', NULL, NULL,
> > 'proto_version', '1', 'publication_names', 'tap_sub_schema')"
> > +);
> >
> > There seems to be a mistake in the publication name in the above call
> > as tap_sub_schema is a subscription name.
> > ~~~
> > Couple of minor comments:
> > 3) File: pgouput.c
> > + /*
> > + * For a parition, changes are published via top-most
> > + * ancestor when pubviaroot is true, so populate pub_relid
> > + * accordingly
> > + */
> >
> > 3a) typo parition -> partition
> > 3b) There should be a full stop (.) at the end i.e. after accordingly
> > ~~~
> >
> > File: pg_publication.c
> > + else
> > + errormsg = gettext_noop("cannot add relation \"%s\" to publication");
> > +
> > +
> > + /* If in EXCEPT clause, must be root partitioned table */
> >
> > >> there is an extra empty line
> > ~~~
> >
> I have addressed the remaining comments as well.
> I have also addressed the comments by Amit and Shveta in [1] and [2].
>
> Attached the latest v55 patch.

Here is an updated version with a couple of typos fixed and separated
the describe table query based on versions which make it more easier
to read.

Regards,
Vignesh

Attachment Content-Type Size
v56-0001-Allow-table-exclusions-in-publications-via-EXCEP.patch application/octet-stream 76.1 KB

From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-04 09:19:07
Message-ID: CAJpy0uAW8NhTPXo8GSOk_dUuTjKDY9RthRvh9merXoqThuvNbQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Mar 4, 2026 at 1:54 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> Here is an updated version with a couple of typos fixed and separated
> the describe table query based on versions which make it more easier
> to read.
>

v56 LGTM.

thanks
Shveta


From: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-04 09:21:13
Message-ID: CABdArM4qh7Uc2nWo9vfDozuLbnwtqHF--AvRpMj_TkVaEAHzig@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Mar 4, 2026 at 1:54 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> Here is an updated version with a couple of typos fixed and separated
> the describe table query based on versions which make it more easier
> to read.
>

Thanks for the patch. It LGTM, no further comments.

--
Thanks,
Nisha


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-04 11:00:48
Message-ID: CAA4eK1+xJAwtYFsquKTbJu0-PGy-KHUtGiqn-c4RhibCXTT_FA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Mar 4, 2026 at 2:49 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Wed, Mar 4, 2026 at 1:54 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > Here is an updated version with a couple of typos fixed and separated
> > the describe table query based on versions which make it more easier
> > to read.
> >
>
> v56 LGTM.
>

Pushed.

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-05 09:35:42
Message-ID: CALDaNm1ALHQwkXBcDALA1MxPMk1niBf+fK4rYQxkHxH2PgnPCA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 4 Mar 2026 at 16:31, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Wed, Mar 4, 2026 at 2:49 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > On Wed, Mar 4, 2026 at 1:54 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > >
> > > Here is an updated version with a couple of typos fixed and separated
> > > the describe table query based on versions which make it more easier
> > > to read.
> > >
> >
> > v56 LGTM.
> >
>
> Pushed.

Here is the rebased patch for the remaining items in the patch series.

Regards,
Vignesh

Attachment Content-Type Size
v57-0001-Support-SET-EXCEPT-TABLE-in-ALTER-PUBLICATION.patch application/octet-stream 25.1 KB
v57-0002-Support-DROP-EXCEPT-TABLE-in-ALTER-PUBLICATION.patch application/octet-stream 13.6 KB

From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-05 11:52:09
Message-ID: CAJpy0uBa-NOSJ0YPTMn-ad9umQ+zDgt8JG4-J1g+oRbp=7nrAg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Mar 5, 2026 at 3:05 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
>
> Here is the rebased patch for the remaining items in the patch series.
>

Thanks. Please find a few comments for 001:

1)
alter_publication.sgml:

The SET clause will replace the list of except tables/tables/schemas
in the publication with the specified list

The order is difficult to read. Would it be better to say it in this
order: tables/schemas/except-tables

2)
postgres=# ALTER TABLE tab_top_root ATTACH PARTITION tab_root FOR
VALUES FROM (0) TO (2000);
ERROR: cannot attach table "tab_root" as partition because it is
referenced in publications "pub1", "pub3" EXCEPT clause
DETAIL: The publication EXCEPT clause cannot contain tables that are
partitions.
HINT: Modify the publication's EXCEPT clause using ALTER PUBLICATION
... SET EXCEPT TABLE or DROP EXCEPT TABLE before attaching the table.

Shall we shorten the HINT slightly? Is it necessary to explicitly say
"before attaching the table", or can we omit it? Thoughts?

3)
+ if (has_except_table)
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("EXCEPT TABLE clause allowed only for ALL TABLES PUBLICATION"));
+

In what scenario will we hit it? I could not find one.

4)
-- fail - can't add an EXCEPT TABLE to 'FOR TABLE' publication
ALTER PUBLICATION testpub_fortable ADD EXCEPT TABLE (testpub_tbl1);
ERROR: EXCEPT TABLE clause allowed only for SET clause

Even though the comment says that it is a test for not allowing EXCEPT
TABLE for 'FOR TABLE' (perhaps trying to hit the error in comment 3),
it ultimately hits another error that EXCEPT is not supported with
'ADD'. I think the error in comment-3 is unreachable. Or let me know
if otherwise.
We need to correct the comment here.

5)
-- fail - can't drop an EXCEPT TABLE from 'FOR TABLE' publication
ALTER PUBLICATION testpub_fortable DROP EXCEPT TABLE (testpub_tbl1);
ERROR: EXCEPT TABLE clause allowed only for SET clause

Same is valid for this, comment (i.e. the intent) and error does not match.

~~

Please check other test-cases too for intent and error. There are many
like above.

thanks
Shveta


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-06 03:23:30
Message-ID: CAA4eK1KAq+4aQjyOgzD3hBcD7=vTCDT7kbpSKi8aNs=gu7Es4w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Mar 5, 2026 at 5:22 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> 2)
> postgres=# ALTER TABLE tab_top_root ATTACH PARTITION tab_root FOR
> VALUES FROM (0) TO (2000);
> ERROR: cannot attach table "tab_root" as partition because it is
> referenced in publications "pub1", "pub3" EXCEPT clause
> DETAIL: The publication EXCEPT clause cannot contain tables that are
> partitions.
> HINT: Modify the publication's EXCEPT clause using ALTER PUBLICATION
> ... SET EXCEPT TABLE or DROP EXCEPT TABLE before attaching the table.
>
> Shall we shorten the HINT slightly? Is it necessary to explicitly say
> "before attaching the table", or can we omit it? Thoughts?
>

I think we can omit it.

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-06 08:17:06
Message-ID: CALDaNm3CAqU4H6Pswvqm8OAWFD6Ygj0TKyUkeOfX-BY1m_aiRA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 5 Mar 2026 at 17:22, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Thu, Mar 5, 2026 at 3:05 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> >
> > Here is the rebased patch for the remaining items in the patch series.
> >
>
> Thanks. Please find a few comments for 001:
>
>
> 1)
> alter_publication.sgml:
>
> The SET clause will replace the list of except tables/tables/schemas
> in the publication with the specified list
>
> The order is difficult to read. Would it be better to say it in this
> order: tables/schemas/except-tables

I have changed it to tables/except tables/schemas to keep tables together

> 2)
> postgres=# ALTER TABLE tab_top_root ATTACH PARTITION tab_root FOR
> VALUES FROM (0) TO (2000);
> ERROR: cannot attach table "tab_root" as partition because it is
> referenced in publications "pub1", "pub3" EXCEPT clause
> DETAIL: The publication EXCEPT clause cannot contain tables that are
> partitions.
> HINT: Modify the publication's EXCEPT clause using ALTER PUBLICATION
> ... SET EXCEPT TABLE or DROP EXCEPT TABLE before attaching the table.
>
> Shall we shorten the HINT slightly? Is it necessary to explicitly say
> "before attaching the table", or can we omit it? Thoughts?

Modified to omit it.

> 3)
> + if (has_except_table)
> + ereport(ERROR,
> + errcode(ERRCODE_SYNTAX_ERROR),
> + errmsg("EXCEPT TABLE clause allowed only for ALL TABLES PUBLICATION"));
> +
>
> In what scenario will we hit it? I could not find one.

It will hit in this scenario, also added a test for thi:
create publication pub2 for except table (t1);
ERROR: EXCEPT TABLE clause allowed only for ALL TABLES PUBLICATION

> 4)
> -- fail - can't add an EXCEPT TABLE to 'FOR TABLE' publication
> ALTER PUBLICATION testpub_fortable ADD EXCEPT TABLE (testpub_tbl1);
> ERROR: EXCEPT TABLE clause allowed only for SET clause
>
> Even though the comment says that it is a test for not allowing EXCEPT
> TABLE for 'FOR TABLE' (perhaps trying to hit the error in comment 3),
> it ultimately hits another error that EXCEPT is not supported with
> 'ADD'. I think the error in comment-3 is unreachable. Or let me know
> if otherwise.
> We need to correct the comment here.

This test can be removed as the error comes from the parser itself and
there is one test already with testpub_foralltables_excepttable. This
will be returned from:
| ALTER PUBLICATION name ADD_P pub_obj_list
{
+ bool has_except_table = false;
AlterPublicationStmt *n =
makeNode(AlterPublicationStmt);

n->pubname = $3;
n->pubobjects = $5;
-
preprocess_pubobj_list(n->pubobjects, yyscanner);
+ has_except_table =
preprocess_pubobj_list(n->pubobjects,
+
yyscanner);
+ if (has_except_table)
+ ereport(ERROR,
+
errcode(ERRCODE_SYNTAX_ERROR),
+
errmsg("EXCEPT TABLE clause allowed only for SET clause"));
+
n->action = AP_AddObjects;
$$ = (Node *) n;
}

> 5)
> -- fail - can't drop an EXCEPT TABLE from 'FOR TABLE' publication
> ALTER PUBLICATION testpub_fortable DROP EXCEPT TABLE (testpub_tbl1);
> ERROR: EXCEPT TABLE clause allowed only for SET clause
>
> Same is valid for this, comment (i.e. the intent) and error does not match.

This test can be removed as the error comes from the parser itself and
there is one test already with testpub_foralltables_excepttable.

Thanks for the comments, the attached v58 version patch has the
changes for the same.

Regards,
Vignesh

Attachment Content-Type Size
v58-0002-Support-DROP-EXCEPT-TABLE-in-ALTER-PUBLICATION.patch application/octet-stream 14.0 KB
v58-0001-Support-SET-EXCEPT-TABLE-in-ALTER-PUBLICATION.patch application/octet-stream 24.5 KB

From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-06 10:56:39
Message-ID: CAA4eK1Lx25rc3-HcquKB5vZi0kNhP91_u_Waxu8V-qbiDP2aYg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Mar 6, 2026 at 1:47 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>

Instead of a syntax like "ALTER PUBLICATION pub1 DROP EXCEPT TABLE t1"
to allow resetting the entire except list by incrementally dropping
the except tables, I could think of following alternatives

Option-1: ALTER PUBLICATION pub1 SET ALL TABLES; This suggests it is
still an ALL TABLES publication, but providing a new definition. Since
it didn't include an EXCEPT clause this time, the exception list is
now empty.

Option-2: ALTER PUBLICATION pub1 SET EXCEPT TABLE DEFAULT; Since the
"default" state of an ALL TABLES publication is to have zero
exceptions, the "default" will serve as an alias for an empty list.

If we follow the first one, then we can choose "ALTER PUBLICATION pub1
SET ALL TABLES EXCEPT TABLE (t1)" to set a new except list instead of
"ALTER PUBLICATION pub1 SET EXCEPT TABLE (t1)"

--
With Regards,
Amit Kapila.


From: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-06 11:20:53
Message-ID: CABdArM5ovXVW7o7MxEKJp4sbwmczPq_Wp5Ppfzhu=_p32ctZBA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Mar 6, 2026 at 1:47 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> Thanks for the comments, the attached v58 version patch has the
> changes for the same.
>

Thanks for the patches. I reviewed and tested v58-0001, and here are a
few comments:

1) alter_publication.sgml
+<phrase>where <replaceable
class="parameter">publication_set_object</replaceable> is one
of:</phrase>
+
+ EXCEPT TABLE [ ONLY ] ( <replaceable
class="parameter">table_name</replaceable> [, ... ] )

Should ONLY be moved inside parentheses(), as it applies per table:-
EXCEPT TABLE ( [ ONLY ] table_name [, ...] )

2) publicationcmds.c
postgres=# alter publication pub2 set EXCEPT TABLE (t3);
ERROR: publication "pub2" is not defined as FOR ALL TABLES
DETAIL: EXCEPT Tables cannot be added to publications that are not
defined as FOR ALL TABLES.

The DETAIL message “EXCEPT Tables cannot be added …” could be adjusted , e.g.,
EXCEPT tables cannot be added ...
or
EXCEPT TABLE cannot be used for publications ...

3) gram.y
The comments above "AlterPublicationStmt:" should be updated for the
newly supported command.

--
Thanks,
Nisha


From: Andrei Lepikhov <lepihov(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-06 12:55:23
Message-ID: 109c66bc-2871-4fba-8dc1-c57d183e9515@gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On 6/3/26 11:56, Amit Kapila wrote:
> On Fri, Mar 6, 2026 at 1:47 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>>
>
> Instead of a syntax like "ALTER PUBLICATION pub1 DROP EXCEPT TABLE t1"
> to allow resetting the entire except list by incrementally dropping
> the except tables, I could think of following alternatives

IMO, using the 'DROP' syntax is an unusual choice because it does not
match how an alter publication process actually happens.

>
> Option-1: ALTER PUBLICATION pub1 SET ALL TABLES; This suggests it is
> still an ALL TABLES publication, but providing a new definition. Since
> it didn't include an EXCEPT clause this time, the exception list is
> now empty.

I vote for a style that allows incremental add/remove table.

> If we follow the first one, then we can choose "ALTER PUBLICATION pub1
> SET ALL TABLES EXCEPT TABLE (t1)" to set a new except list instead of
> "ALTER PUBLICATION pub1 SET EXCEPT TABLE (t1)"
This approach works best for me. It also matches the internal
replication logic: take the new publication state, compare it with the
old one, and process the differences.

--
regards, Andrei Lepikhov,
pgEdge


From: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-06 13:19:50
Message-ID: CAFiTN-vqyG_EJjuxi3PyqqATsWks3ZKJFy1CEKiF6T=08Mz0QA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Mar 6, 2026 at 4:26 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Fri, Mar 6, 2026 at 1:47 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
>
> Instead of a syntax like "ALTER PUBLICATION pub1 DROP EXCEPT TABLE t1"
> to allow resetting the entire except list by incrementally dropping
> the except tables, I could think of following alternatives
>
> Option-1: ALTER PUBLICATION pub1 SET ALL TABLES; This suggests it is
> still an ALL TABLES publication, but providing a new definition. Since
> it didn't include an EXCEPT clause this time, the exception list is
> now empty.
>
> Option-2: ALTER PUBLICATION pub1 SET EXCEPT TABLE DEFAULT; Since the
> "default" state of an ALL TABLES publication is to have zero
> exceptions, the "default" will serve as an alias for an empty list.
>
> If we follow the first one, then we can choose "ALTER PUBLICATION pub1
> SET ALL TABLES EXCEPT TABLE (t1)" to set a new except list instead of
> "ALTER PUBLICATION pub1 SET EXCEPT TABLE (t1)"

I prefer Option-1 as it provides a consistent extension of the
existing CREATE PUBLICATION syntax. Since we already use FOR ALL
TABLES and FOR ALL TABLES EXCEPT... during CREATE PUBLICATION,
applying the same logic to ALTER PUBLICATION is intuitive and
maintains a uniform experience for the user. So +1 for Option-1.

--
Regards,
Dilip Kumar
Google


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Andrei Lepikhov <lepihov(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-07 01:11:46
Message-ID: CAA4eK1J2DN0y821pDjhi-xYVfyiLqHVpHXf6OhTP-RGhErtqPw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Mar 6, 2026 at 6:25 PM Andrei Lepikhov <lepihov(at)gmail(dot)com> wrote:
>
> On 6/3/26 11:56, Amit Kapila wrote:
> >
> > Option-1: ALTER PUBLICATION pub1 SET ALL TABLES; This suggests it is
> > still an ALL TABLES publication, but providing a new definition. Since
> > it didn't include an EXCEPT clause this time, the exception list is
> > now empty.
>
> I vote for a style that allows incremental add/remove table.
>
> > If we follow the first one, then we can choose "ALTER PUBLICATION pub1
> > SET ALL TABLES EXCEPT TABLE (t1)" to set a new except list instead of
> > "ALTER PUBLICATION pub1 SET EXCEPT TABLE (t1)"
> This approach works best for me. It also matches the internal
> replication logic: take the new publication state, compare it with the
> old one, and process the differences.
>

So, to summarize based on your and Dilip's inputs, the following
syntax will be preferable to set/reset EXCEPT list: (a) To set a
except table list to a different list than what is defined originally,
we will use: "ALTER PUBLICATION pub1 SET ALL TABLES EXCEPT TABLE (t1,
..)" (b) To reset the entire except list, we will use "ALTER
PUBLICATION pub1 SET ALL TABLES". Do let me know if I misunderstood
your response?

Thanks for the input.

--
With Regards,
Amit Kapila.


From: Andrei Lepikhov <lepihov(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-08 14:37:15
Message-ID: 78e4016c-b75a-4076-97b8-437d01a1563c@gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On 7/3/26 02:11, Amit Kapila wrote:
> On Fri, Mar 6, 2026 at 6:25 PM Andrei Lepikhov <lepihov(at)gmail(dot)com> wrote:
> So, to summarize based on your and Dilip's inputs, the following
> syntax will be preferable to set/reset EXCEPT list: (a) To set a
> except table list to a different list than what is defined originally,
> we will use: "ALTER PUBLICATION pub1 SET ALL TABLES EXCEPT TABLE (t1,
> ..)" (b) To reset the entire except list, we will use "ALTER
> PUBLICATION pub1 SET ALL TABLES". Do let me know if I misunderstood
> your response?
Yes, that's correct. Variants a and b seem the clearest to me.

--
regards, Andrei Lepikhov,
pgEdge


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Andrei Lepikhov <lepihov(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-09 02:52:31
Message-ID: CALDaNm34tpJDVxEr70dmggY6sWyJxvaSuHN+pW2B6skTtjs46A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, 7 Mar 2026 at 06:41, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Fri, Mar 6, 2026 at 6:25 PM Andrei Lepikhov <lepihov(at)gmail(dot)com> wrote:
> >
> > On 6/3/26 11:56, Amit Kapila wrote:
> > >
> > > Option-1: ALTER PUBLICATION pub1 SET ALL TABLES; This suggests it is
> > > still an ALL TABLES publication, but providing a new definition. Since
> > > it didn't include an EXCEPT clause this time, the exception list is
> > > now empty.
> >
> > I vote for a style that allows incremental add/remove table.
> >
> > > If we follow the first one, then we can choose "ALTER PUBLICATION pub1
> > > SET ALL TABLES EXCEPT TABLE (t1)" to set a new except list instead of
> > > "ALTER PUBLICATION pub1 SET EXCEPT TABLE (t1)"
> > This approach works best for me. It also matches the internal
> > replication logic: take the new publication state, compare it with the
> > old one, and process the differences.
> >
>
> So, to summarize based on your and Dilip's inputs, the following
> syntax will be preferable to set/reset EXCEPT list: (a) To set a
> except table list to a different list than what is defined originally,
> we will use: "ALTER PUBLICATION pub1 SET ALL TABLES EXCEPT TABLE (t1,
> ..)" (b) To reset the entire except list, we will use "ALTER
> PUBLICATION pub1 SET ALL TABLES".

The attached v59 patch has the changes to update the syntax accordingly.

Regards,
Vignesh

Attachment Content-Type Size
v59-0001-Support-SET-ALL-TABLES-EXCEPT-TABLE-in-ALTER-PUB.patch application/octet-stream 22.6 KB

From: vignesh C <vignesh21(at)gmail(dot)com>
To: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-09 04:32:26
Message-ID: CALDaNm3fjf7EAdpGcHpwaq01EowbS1U-KcPU3VZzt8eZs3ThgA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 6 Mar 2026 at 16:51, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
>
> On Fri, Mar 6, 2026 at 1:47 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > Thanks for the comments, the attached v58 version patch has the
> > changes for the same.
> >
>
> Thanks for the patches. I reviewed and tested v58-0001, and here are a
> few comments:
>
> 1) alter_publication.sgml
> +<phrase>where <replaceable
> class="parameter">publication_set_object</replaceable> is one
> of:</phrase>
> +
> + EXCEPT TABLE [ ONLY ] ( <replaceable
> class="parameter">table_name</replaceable> [, ... ] )
>
> Should ONLY be moved inside parentheses(), as it applies per table:-
> EXCEPT TABLE ( [ ONLY ] table_name [, ...] )

Modified

> 2) publicationcmds.c
> postgres=# alter publication pub2 set EXCEPT TABLE (t3);
> ERROR: publication "pub2" is not defined as FOR ALL TABLES
> DETAIL: EXCEPT Tables cannot be added to publications that are not
> defined as FOR ALL TABLES.
>
> The DETAIL message “EXCEPT Tables cannot be added …” could be adjusted , e.g.,
> EXCEPT tables cannot be added ...
> or
> EXCEPT TABLE cannot be used for publications ...

I felt the current message is in line with the existing messages in
that function. So not making any change.

> 3) gram.y
> The comments above "AlterPublicationStmt:" should be updated for the
> newly supported command.

Updated

The v59 version patch attached at [1] has the changes for the same.
[1] - https://www.postgresql.org/message-id/CALDaNm34tpJDVxEr70dmggY6sWyJxvaSuHN%2BpW2B6skTtjs46A%40mail.gmail.com

Regards,
Vignesh


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Andrei Lepikhov <lepihov(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-09 04:36:00
Message-ID: CAJpy0uAWyaorY4NzreVM5hURQYY7hKpj=c8dWziF3GBkFDvLJw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Mar 9, 2026 at 8:22 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
>
> The attached v59 patch has the changes to update the syntax accordingly.
>

Thanks for the patch. I have attached my suggestion for doc change,
please take it if you find it appropriate.

Reviewing further.

thanks
Shveta

Attachment Content-Type Size
0001-doc-change.patch.txt text/plain 3.1 KB

From: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Andrei Lepikhov <lepihov(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-09 07:00:42
Message-ID: CABdArM65WySkXh0KSTdpX2cxKEPBdGGTt693vhpgAdW-uH97JQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Mar 9, 2026 at 8:22 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> The attached v59 patch has the changes to update the syntax accordingly.
>
Thanks for the patch, here are few comments:

1) commit message:
"... the user must first modify
the publication using ALTER PUBLICATION ... SET EXCEPT TABLE
before attaching the partition."

The command is modified now and "SET EXCEPT TABLE" is no longer
supported, so it should be -

"... the user must first modify
the publication using ALTER PUBLICATION ... SET ALL TABLES EXCEPT TABLE
before attaching the partition."
~~~

2) Unexpected behavior: "ALTER PUBLICATION pub1 SET ALL TABLES;"
succeeds for a non-ALL TABLES publication and removes the existing
tables from the publication:

CREATE publication pub1 for table t1;

postgres=# \dRp+
Publication pub1
Owner | All tables | All sequences | Inserts | Updates | Deletes |
Truncates | Generated columns | Via root | Description
---------+------------+---------------+---------+---------+---------+-----------+-------------------+----------+-------------
moond_n | f | f | t | t | t |
t | none | f |
Tables:
"public.t1"

postgres=# alter publication pub1 set all tables ;
ALTER PUBLICATION

postgres=# \dRp+
Publication pub1
Owner | All tables | All sequences | Inserts | Updates | Deletes |
Truncates | Generated columns | Via root | Description
---------+------------+---------------+---------+---------+---------+-----------+-------------------+----------+-------------
moond_n | f | f | t | t | t |
t | none | f |
(1 row)

3) Should we add a test for "ALTER PUBLICATION tab_pub SET ALL
TABLES;" verification?

--
Thanks,
Nisha


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Andrei Lepikhov <lepihov(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-09 07:34:45
Message-ID: CAA4eK1LoAqAkLqAM1C=LV1LcacPR-4pe58AZYOAp9F8c+fYKnw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Mar 9, 2026 at 8:22 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> The attached v59 patch has the changes to update the syntax accordingly.
>

Creation of FOR ALL TABLES publications requires superuser privileges.
See following code in CreatePublication()

---
/* FOR ALL TABLES and FOR ALL SEQUENCES requires superuser */
if (!superuser())
{
if (stmt->for_all_tables || stmt->for_all_sequences)
ereport(ERROR,
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to create a FOR ALL TABLES or ALL SEQUENCES
publication"));
}
---

Similarly, won't altering them also require the superuser privilege? I
don't see the corresponding code in the patch.

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Andrei Lepikhov <lepihov(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-09 10:53:37
Message-ID: CALDaNm0=PhFy8jQuDGe0JguXWWvxVNb5hp2+h9JauH3d9w-ceg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 9 Mar 2026 at 13:04, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Mon, Mar 9, 2026 at 8:22 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > The attached v59 patch has the changes to update the syntax accordingly.
> >
>
> Creation of FOR ALL TABLES publications requires superuser privileges.
> See following code in CreatePublication()
>
> ---
> /* FOR ALL TABLES and FOR ALL SEQUENCES requires superuser */
> if (!superuser())
> {
> if (stmt->for_all_tables || stmt->for_all_sequences)
> ereport(ERROR,
> errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> errmsg("must be superuser to create a FOR ALL TABLES or ALL SEQUENCES
> publication"));
> }
> ---
>
> Similarly, won't altering them also require the superuser privilege? I
> don't see the corresponding code in the patch.

This is addressed in the v60 version patch attached.
Also Nisha's comments from [1] and Shveta's comments from [2] are
handled in the v60 version.

[1] - https://www.postgresql.org/message-id/CABdArM65WySkXh0KSTdpX2cxKEPBdGGTt693vhpgAdW-uH97JQ%40mail.gmail.com
[2] - https://www.postgresql.org/message-id/CAJpy0uAWyaorY4NzreVM5hURQYY7hKpj%3Dc8dWziF3GBkFDvLJw%40mail.gmail.com

Regards,
Vignesh

Attachment Content-Type Size
v60-0001-Support-SET-ALL-TABLES-EXCEPT-TABLE-in-ALTER-PUB.patch application/octet-stream 26.4 KB

From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Andrei Lepikhov <lepihov(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-10 04:54:48
Message-ID: CAA4eK1KTW78BMmrHXy2c_UUFa8MxxTuzLe8dnEaKFGXH1x0mEg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Mar 9, 2026 at 4:23 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> This is addressed in the v60 version patch attached.
> Also Nisha's comments from [1] and Shveta's comments from [2] are
> handled in the v60 version.
>

*
+ /* Check that user is allowed to manipulate the publication. */
+ if (excepttables && !pubform->puballtables)
+ ereport(ERROR,
+ errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("publication \"%s\" is not defined as FOR ALL TABLES",
+ NameStr(pubform->pubname)),
+ errdetail("Except tables cannot be added to or dropped from
publications that are not defined as FOR ALL TABLES."));
+
+ /*
+ * SET ALL TABLES is allowed only for publications defined as FOR ALL
+ * TABLES.
+ */
+ if (stmt->action == AP_SetObjects && !pubform->puballtables &&
+ !tables && !excepttables && !schemaidlist)
+ ereport(ERROR,
+ errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("publication \"%s\" is not defined as FOR ALL TABLES",
+ NameStr(pubform->pubname)));
+
+ /* Only a superuser can add or remove EXCEPT tables */
+ if (stmt->action == AP_SetObjects &&
+ (excepttables || (!tables && !excepttables && !schemaidlist)) &&
+ !superuser())
+ ereport(ERROR,
+ errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to add or drop except tables"));

All the above checks are trying to drive the answer to whether the new
Alter statement is for_all_tables via indirect checks. Why not keep
for_all_tables boolean variable in AlterPublicationStmt similar to
CreatePublicationStmt? That should simplify the above checks.

* Also, the superuser check should be earlier in the code, say just
after following existing check:
if ((stmt->action == AP_AddObjects || stmt->action == AP_SetObjects) &&
schemaidlist && !superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to add or set schemas")));

--
With Regards,
Amit Kapila.


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Andrei Lepikhov <lepihov(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-10 05:46:01
Message-ID: CAJpy0uBX--yT47P8=U78aKa1Rc4VKem59r2AuhtXaYd1SGubkA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 10, 2026 at 10:25 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Mon, Mar 9, 2026 at 4:23 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > This is addressed in the v60 version patch attached.
> > Also Nisha's comments from [1] and Shveta's comments from [2] are
> > handled in the v60 version.
> >
>
> *
> + /* Check that user is allowed to manipulate the publication. */
> + if (excepttables && !pubform->puballtables)
> + ereport(ERROR,
> + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> + errmsg("publication \"%s\" is not defined as FOR ALL TABLES",
> + NameStr(pubform->pubname)),
> + errdetail("Except tables cannot be added to or dropped from
> publications that are not defined as FOR ALL TABLES."));
> +
> + /*
> + * SET ALL TABLES is allowed only for publications defined as FOR ALL
> + * TABLES.
> + */
> + if (stmt->action == AP_SetObjects && !pubform->puballtables &&
> + !tables && !excepttables && !schemaidlist)
> + ereport(ERROR,
> + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> + errmsg("publication \"%s\" is not defined as FOR ALL TABLES",
> + NameStr(pubform->pubname)));
> +
> + /* Only a superuser can add or remove EXCEPT tables */
> + if (stmt->action == AP_SetObjects &&
> + (excepttables || (!tables && !excepttables && !schemaidlist)) &&
> + !superuser())
> + ereport(ERROR,
> + errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> + errmsg("must be superuser to add or drop except tables"));
>
> All the above checks are trying to drive the answer to whether the new
> Alter statement is for_all_tables via indirect checks. Why not keep
> for_all_tables boolean variable in AlterPublicationStmt similar to
> CreatePublicationStmt? That should simplify the above checks.
>

+1

> * Also, the superuser check should be earlier in the code, say just
> after following existing check:
> if ((stmt->action == AP_AddObjects || stmt->action == AP_SetObjects) &&
> schemaidlist && !superuser())
> ereport(ERROR,
> (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> errmsg("must be superuser to add or set schemas")));
>

I too thought about it, but then it seems the current order of check
gives better error (IMO). As an example consider where pub1 is a
publication for explicit tables, then doing 'ALTER PUB SET ALL TABLES'
on it should give the error that 'pub1 is not for ALL TABLES' rather
than 'must be superuser'. Because even if ownership was correct, it
was not going to work.

Currently:

postgres=> alter publication pub1 set all tables;
ERROR: publication "pub1" is not defined as FOR ALL TABLES

And for pub2 which is for all tables, we get user error:

postgres=> alter publication pub2 set all tables;
ERROR: must be superuser to add or drop except tables

The errors in both cases seem correct to me. What do you think?

Thanks
Shveta


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Andrei Lepikhov <lepihov(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-10 06:17:32
Message-ID: CAA4eK1+hOujZNuczYg6xVMMB0H96Co3TuuuKRvUjNNMgQ_xz3g@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 10, 2026 at 11:16 AM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Tue, Mar 10, 2026 at 10:25 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
>
> > * Also, the superuser check should be earlier in the code, say just
> > after following existing check:
> > if ((stmt->action == AP_AddObjects || stmt->action == AP_SetObjects) &&
> > schemaidlist && !superuser())
> > ereport(ERROR,
> > (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> > errmsg("must be superuser to add or set schemas")));
> >
>
> I too thought about it, but then it seems the current order of check
> gives better error (IMO). As an example consider where pub1 is a
> publication for explicit tables, then doing 'ALTER PUB SET ALL TABLES'
> on it should give the error that 'pub1 is not for ALL TABLES' rather
> than 'must be superuser'. Because even if ownership was correct, it
> was not going to work.
>
> Currently:
>
> postgres=> alter publication pub1 set all tables;
> ERROR: publication "pub1" is not defined as FOR ALL TABLES
>
> And for pub2 which is for all tables, we get user error:
>
> postgres=> alter publication pub2 set all tables;
> ERROR: must be superuser to add or drop except tables
>
> The errors in both cases seem correct to me. What do you think?
>

I still feel superuser check should be first and the user should get
that when it tries to use FOR ALL TABLES. Also, the better error
message for the same would be: "must be superuser to define FOR ALL
TABLES publication"

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Andrei Lepikhov <lepihov(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-10 12:49:34
Message-ID: CALDaNm2h8GW6B8rohNMpi0D3UQ5rpnJTVmAjaVWsrAtavE17iw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, 10 Mar 2026 at 10:25, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Mon, Mar 9, 2026 at 4:23 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > This is addressed in the v60 version patch attached.
> > Also Nisha's comments from [1] and Shveta's comments from [2] are
> > handled in the v60 version.
> >
>
> *
> + /* Check that user is allowed to manipulate the publication. */
> + if (excepttables && !pubform->puballtables)
> + ereport(ERROR,
> + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> + errmsg("publication \"%s\" is not defined as FOR ALL TABLES",
> + NameStr(pubform->pubname)),
> + errdetail("Except tables cannot be added to or dropped from
> publications that are not defined as FOR ALL TABLES."));
> +
> + /*
> + * SET ALL TABLES is allowed only for publications defined as FOR ALL
> + * TABLES.
> + */
> + if (stmt->action == AP_SetObjects && !pubform->puballtables &&
> + !tables && !excepttables && !schemaidlist)
> + ereport(ERROR,
> + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> + errmsg("publication \"%s\" is not defined as FOR ALL TABLES",
> + NameStr(pubform->pubname)));
> +
> + /* Only a superuser can add or remove EXCEPT tables */
> + if (stmt->action == AP_SetObjects &&
> + (excepttables || (!tables && !excepttables && !schemaidlist)) &&
> + !superuser())
> + ereport(ERROR,
> + errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> + errmsg("must be superuser to add or drop except tables"));
>
> All the above checks are trying to drive the answer to whether the new
> Alter statement is for_all_tables via indirect checks. Why not keep
> for_all_tables boolean variable in AlterPublicationStmt similar to
> CreatePublicationStmt? That should simplify the above checks.
>
> * Also, the superuser check should be earlier in the code, say just
> after following existing check:
> if ((stmt->action == AP_AddObjects || stmt->action == AP_SetObjects) &&
> schemaidlist && !superuser())
> ereport(ERROR,
> (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> errmsg("must be superuser to add or set schemas")));

Thanks for the comments, these are addressed in the v61 version patch attached.

Regards,
Vignesh

Attachment Content-Type Size
v61-0001-Add-support-for-EXCEPT-TABLE-in-ALTER-PUBLICATIO.patch application/octet-stream 27.2 KB

From: Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-10 20:54:31
Message-ID: CAD21AoBdE5GXw6PayASYUEkrWi6UQ6fNeOsuxf_+wVMkLZzOMA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Mar 4, 2026 at 3:01 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Wed, Mar 4, 2026 at 2:49 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > On Wed, Mar 4, 2026 at 1:54 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > >
> > > Here is an updated version with a couple of typos fixed and separated
> > > the describe table query based on versions which make it more easier
> > > to read.
> > >
> >
> > v56 LGTM.
> >
>
> Pushed.

Sorry for joining the discussion late.

I've tried with the new EXCEPT clause and I have some questions about
the newly introduced syntax. With this feature, we can now write:

CREATE PUBLICATION pub FOR ALL TABLES EXCEPT TABLE (a, b, c);

The exclusion table list is written in the form of TABLE (a, b, c) but
it's quite different from the inclusion table list we can specify
(e.g., TABLE a, TABLE b, TABLE c). I'm concerned that it could confuse
users. Have these points already been discussed? Also, isn't the TABLE
after EXCEPT redundant?

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-11 03:24:46
Message-ID: CAJpy0uB20MhJJEaPJdm31t4fykJ+fChA_76jU2P9HX5knbJvAA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Mar 11, 2026 at 2:25 AM Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com> wrote:
>
> On Wed, Mar 4, 2026 at 3:01 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> > On Wed, Mar 4, 2026 at 2:49 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> > >
> > > On Wed, Mar 4, 2026 at 1:54 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > > >
> > > > Here is an updated version with a couple of typos fixed and separated
> > > > the describe table query based on versions which make it more easier
> > > > to read.
> > > >
> > >
> > > v56 LGTM.
> > >
> >
> > Pushed.
>
> Sorry for joining the discussion late.
>
> I've tried with the new EXCEPT clause and I have some questions about
> the newly introduced syntax. With this feature, we can now write:
>
> CREATE PUBLICATION pub FOR ALL TABLES EXCEPT TABLE (a, b, c);
>
> The exclusion table list is written in the form of TABLE (a, b, c) but
> it's quite different from the inclusion table list we can specify
> (e.g., TABLE a, TABLE b, TABLE c). I'm concerned that it could confuse
> users. Have these points already been discussed? Also, isn't the TABLE
> after EXCEPT redundant?
>

Thanks for the question.

Yes, these concerns were discussed earlier when the EXCEPT syntax was
introduced. The current syntax:

CREATE PUBLICATION pub FOR ALL TABLES EXCEPT TABLE (a, b, c);

was chosen intentionally, mainly for extensibility and to avoid
ambiguity in future enhancements.

1. TABLE keyword after EXCEPT

At first glance, the TABLE keyword might appear redundant. However, it
becomes important if we later extend the syntax to allow excluding
other object types, such as schemas or sequences. For example:

CREATE PUBLICATION pub FOR ALL TABLES
EXCEPT SCHEMA (s1, s2), EXCEPT TABLE (t1, t2);

or potentially more complex combinations such as:

CREATE PUBLICATION pub
FOR TABLES, SEQUENCES IN SCHEMA sch1
EXCEPT TABLE (t1), EXCEPT SEQUENCE (s1);

In such cases, explicitly specifying TABLE (or SCHEMA, SEQUENCE, etc.)
after EXCEPT avoids ambiguity and keeps the syntax consistent.

2. Parentheses around the exclusion list

Parentheses are required to clearly separate the excluded objects from
other elements in the publication definition, especially when mixed
with inclusion clauses. For example, consider a future case like:

CREATE PUBLICATION pub
FOR TABLES IN SCHEMA s1
EXCEPT TABLE (t1, t2), TABLE t3;

Here it is clear that t1 and t2 are excluded, while t3 is explicitly
included. Without parentheses, a statement like:

CREATE PUBLICATION pub
FOR TABLES IN SCHEMA s1
EXCEPT TABLE t1, t2, TABLE t3;

would be harder to interpret and potentially ambiguous.

So although the syntax differs slightly from the existing inclusion
list (e.g., TABLE a, b), requiring both the TABLE keyword and
parentheses after EXCEPT helps keep the grammar unambiguous and makes
the syntax easier to extend in the future.

Original discussion is at [1].

[1]: https://www.postgresql.org/message-id/CAJpy0uB%3DJxTYXOB7VmrhVLR%2B1PG0%3DTtHuGekaqibOPpo2UBLiQ%40mail.gmail.com

thanks
Shveta


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Andrei Lepikhov <lepihov(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-11 04:59:59
Message-ID: CAJpy0uBwitVoe5se_tyFC=NF5uxHu__XK-CiDODkTrYpC+2PaQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 10, 2026 at 6:19 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
>
> Thanks for the comments, these are addressed in the v61 version patch attached.
>

I don't have any further comments. The patch LGTM.

thanks
Shveta.


From: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Andrei Lepikhov <lepihov(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-11 05:41:29
Message-ID: CABdArM7avCmv+QbtPwDnF9J7gPnOqECCVj74hEt+pfSEzcKKHw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 10, 2026 at 6:19 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> Thanks for the comments, these are addressed in the v61 version patch attached.
>
Thanks for the patch, I have few comments:

1) publicationcmd.c: CheckAlterPublication()
After the recent change to use stmt->for_all_tables, the
"excepttables" parameter is no longer used in this function and can be
removed.
~~~

Couple of minor suggestions:
2)
+ if (stmt->for_all_tables && !superuser())
+ ereport(ERROR,
+ errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to define FOR ALL TABLES publication"));
+

Since this check is in the context of ALTER PUBLICATION, should the
error message instead be:
"must be superuser to alter FOR ALL TABLES publication"

3) test comment in publication.sql:1015 -
"-- fail - ADD/DROP EXCEPT table requires superuser privileges"
The test uses only SET, not ADD/DROP, so the comment could be updated to:

-- fail - modifying EXCEPT table list requires superuser privileges
(I’m also fine with any better alternative.)

--
Thanks,
Nisha


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Andrei Lepikhov <lepihov(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-11 10:07:36
Message-ID: CALDaNm1SGJtJq_W68khExG1EL4ZmyZ2U7JSc1Z3FsYr4nSbi_A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 11 Mar 2026 at 11:11, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> wrote:
>
> On Tue, Mar 10, 2026 at 6:19 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > Thanks for the comments, these are addressed in the v61 version patch attached.
> >
> Thanks for the patch, I have few comments:
>
> 1) publicationcmd.c: CheckAlterPublication()
> After the recent change to use stmt->for_all_tables, the
> "excepttables" parameter is no longer used in this function and can be
> removed.
> ~~~
>
> Couple of minor suggestions:
> 2)
> + if (stmt->for_all_tables && !superuser())
> + ereport(ERROR,
> + errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
> + errmsg("must be superuser to define FOR ALL TABLES publication"));
> +
>
> Since this check is in the context of ALTER PUBLICATION, should the
> error message instead be:
> "must be superuser to alter FOR ALL TABLES publication"
>
> 3) test comment in publication.sql:1015 -
> "-- fail - ADD/DROP EXCEPT table requires superuser privileges"
> The test uses only SET, not ADD/DROP, so the comment could be updated to:
>
> -- fail - modifying EXCEPT table list requires superuser privileges
> (I’m also fine with any better alternative.)

These comments are addressed in the v62 version patch attached.

Regards,
Vignesh

Attachment Content-Type Size
v62-0001-Add-support-for-EXCEPT-TABLE-in-ALTER-PUBLICATIO.patch application/octet-stream 26.8 KB

From: Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-11 17:53:22
Message-ID: CAD21AoCC8XuwfX62qKBSfHUAoww_XB3_84HjswgL9jxQy696yw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 10, 2026 at 8:24 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Wed, Mar 11, 2026 at 2:25 AM Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com> wrote:
> >
> > On Wed, Mar 4, 2026 at 3:01 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> > >
> > > On Wed, Mar 4, 2026 at 2:49 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> > > >
> > > > On Wed, Mar 4, 2026 at 1:54 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > > > >
> > > > > Here is an updated version with a couple of typos fixed and separated
> > > > > the describe table query based on versions which make it more easier
> > > > > to read.
> > > > >
> > > >
> > > > v56 LGTM.
> > > >
> > >
> > > Pushed.
> >
> > Sorry for joining the discussion late.
> >
> > I've tried with the new EXCEPT clause and I have some questions about
> > the newly introduced syntax. With this feature, we can now write:
> >
> > CREATE PUBLICATION pub FOR ALL TABLES EXCEPT TABLE (a, b, c);
> >
> > The exclusion table list is written in the form of TABLE (a, b, c) but
> > it's quite different from the inclusion table list we can specify
> > (e.g., TABLE a, TABLE b, TABLE c). I'm concerned that it could confuse
> > users. Have these points already been discussed? Also, isn't the TABLE
> > after EXCEPT redundant?
> >
>
> Thanks for the question.
>
> Yes, these concerns were discussed earlier when the EXCEPT syntax was
> introduced. The current syntax:
>
> CREATE PUBLICATION pub FOR ALL TABLES EXCEPT TABLE (a, b, c);
>
> was chosen intentionally, mainly for extensibility and to avoid
> ambiguity in future enhancements.
>
> 1. TABLE keyword after EXCEPT
>
> At first glance, the TABLE keyword might appear redundant. However, it
> becomes important if we later extend the syntax to allow excluding
> other object types, such as schemas or sequences. For example:
>
> CREATE PUBLICATION pub FOR ALL TABLES
> EXCEPT SCHEMA (s1, s2), EXCEPT TABLE (t1, t2);
>
> or potentially more complex combinations such as:
>
> CREATE PUBLICATION pub
> FOR TABLES, SEQUENCES IN SCHEMA sch1
> EXCEPT TABLE (t1), EXCEPT SEQUENCE (s1);
>
> In such cases, explicitly specifying TABLE (or SCHEMA, SEQUENCE, etc.)
> after EXCEPT avoids ambiguity and keeps the syntax consistent.

I understand that it's for future extension but I'm still unsure that
users would not be confused by the fact that the syntaxes of inclusion
list and exclusion list are different; TABLES IN SCHEMA s1 vs. SCHEMA
(s1).

>
> 2. Parentheses around the exclusion list
>
> Parentheses are required to clearly separate the excluded objects from
> other elements in the publication definition, especially when mixed
> with inclusion clauses. For example, consider a future case like:
>
> CREATE PUBLICATION pub
> FOR TABLES IN SCHEMA s1
> EXCEPT TABLE (t1, t2), TABLE t3;
>
> Here it is clear that t1 and t2 are excluded, while t3 is explicitly
> included. Without parentheses, a statement like:
>
> CREATE PUBLICATION pub
> FOR TABLES IN SCHEMA s1
> EXCEPT TABLE t1, t2, TABLE t3;
>
> would be harder to interpret and potentially ambiguous.
>
> So although the syntax differs slightly from the existing inclusion
> list (e.g., TABLE a, b), requiring both the TABLE keyword and
> parentheses after EXCEPT helps keep the grammar unambiguous and makes
> the syntax easier to extend in the future.

I'm still unsure that the syntax like TABLE (t1, t2) for the exclusion
list is syntactically correct. The syntax of TABLE (...) is already
used in a quite different way as follows (borrowed an example from
stats_import.sql):

CREATE FUNCTION stats_import.pg_statistic_get_difference(a text, b text)
RETURNS TABLE (relname text, stats stats_import.pg_statistic_flat_t)
BEGIN ATOMIC
WITH aset AS (SELECT * FROM stats_import.pg_statistic_flat(a)),
bset AS (SELECT * FROM stats_import.pg_statistic_flat(b))
SELECT a AS relname, a_minus_b::stats_import.pg_statistic_flat_t
FROM (TABLE aset EXCEPT TABLE bset) AS a_minus_b
UNION ALL
SELECT b AS relname, b_minus_a::stats_import.pg_statistic_flat_t
FROM (TABLE bset EXCEPT TABLE aset) AS b_minus_a;
END;

Wouldn't it be more appropriate to use a plural form or the IN
keyword, such as EXCEPT TABLES (t1, t2) or EXCEPT TABLES IN (t1, t2)?

Or if we might want to add multiple items in the EXCEPT clause in the
future we can have parentheses around all exclusion items as follow:

CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, TABLE t2,
TABLES IN SCHEMA s1);
CREATE PUBLICATION pub FOR TABLES IN SCHEMA s1 EXCEPT (TABLE t1, TABLE
t2), TABLE t3;

> Original discussion is at [1].

Thanks. I'll read the discussion.

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-12 09:47:37
Message-ID: CAHut+PuyYsTfY57o63A4Wsu4AZ=VPuG+UXz7UwtjLb+90nNSrg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Mar 2, 2026 at 9:18 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>

After a couple of weeks away, I have been trying to catch up on what
became of this feature.

I was surprised by the late syntax change to make the TABLE keyword
now mandatory in EXCEPT TABLE. My initial impression is that it forces
the user to write an unnecessarily verbose command like:

CREATE PUBLICATION pub FOR ALL TABLES EXCEPT TABLE (tab1,tab2);
vs
CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (tab1,tab2);

And the examples to justify making this mandatory [1] are not quite
correct, AFAICT.

Let's look at those in more detail:

>
> Currently, the syntax we plan to support in patch001 is:
>
> CREATE PUBLICATION pub for ALL TABLES EXCEPT TABLE (tab1, tab2, ...)
>
> That is:
>
> a) The TABLE keyword is mandatory after EXCEPT.
> b) Parentheses around the table list are mandatory.
>
> There has been some confusion regarding the EXCEPT syntax. Below are
> the points that help justify the above syntax.
>
> 1) TABLE keyword:
>
> Consider the command:
> CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT (tab1, tab2);
>
> At first glance, this appears acceptable even without the TABLE
> keyword after EXCEPT. However, in the future, if we support excluding
> a particular schema, for example:
>
> CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT SCHEMA s1, s2;
>
> then it becomes necessary to explicitly specify whether we are
> excluding a TABLE, SCHEMA, or SEQUENCE after EXCEPT.

SEQUENCE? -- Hm, this example is "FOR ALL TABLES" -- emphasis on
*tables* -- sequences have nothing to do with "FOR ALL TABLES": they
would be handled by a "FOR ALL SEQUENCES" command.

TABLE v SCHEMA? -- I agree that if there will be some future way for
excluding all tables from certain schemas, then you will need to be
able to distinguish excluded schemas from excluded tables. However,
the command in this example is "FOR ALL TABLES" -- emphasis on
*tables* -- so IMO omission of TABLE keyword can still be understood
to mean the default behaviour because the type is very clear.

e.g. all these are unambiguous to me
CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (tab1,tab2);
CREATE PUBLICATION pub FOR ALL TABLES EXCEPT TABLE (tab1,tab2);
CREATE PUBLICATION pub FOR ALL TABLES EXCEPT SCHEMA (sch1,sch2);

and combinations too:
CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (tab1,tab2) SCHEMA (sch1,sch2);
CREATE PUBLICATION pub FOR ALL TABLES EXCEPT TABLE (tab1,tab2) SCHEMA
(sch1 sch2);

>
> Similarly, if we extend CREATE PUBLICATION to support something like:
> CREATE PUBLICATION pub
> FOR TABLES, SEQUENCES IN SCHEMA sch1
> EXCEPT TABLE (t1), EXCEPT SEQUENCE (s1);
>
> then also, the TABLE or SEQUENCE keyword after EXCEPT becomes
> mandatory for clarity.
>

That example seemed bogus to me. If in future we allow to publish
sequences by schema, then IMO that future syntax would be like:
CREATE PUBLICATION pub1 FOR SEQUENCES IN SCHEMA sch1;

Then, exclusions would look like:
CREATE PUBLICATION pub1 FOR SEQUENCES IN SCHEMA sch1 EXCEPT SEQUENCE
(seq1,seq2);

But here the SEQUENCE keyword is also optional because the type
(sequences) is already clear from the command!

So above is the same as:
CREATE PUBLICATION pub1 FOR SEQUENCES IN SCHEMA sch1 EXCEPT (seq1,seq2);

Therefore, the equivalent of your example would be:
CREATE PUBLICATION pub1 FOR TABLES IN SCHEMA sch1 EXCEPT TABLE (tab1),
FOR SEQUENCES IN SCHEMA sch1 EXCEPT SEQUENCE (seq1);

or (omitting optional keywords)
CREATE PUBLICATION pub1 FOR TABLES IN SCHEMA sch1 EXCEPT (tab1), FOR
SEQUENCES IN SCHEMA sch1 EXCEPT (seq1);

~~~

Summary.

* Must the TABLE (or other type) keyword be mandatory to clarify what
the excluded type is? No, I don't think so; the default type the
command refers to is unambiguous already.

* Does making the TABLE (or other type) mandatory make it easier for
the end-user? I'm not so sure. Saying just EXCEPT (tab1) instead of
EXCEPT TABLE (tab1,tab2) seemed more natural to me.

* Was it just easier to implement when mandatory? Probably true.

* Isn't this analogous to "ALTER TABLE ADD/DROP/ALTER [COLUMN]"
commands [2]? PostgreSQL doesn't force the user to type the
unnecessary COLUMN keyword.

IMO, none of the examples/reasons given justified why the TABLE needed
to be made mandatory. Certainly, the CREATE PUBLICATION command is
already long enough without enforcing redundant keywords.

======
[1] https://www.postgresql.org/message-id/CAJpy0uB%3DJxTYXOB7VmrhVLR%2B1PG0%3DTtHuGekaqibOPpo2UBLiQ%40mail.gmail.com
[2] https://www.postgresql.org/docs/current/sql-altertable.html

Kind Regards,
Peter Smith.
Fujitsu Australia


From: "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>
To: 'Masahiko Sawada' <sawada(dot)mshk(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Skipping schema changes in publication
Date: 2026-03-12 11:50:39
Message-ID: OS9PR01MB12149EA0C749BC29C7C949E32F544A@OS9PR01MB12149.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Dear Sawada-san,

> I'm still unsure that the syntax like TABLE (t1, t2) for the exclusion
> list is syntactically correct. The syntax of TABLE (...) is already
> used in a quite different way as follows (borrowed an example from
> stats_import.sql):
>
> CREATE FUNCTION stats_import.pg_statistic_get_difference(a text, b text)
> RETURNS TABLE (relname text, stats stats_import.pg_statistic_flat_t)
> BEGIN ATOMIC
> WITH aset AS (SELECT * FROM stats_import.pg_statistic_flat(a)),
> bset AS (SELECT * FROM stats_import.pg_statistic_flat(b))
> SELECT a AS relname, a_minus_b::stats_import.pg_statistic_flat_t
> FROM (TABLE aset EXCEPT TABLE bset) AS a_minus_b
> UNION ALL
> SELECT b AS relname, b_minus_a::stats_import.pg_statistic_flat_t
> FROM (TABLE bset EXCEPT TABLE aset) AS b_minus_a;
> END;
>
> Wouldn't it be more appropriate to use a plural form or the IN
> keyword, such as EXCEPT TABLES (t1, t2) or EXCEPT TABLES IN (t1, t2)?

But there is an existing syntax to list target tables, FOR TABLE t1, t2, t3...,
which does not have the plural. Current rule is to use the singular for
specifying the exact table, and we follow.

> Or if we might want to add multiple items in the EXCEPT clause in the
> future we can have parentheses around all exclusion items as follow:
>
> CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, TABLE t2,
> TABLES IN SCHEMA s1);
> CREATE PUBLICATION pub FOR TABLES IN SCHEMA s1 EXCEPT (TABLE t1,
> TABLE
> t2), TABLE t3;

I agree those alternatives could work, but one downside is the redundant use of
"TABLE" when many tables are excluded. If we want to stay consistent with the
existing style, perhaps we could write it as:

```
CREATE PUBLICATION pub FOR ALL TABLES EXCPET (TABLE t1, t2, t3);
```

Because we have already been accepting the syntax like "FOR TABLE t1, t2, t3".

Best regards,
Hayato Kuroda
FUJITSU LIMITED


From: Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>
To: "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-12 16:46:09
Message-ID: CAD21AoBbZEshyaK0PeiF_J4_S75EfF=Gcs=C+X-osoVoUnawuQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Mar 12, 2026 at 4:50 AM Hayato Kuroda (Fujitsu)
<kuroda(dot)hayato(at)fujitsu(dot)com> wrote:
>
> Dear Sawada-san,
>
> > I'm still unsure that the syntax like TABLE (t1, t2) for the exclusion
> > list is syntactically correct. The syntax of TABLE (...) is already
> > used in a quite different way as follows (borrowed an example from
> > stats_import.sql):
> >
> > CREATE FUNCTION stats_import.pg_statistic_get_difference(a text, b text)
> > RETURNS TABLE (relname text, stats stats_import.pg_statistic_flat_t)
> > BEGIN ATOMIC
> > WITH aset AS (SELECT * FROM stats_import.pg_statistic_flat(a)),
> > bset AS (SELECT * FROM stats_import.pg_statistic_flat(b))
> > SELECT a AS relname, a_minus_b::stats_import.pg_statistic_flat_t
> > FROM (TABLE aset EXCEPT TABLE bset) AS a_minus_b
> > UNION ALL
> > SELECT b AS relname, b_minus_a::stats_import.pg_statistic_flat_t
> > FROM (TABLE bset EXCEPT TABLE aset) AS b_minus_a;
> > END;
> >
> > Wouldn't it be more appropriate to use a plural form or the IN
> > keyword, such as EXCEPT TABLES (t1, t2) or EXCEPT TABLES IN (t1, t2)?
>
> But there is an existing syntax to list target tables, FOR TABLE t1, t2, t3...,
> which does not have the plural. Current rule is to use the singular for
> specifying the exact table, and we follow.

"TABLE t1, t2, t3" and "TABLE (t1, t2, t3)" are different to me since
the latter reminds me of TABLE (...) syntax for defining a returning
table.

> > Or if we might want to add multiple items in the EXCEPT clause in the
> > future we can have parentheses around all exclusion items as follow:
> >
> > CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, TABLE t2,
> > TABLES IN SCHEMA s1);
> > CREATE PUBLICATION pub FOR TABLES IN SCHEMA s1 EXCEPT (TABLE t1,
> > TABLE
> > t2), TABLE t3;
>
> I agree those alternatives could work, but one downside is the redundant use of
> "TABLE" when many tables are excluded. If we want to stay consistent with the
> existing style, perhaps we could write it as:
>
> ```
> CREATE PUBLICATION pub FOR ALL TABLES EXCPET (TABLE t1, t2, t3);
> ```
>
> Because we have already been accepting the syntax like "FOR TABLE t1, t2, t3".
>

Yeah, we can omit the TABLE keyword for the second and subsequent
tables. My whole point is that using different syntaxes for the
inclusion list and the exclusion list would quite confuse users.

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>
Cc: "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-13 03:24:45
Message-ID: CAHut+PssG+sHeV+Xo0g=S7xBb9FgDPjHYDR4iSuOdYXDq-Psng@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Mar 13, 2026 at 3:46 AM Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com> wrote:
>
> On Thu, Mar 12, 2026 at 4:50 AM Hayato Kuroda (Fujitsu)
> <kuroda(dot)hayato(at)fujitsu(dot)com> wrote:
> >
> > Dear Sawada-san,
> >
> > > I'm still unsure that the syntax like TABLE (t1, t2) for the exclusion
> > > list is syntactically correct. The syntax of TABLE (...) is already
> > > used in a quite different way as follows (borrowed an example from
> > > stats_import.sql):
> > >
> > > CREATE FUNCTION stats_import.pg_statistic_get_difference(a text, b text)
> > > RETURNS TABLE (relname text, stats stats_import.pg_statistic_flat_t)
> > > BEGIN ATOMIC
> > > WITH aset AS (SELECT * FROM stats_import.pg_statistic_flat(a)),
> > > bset AS (SELECT * FROM stats_import.pg_statistic_flat(b))
> > > SELECT a AS relname, a_minus_b::stats_import.pg_statistic_flat_t
> > > FROM (TABLE aset EXCEPT TABLE bset) AS a_minus_b
> > > UNION ALL
> > > SELECT b AS relname, b_minus_a::stats_import.pg_statistic_flat_t
> > > FROM (TABLE bset EXCEPT TABLE aset) AS b_minus_a;
> > > END;
> > >
> > > Wouldn't it be more appropriate to use a plural form or the IN
> > > keyword, such as EXCEPT TABLES (t1, t2) or EXCEPT TABLES IN (t1, t2)?
> >
> > But there is an existing syntax to list target tables, FOR TABLE t1, t2, t3...,
> > which does not have the plural. Current rule is to use the singular for
> > specifying the exact table, and we follow.
>
> "TABLE t1, t2, t3" and "TABLE (t1, t2, t3)" are different to me since
> the latter reminds me of TABLE (...) syntax for defining a returning
> table.
>
> > > Or if we might want to add multiple items in the EXCEPT clause in the
> > > future we can have parentheses around all exclusion items as follow:
> > >
> > > CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, TABLE t2,
> > > TABLES IN SCHEMA s1);
> > > CREATE PUBLICATION pub FOR TABLES IN SCHEMA s1 EXCEPT (TABLE t1,
> > > TABLE
> > > t2), TABLE t3;
> >
> > I agree those alternatives could work, but one downside is the redundant use of
> > "TABLE" when many tables are excluded. If we want to stay consistent with the
> > existing style, perhaps we could write it as:
> >
> > ```
> > CREATE PUBLICATION pub FOR ALL TABLES EXCPET (TABLE t1, t2, t3);
> > ```
> >
> > Because we have already been accepting the syntax like "FOR TABLE t1, t2, t3".
> >
>
> Yeah, we can omit the TABLE keyword for the second and subsequent
> tables. My whole point is that using different syntaxes for the
> inclusion list and the exclusion list would quite confuse users.
>

Hou-San (off-list) gave an interesting example of how it might look
when the example is combined with the hypothetical future ability to
exclude all schema tables from a "FOR ALL TABLES"
CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, t2, TABLES IN
SCHEMA s1);

The syntax starts to look more complicated when there are multiple
schemas, but IMO it is still perfectly fine.
e.g. FOR ALL TABLES EXCEPT (TABLE t1, t2, TABLES IN SCHEMA s1, s2);

AFAICT, it is doable. The synopsis syntax changes are something like this:
------
and publication_all_object is one of:
ALL TABLES [ EXCEPT ( except_table_list_object [, ... ] ) ]
ALL SEQUENCES

and except_table_list_object is:
TABLE except_table_object [, ...]
TABLES IN SCHEMA schema_name [, ...]

and except_table_object is:
[ ONLY ] table_name [ * ]
------

This gives the user flexibility to name the type however they want to:
e.g. EXCEPT (TABLE t1, TABLE t2, TABLE t3)
e.g. EXCEPT (TABLE t1, t2, t3)
e.g. EXCEPT (TABLE t1, t2, TABLE t3)
e.g. EXCEPT (TABLE t1, TABLES IN SCHEMA s1, s2, TABLE t2, t3);

You get all the flexibility (e.g. which ellipses are expanded) for
free from the grammar, and it is already very typical lists in the
existing CREATE PUBLICATION command, which allow things like:
e.g. CREATE PUBLICATION pub FOR TABLE t1,t2, TABLE t3;

This syntax LGTM because
* User is not required to repeat TABLE keyword multiple times (but
they can if they want to)
* The exclusion lists inside the EXCEPT look and work the same as the
inclusion lists of CREATE PUBLICATION

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-13 09:51:34
Message-ID: CAA4eK1LaSfAG7UAuy1xpnkWKM_YtrPuhbgAxYBFY3Sp_v_KqoQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Mar 13, 2026 at 8:55 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hou-San (off-list) gave an interesting example of how it might look
> when the example is combined with the hypothetical future ability to
> exclude all schema tables from a "FOR ALL TABLES"
> CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, t2, TABLES IN
> SCHEMA s1);
>

So, if we follow this, in future, the syntax would look like:
Create publication pub1 FOR ALL TABLES EXCEPT (TABLE t1, t2, TABLES IN
SCHEMA s1, s2), ALL SEQUENCES EXCEPT (SEQUENCE s1);

I think if we use the above syntax then one can also argue that why
not use FOR ALL (TABLES, SEQUENCES) instead of ALL TABLES, ALL
SEQUENCES.

Instead the current command would like:
Create publication pub1 FOR ALL TABLES EXCEPT TABLE (t1, t2), EXCEPT
TABLES IN SCHEMA (s1, s2), ALL SEQUENCES EXCEPT SEQUENCE (seq1, seq2);

Though it is slightly lengthy it makes the syntax local such that the
meaning of a clause is determined by what is inside it, not by
something that appears ten words later.

--
With Regards,
Amit Kapila.


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-13 10:00:05
Message-ID: CAA4eK1J4MHS7Y9XKTrjhcMN9nkPe0dw5oiRa4nCK1qr1cOF__A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Mar 11, 2026 at 11:24 PM Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com> wrote:
>
> >
> > 2. Parentheses around the exclusion list
> >
> > Parentheses are required to clearly separate the excluded objects from
> > other elements in the publication definition, especially when mixed
> > with inclusion clauses. For example, consider a future case like:
> >
> > CREATE PUBLICATION pub
> > FOR TABLES IN SCHEMA s1
> > EXCEPT TABLE (t1, t2), TABLE t3;
> >
> > Here it is clear that t1 and t2 are excluded, while t3 is explicitly
> > included. Without parentheses, a statement like:
> >
> > CREATE PUBLICATION pub
> > FOR TABLES IN SCHEMA s1
> > EXCEPT TABLE t1, t2, TABLE t3;
> >
> > would be harder to interpret and potentially ambiguous.
> >
> > So although the syntax differs slightly from the existing inclusion
> > list (e.g., TABLE a, b), requiring both the TABLE keyword and
> > parentheses after EXCEPT helps keep the grammar unambiguous and makes
> > the syntax easier to extend in the future.
>
> I'm still unsure that the syntax like TABLE (t1, t2) for the exclusion
> list is syntactically correct. The syntax of TABLE (...) is already
> used in a quite different way as follows (borrowed an example from
> stats_import.sql):
>
> CREATE FUNCTION stats_import.pg_statistic_get_difference(a text, b text)
> RETURNS TABLE (relname text, stats stats_import.pg_statistic_flat_t)
>

Both are different usage and not clear if they are comparable.

>
> Wouldn't it be more appropriate to use a plural form or the IN
> keyword, such as EXCEPT TABLES (t1, t2) or EXCEPT TABLES IN (t1, t2)?
>

We can consider it. Let's try to compare it with following existing
publication syntax:

CREATE PUBLICATION production_publication FOR TABLE users,
departments, TABLES IN SCHEMA production;
CREATE PUBLICATION alltables FOR ALL TABLES;

Here we used singular form when a user could specify one or more
objects and plural when all objects of schema or database are
considered.

As per this, the except syntax falls in the singular category which is
in favor of current syntax.

--
With Regards,
Amit Kapila.


From: Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-13 18:21:16
Message-ID: CAD21AoAb8E8krN63cY_U7RQs9v-zkqUZyKT_UVKDwKfExtvTBg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Mar 13, 2026 at 2:51 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Fri, Mar 13, 2026 at 8:55 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >
> > Hou-San (off-list) gave an interesting example of how it might look
> > when the example is combined with the hypothetical future ability to
> > exclude all schema tables from a "FOR ALL TABLES"
> > CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, t2, TABLES IN
> > SCHEMA s1);
> >
>
> So, if we follow this, in future, the syntax would look like:
> Create publication pub1 FOR ALL TABLES EXCEPT (TABLE t1, t2, TABLES IN
> SCHEMA s1, s2), ALL SEQUENCES EXCEPT (SEQUENCE s1);
>
> I think if we use the above syntax then one can also argue that why
> not use FOR ALL (TABLES, SEQUENCES) instead of ALL TABLES, ALL
> SEQUENCES.

The same is true for the syntaxes of TABLE(t1, t2) and SCHEMA(s1, s2),
no? If we allow grouping the tables and the schemas by TABLE and
SCHEMA keywords respectively in exclusion lists, one could argue why
we don't allow it for the inclusion list.

>
> Instead the current command would like:
> Create publication pub1 FOR ALL TABLES EXCEPT TABLE (t1, t2), EXCEPT
> TABLES IN SCHEMA (s1, s2), ALL SEQUENCES EXCEPT SEQUENCE (seq1, seq2);
>
> Though it is slightly lengthy it makes the syntax local such that the
> meaning of a clause is determined by what is inside it, not by
> something that appears ten words later.

While it helps the syntax locality, I'm concerned that it could make
the context of the EXCEPT clause ambiguous. For example, IIUC the
above syntax rule would allow us to write:

CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLES IN SCHEMA (s1),
EXCEPT TABLE (t1);

Regarding the second EXCEPT clause, while one might think it excludes
t1 from ALL TABLES, one might think it excludes t1 from the first
EXCLUDE clause (i.e., the publication actually includes t1 in the
publication).

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-14 09:35:21
Message-ID: CAA4eK1K1GLR7DXSABayQE+pWM=v1ODD6haPYxuDhAYwJN5gjzg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Mar 13, 2026 at 11:51 PM Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com> wrote:
>
> On Fri, Mar 13, 2026 at 2:51 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> > On Fri, Mar 13, 2026 at 8:55 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> > >
> > > Hou-San (off-list) gave an interesting example of how it might look
> > > when the example is combined with the hypothetical future ability to
> > > exclude all schema tables from a "FOR ALL TABLES"
> > > CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, t2, TABLES IN
> > > SCHEMA s1);
> > >
> >
> > So, if we follow this, in future, the syntax would look like:
> > Create publication pub1 FOR ALL TABLES EXCEPT (TABLE t1, t2, TABLES IN
> > SCHEMA s1, s2), ALL SEQUENCES EXCEPT (SEQUENCE s1);
> >
> > I think if we use the above syntax then one can also argue that why
> > not use FOR ALL (TABLES, SEQUENCES) instead of ALL TABLES, ALL
> > SEQUENCES.
>
> The same is true for the syntaxes of TABLE(t1, t2) and SCHEMA(s1, s2),
> no? If we allow grouping the tables and the schemas by TABLE and
> SCHEMA keywords respectively in exclusion lists, one could argue why
> we don't allow it for the inclusion list.
>
> >
> > Instead the current command would like:
> > Create publication pub1 FOR ALL TABLES EXCEPT TABLE (t1, t2), EXCEPT
> > TABLES IN SCHEMA (s1, s2), ALL SEQUENCES EXCEPT SEQUENCE (seq1, seq2);
> >
> > Though it is slightly lengthy it makes the syntax local such that the
> > meaning of a clause is determined by what is inside it, not by
> > something that appears ten words later.
>
> While it helps the syntax locality, I'm concerned that it could make
> the context of the EXCEPT clause ambiguous. For example, IIUC the
> above syntax rule would allow us to write:
>
> CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLES IN SCHEMA (s1),
> EXCEPT TABLE (t1);
>
> Regarding the second EXCEPT clause, while one might think it excludes
> t1 from ALL TABLES, one might think it excludes t1 from the first
> EXCLUDE clause (i.e., the publication actually includes t1 in the
> publication).
>

According to me, the comma between EXCEPT clauses breaks such a chain
of thought but others may think differently. The docs can clarify such
a confusion if any but if multiple people interpret it the way you
think, I am fine to go with the direction you are proposing. I am
slightly worried that both syntaxes have some pros and cons, so even
if we change to what you are suggesting, one can argue to go back to
previous syntax as that also has some merits. So, I feel we can
complete the pending patch [1] and try to get the opinion of some
other people unless changing the code to support another alternative
is difficult.

[1] - https://www.postgresql.org/message-id/CALDaNm1SGJtJq_W68khExG1EL4ZmyZ2U7JSc1Z3FsYr4nSbi_A%40mail.gmail.com

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-15 12:25:34
Message-ID: CALDaNm2kvFahDDvdgCNo=Nv-COz_N5Xw8YmzQBN2bd3g=N81fQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, 14 Mar 2026 at 15:05, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Fri, Mar 13, 2026 at 11:51 PM Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com> wrote:
> >
> > On Fri, Mar 13, 2026 at 2:51 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> > >
> > > On Fri, Mar 13, 2026 at 8:55 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> > > >
> > > > Hou-San (off-list) gave an interesting example of how it might look
> > > > when the example is combined with the hypothetical future ability to
> > > > exclude all schema tables from a "FOR ALL TABLES"
> > > > CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, t2, TABLES IN
> > > > SCHEMA s1);
> > > >
> > >
> > > So, if we follow this, in future, the syntax would look like:
> > > Create publication pub1 FOR ALL TABLES EXCEPT (TABLE t1, t2, TABLES IN
> > > SCHEMA s1, s2), ALL SEQUENCES EXCEPT (SEQUENCE s1);
> > >
> > > I think if we use the above syntax then one can also argue that why
> > > not use FOR ALL (TABLES, SEQUENCES) instead of ALL TABLES, ALL
> > > SEQUENCES.
> >
> > The same is true for the syntaxes of TABLE(t1, t2) and SCHEMA(s1, s2),
> > no? If we allow grouping the tables and the schemas by TABLE and
> > SCHEMA keywords respectively in exclusion lists, one could argue why
> > we don't allow it for the inclusion list.
> >
> > >
> > > Instead the current command would like:
> > > Create publication pub1 FOR ALL TABLES EXCEPT TABLE (t1, t2), EXCEPT
> > > TABLES IN SCHEMA (s1, s2), ALL SEQUENCES EXCEPT SEQUENCE (seq1, seq2);
> > >
> > > Though it is slightly lengthy it makes the syntax local such that the
> > > meaning of a clause is determined by what is inside it, not by
> > > something that appears ten words later.
> >
> > While it helps the syntax locality, I'm concerned that it could make
> > the context of the EXCEPT clause ambiguous. For example, IIUC the
> > above syntax rule would allow us to write:
> >
> > CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLES IN SCHEMA (s1),
> > EXCEPT TABLE (t1);
> >
> > Regarding the second EXCEPT clause, while one might think it excludes
> > t1 from ALL TABLES, one might think it excludes t1 from the first
> > EXCLUDE clause (i.e., the publication actually includes t1 in the
> > publication).
> >
>
> According to me, the comma between EXCEPT clauses breaks such a chain
> of thought but others may think differently. The docs can clarify such
> a confusion if any but if multiple people interpret it the way you
> think, I am fine to go with the direction you are proposing. I am
> slightly worried that both syntaxes have some pros and cons, so even
> if we change to what you are suggesting, one can argue to go back to
> previous syntax as that also has some merits. So, I feel we can
> complete the pending patch [1] and try to get the opinion of some
> other people unless changing the code to support another alternative
> is difficult.

+1 to proceed with completing the pending work.
I implemented the suggested new syntax, and it only requires a few
lines of code changes. I evaluated the change to ensure there is no
additional complexity, and it appears straightforward. We can switch
to the new syntax once we gather a few more opinions and finalize it.
The attached 0002 patch includes the corresponding changes.

Regards,
Vignesh

Attachment Content-Type Size
v63-0001-Add-support-for-EXCEPT-TABLE-in-ALTER-PUBLICATIO.patch application/octet-stream 26.8 KB
v63-0002-Change-syntax-of-CREATE-PUBLICATION-.-FOR-ALL-TA.patch application/octet-stream 23.5 KB

From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-16 04:37:02
Message-ID: CAJpy0uD--YKK-mrKxMS1Gq43kbmi+KjoRtns8o_3oc=78W0nWA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, Mar 14, 2026 at 3:05 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
>
> So, I feel we can
> complete the pending patch [1] and try to get the opinion of some
> other people unless changing the code to support another alternative
> is difficult.
>

+1. It definitely needs more opinion before we go and change the patch.

thanks
Shveta


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-16 06:35:44
Message-ID: CAHut+Pvw-XNBnW-ymGdWpLxaEime7_EdOihcUheGyZvw73kcgg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

I was away for a couple of weeks leading up to when the EXCEPT TABLE
feature got pushed (commit fd36606), so I missed my chance to review
it.

Here are some late review comments of code already on master:

======
doc/src/sgml/ref/create_publication.sgml

1.
+ <para>
+ There can be a case where a subscription includes multiple publications.
+ In such a case, a table or partition that is included in one publication
+ and listed in the <literal>EXCEPT TABLE</literal> clause of another is
+ considered included for replication.
+ </para>

1a
IIUC you cannot directly specify a partition in the EXCEPT TABLE list
but a partition still might implicitly be excluded if its root
partition table is excluded. So I felt the wording "and listed in" is
not quite correct since you cannot "list" a partition -- it could be
more like below.

SUGGESTION:
There can be a case where a subscription includes multiple
publications. In such a case, a table or partition that is included in
one publication but excluded (explicitly or implicitly) by the
<literal>EXCEPT TABLE</literal> clause of another is considered
included for replication.

~

1b.
Anyway, this note is talking about *subscriptions* to multiple
publications, so I felt that it belongs in the CREATE SUBSCRIPTION
"Notes" section. Or, maybe on both pages.

======
src/backend/catalog/pg_publication.c

check_publication_add_relation:

2.
+ if (pri->except)
+ errormsg = gettext_noop("cannot use publication EXCEPT clause for
relation \"%s\"");
+ else
+ errormsg = gettext_noop("cannot add relation \"%s\" to publication");

I felt that the first message wording could be improved. e.g. "using
EXCEPT clause for a relation" sounds backwards. In passing, make it
more similar to the other (else) message.

SUGGESTION
cannot specify relation \"%s\" in the publication EXCEPT clause

======
src/backend/commands/tablecmds.c

ATExecAttachPartition:

3.
+ bool first = true;
+ StringInfoData pubnames;
+
+ initStringInfo(&pubnames);
+
+ foreach_oid(pubid, exceptpuboids)
+ {
+ char *pubname = get_publication_name(pubid, false);
+
+ if (!first)
+ {
+ /*
+ * translator: This is a separator in a list of publication
+ * names.
+ */
+ appendStringInfoString(&pubnames, _(", "));
+ }
+
+ first = false;
+
+ appendStringInfo(&pubnames, _("\"%s\""), pubname);
+ }

3a.
Why is appendStringInfo(&pubnames, _("\"%s\""), pubname) using the
"_(" macro?. AFAIK it does not make sense to call gettext() for a
pubname.

~

3b.
Postgres already has a function to make a CSV list of pubnames. Can't
we build a list of pubnames here, then just call the common
'GetPublicationsStr' to get that as a CSV string. PSA a patch
demonstrating what I mean.

======
src/test/subscription/t/037_except.pl

4.
+# Exclude tab1 (non-inheritance case), and also exclude parent and ONLY parent1
+# to verify exclusion behavior for inherited tables, including the effect of
+# ONLY in the EXCEPT TABLE clause.
+$node_publisher->safe_psql('postgres',
+ "CREATE PUBLICATION tab_pub FOR ALL TABLES EXCEPT TABLE (tab1,
parent, only parent1)"
+);
+
+# Create a logical replication slot to help with later tests.
+$node_publisher->safe_psql('postgres',
+ "SELECT pg_create_logical_replication_slot('test_slot', 'pgoutput')");
+
+$node_subscriber->safe_psql('postgres',
+ "CREATE SUBSCRIPTION tab_sub CONNECTION '$publisher_connstr'
PUBLICATION tab_pub"
+);
+

Why are those pub/sub prefixed "tab_"? They are not tables.

Note that elsewhere in this same patch tap test there are other
pub/subs called "tap_pub_part" and "tap_sub_part". So why are some
"tap_" and some "tab_"?

I guess those ones called "tab_pub" and "tab_sub" look like they've
been accidentally changed by a global "tab" replacement, or were
assumed to be typos when they were not.

======
Kind Regards,
Peter Smith.
Fujitsu Australia

Attachment Content-Type Size
PS_use_GetPublicationsStr.txt text/plain 1.3 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-16 08:38:21
Message-ID: CAHut+PsCqTR_kQu5M1TqBjnE6KM5cO22aH8boHfpMa_gSJBmWg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Vignesh.

Unfortunately, IMO there are some fundamental problems here due to
there being no accounting for publications with FOR ALL SEQUENCES. So
I am posting my review comments for just the docs part so you can see
it from my PoV. Maybe this was already discussed earlier in the thread
but I saw no mentions of it. AFAICT the discussion/posts were mostly
focussed on the setting/resetting of EXCEPT TABLE but seem to be
overlooking the bigger picture.

Below review comments are for v63-0001 docs only.

======
Commit Message

1.
The first form replaces the current EXCEPT TABLE list with the specified
tables. The second form clears the existing except table list. Like the
creation syntax, only root partitioned tables can be specified in the
exclusion list.

~

IMO the second form is a long-time missing command from Postgres. For
example, it is possible to create an "empty" publication. But without
this "ALTER PUBLICATION name SET ALL TABLES" there was no way to
convert that to be a "FOR ALL TABLES" publication. So really this
feature was independently needed and should be done anyway
irrespective of any side-effect it has for the EXCEPT TABLE list.

Ideally the SET/ADD/DROP ALL TABLES can split out and done ahead of
the EXCEPT TABLE stuff.

Similarly, SET/ADD/DROP should be implemented also for FOR ALL
SEQUENCES otherwise there is no way to manipulate those either.

======
doc/src/sgml/ref/alter_publication.sgml

2.
Implementing the "SET ALL TABLES" is only a start. You also need to
have the other case:

* ADD ALL TABLES
* DROP ALL TABLES

Note you might start out with something like "CREATE PUBLICATION pub
FOR ALL TABLES, FOR ALL SEQUENCES" so you need to be able to be able
to modify/remove the published TABLES part without overwriting
published SEQUENCES part!!

i.e The "SET" means set the publication; it doesn't mean add to the
publication. So SET ALL TABLES obliterates any FOR ALL SEQUENCES.

~~~

3.
+<phrase>where <replaceable
class="parameter">publication_except_tables</replaceable> is:</phrase>
+
+ [ EXCEPT TABLE ( [ ONLY ] <replaceable
class="parameter">table_name</replaceable> [, ... ] ) ]
+

Hmm. Ideally, this should be part of 'publication_object' and
publication_drop_object' because the ADD/DROP are also needed for the
reasons given in my above review commentS.

~~~

4.
<para>
- The first three variants change which tables/schemas are part of the
- publication. The <literal>SET</literal> clause will replace the list of
- tables/schemas in the publication with the specified list; the existing
- tables/schemas that were present in the publication will be removed. The
+ The first four variants modify which tables/schemas are included in the
+ publication, or which tables are excluded from it. The
+ <literal>SET ALL TABLES</literal> clause is used to update the
+ <literal>EXCEPT TABLE</literal> list of a <literal>FOR ALL TABLES</literal>
+ publication. If <literal>EXCEPT TABLE</literal> is specified with a list of
+ tables, the existing except table list is replaced with the
specified tables.
+ If <literal>EXCEPT TABLE</literal> is omitted, the existing except table
+ list is cleared. The <literal>SET</literal> clause, when used with a
+ publication defined with <literal>FOR TABLE</literal> or
+ <literal>FOR TABLES IN SCHEMA</literal>, replaces the list of tables/schemas
+ in the publication with the specified list; the existing tables or schemas
+ that were present in the publication will be removed. The

I find this all a bit dubious because nothing seems to be accounting
for the possibility of "FOR ALL SEQUENCES" also in the publication...
e.g this entire ALTER command should also have

SET ALL SEQUENCES
ADD ALL SEQUENCES
DROP ALL SEQUENCE

and

SET ALL TABLES
ADD ALL TABLES
DROP ALL TABLES

IMO, a user will need to take care when using ALTER PUBLICATION ...
SET ALL TABLES that it does not destroy the publication of sequences
(and vice versa)

-- Start with an "empty" publication and make it a "FOR ALL TABLES"
publication...
CREATE PUBLICATION pub;
ALTER PUBLICATION pub SET ALL TABLES;
-- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES"

-- give some table exceptions to it
ALTER PUBLICATION pub SET ALL TABLES EXCEPT TABLE(t1,t2);
-- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES
EXCEPT TABLE(t1,t2)"

-- add sequences to this
ALTER PUBLICATION pub ADD ALL SEQUENCES
-- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES
EXCEPT TABLE(t1,t2), FOR ALL SEQUENCES"

-- remove the table exception
-- here you cannot simply use SET ALL TABLES because you will lose the
ALL SEQUENCES part of the publication!!
-- So, instead you need to do like below
ALTER PUBLICATION pub DROP ALL TABLES;
ALTER PUBLICATION pub ADD ALL TABLES;
-- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES, FOR
ALL SEQUENCES"

~~~

5.
+</programlisting></para>
+
+ <para>
+ Replace the publication's EXCEPT table list:

/EXCEPT table list/EXCEPT TABLE list/

~~~

6.
+ <para>
+ Change the publication to include all tables by removing any existing
+ EXCEPT table list:

The clearing of the EXCEPT TABLES is more like a side-effect, so I
think this can be worded differently.

SUGGESTION
Reset the publication to be a FOR ALL TABLES publication with no
excluded tables.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-16 08:49:47
Message-ID: CAA4eK1LLZayJBtrZEMt8PTXdbv_XB14u4PTS4pVBUgEUHPikKQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Mar 16, 2026 at 12:06 PM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> ======
> src/backend/commands/tablecmds.c
>
> ATExecAttachPartition:
>
> 3.
> + bool first = true;
> + StringInfoData pubnames;
> +
> + initStringInfo(&pubnames);
> +
> + foreach_oid(pubid, exceptpuboids)
> + {
> + char *pubname = get_publication_name(pubid, false);
> +
> + if (!first)
> + {
> + /*
> + * translator: This is a separator in a list of publication
> + * names.
> + */
> + appendStringInfoString(&pubnames, _(", "));
> + }
> +
> + first = false;
> +
> + appendStringInfo(&pubnames, _("\"%s\""), pubname);
> + }
>
> 3a.
> Why is appendStringInfo(&pubnames, _("\"%s\""), pubname) using the
> "_(" macro?. AFAIK it does not make sense to call gettext() for a
> pubname.
>

Why? I see a similar usage in logicalrep_get_attrs_str().

> ~
>
> 3b.
> Postgres already has a function to make a CSV list of pubnames. Can't
> we build a list of pubnames here, then just call the common
> 'GetPublicationsStr' to get that as a CSV string. PSA a patch
> demonstrating what I mean.
>

Here you are first forming a list then adding commas to it by parsing
it. I think such a duplicate effort is not required.

--
With Regards,
Amit Kapila.


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-16 09:39:12
Message-ID: CAA4eK1L2z_CwKr_5VwgzmuQOZzVbzAjFWdmQt4yCm=NitaR7Lg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Mar 16, 2026 at 2:08 PM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> IMO, a user will need to take care when using ALTER PUBLICATION ...
> SET ALL TABLES that it does not destroy the publication of sequences
> (and vice versa)
>
> -- Start with an "empty" publication and make it a "FOR ALL TABLES"
> publication...
> CREATE PUBLICATION pub;
> ALTER PUBLICATION pub SET ALL TABLES;
> -- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES"
>
>
> -- give some table exceptions to it
> ALTER PUBLICATION pub SET ALL TABLES EXCEPT TABLE(t1,t2);
> -- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES
> EXCEPT TABLE(t1,t2)"
>
>
> -- add sequences to this
> ALTER PUBLICATION pub ADD ALL SEQUENCES
> -- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES
> EXCEPT TABLE(t1,t2), FOR ALL SEQUENCES"
>
>
> -- remove the table exception
> -- here you cannot simply use SET ALL TABLES because you will lose the
> ALL SEQUENCES part of the publication!!

Though the patch is not doing that but the syntax intends that. So, we
should have a variant like "Alter Publication pub1 Set All Tables, All
Sequences" to retain both.

> -- So, instead you need to do like below
> ALTER PUBLICATION pub DROP ALL TABLES;
> ALTER PUBLICATION pub ADD ALL TABLES;
> -- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES, FOR
> ALL SEQUENCES"
>

I think we can make a separate case for ADD/DROP rather than tie it
along with this patch. For example, DROP ALL Tables could be used for
ALL TABLES and non-ALL TABLES publication, for later it could mean to
drop all the publicized tables and for earlier it just toggles the
flag.

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-16 10:56:00
Message-ID: CALDaNm0mYT55pjdyN-yY=5dSOfMVx307CtP3xYqzWVa0MPRtLQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 16 Mar 2026 at 12:06, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> I was away for a couple of weeks leading up to when the EXCEPT TABLE
> feature got pushed (commit fd36606), so I missed my chance to review
> it.
>
> Here are some late review comments of code already on master:
>
> ======
> doc/src/sgml/ref/create_publication.sgml
>
> 1.
> + <para>
> + There can be a case where a subscription includes multiple publications.
> + In such a case, a table or partition that is included in one publication
> + and listed in the <literal>EXCEPT TABLE</literal> clause of another is
> + considered included for replication.
> + </para>
>
> 1a
> IIUC you cannot directly specify a partition in the EXCEPT TABLE list
> but a partition still might implicitly be excluded if its root
> partition table is excluded. So I felt the wording "and listed in" is
> not quite correct since you cannot "list" a partition -- it could be
> more like below.
>
> SUGGESTION:
> There can be a case where a subscription includes multiple
> publications. In such a case, a table or partition that is included in
> one publication but excluded (explicitly or implicitly) by the
> <literal>EXCEPT TABLE</literal> clause of another is considered
> included for replication.

Modified

> ~
>
> 1b.
> Anyway, this note is talking about *subscriptions* to multiple
> publications, so I felt that it belongs in the CREATE SUBSCRIPTION
> "Notes" section. Or, maybe on both pages.

I felt this talks about publication, so this place is ok. We can do it
like the way you are telling if others also feel that way.

> ======
> src/backend/catalog/pg_publication.c
>
> check_publication_add_relation:
>
> 2.
> + if (pri->except)
> + errormsg = gettext_noop("cannot use publication EXCEPT clause for
> relation \"%s\"");
> + else
> + errormsg = gettext_noop("cannot add relation \"%s\" to publication");
>
> I felt that the first message wording could be improved. e.g. "using
> EXCEPT clause for a relation" sounds backwards. In passing, make it
> more similar to the other (else) message.
>
> SUGGESTION
> cannot specify relation \"%s\" in the publication EXCEPT clause

Modified

> ======
> src/backend/commands/tablecmds.c
>
> ATExecAttachPartition:
>
> 3.
> + bool first = true;
> + StringInfoData pubnames;
> +
> + initStringInfo(&pubnames);
> +
> + foreach_oid(pubid, exceptpuboids)
> + {
> + char *pubname = get_publication_name(pubid, false);
> +
> + if (!first)
> + {
> + /*
> + * translator: This is a separator in a list of publication
> + * names.
> + */
> + appendStringInfoString(&pubnames, _(", "));
> + }
> +
> + first = false;
> +
> + appendStringInfo(&pubnames, _("\"%s\""), pubname);
> + }
>
> 3a.
> Why is appendStringInfo(&pubnames, _("\"%s\""), pubname) using the
> "_(" macro?. AFAIK it does not make sense to call gettext() for a
> pubname.

I had seen that it is implemented similarly in logicalrep_get_attrs_str too:
appendStringInfo(&attsbuf, _("\"%s\""), remoterel->attnames[i]);

Amit also has mentioned this at [1].

> ~
>
> 3b.
> Postgres already has a function to make a CSV list of pubnames. Can't
> we build a list of pubnames here, then just call the common
> 'GetPublicationsStr' to get that as a CSV string. PSA a patch
> demonstrating what I mean.

The current implementation loops the publication only once. In the
approach you suggested first you will loop through pubids and get the
pubname then pass it to GetPublicationsStr and loop again. I felt the
existing is better.

> ======
> src/test/subscription/t/037_except.pl
>
> 4.
> +# Exclude tab1 (non-inheritance case), and also exclude parent and ONLY parent1
> +# to verify exclusion behavior for inherited tables, including the effect of
> +# ONLY in the EXCEPT TABLE clause.
> +$node_publisher->safe_psql('postgres',
> + "CREATE PUBLICATION tab_pub FOR ALL TABLES EXCEPT TABLE (tab1,
> parent, only parent1)"
> +);
> +
> +# Create a logical replication slot to help with later tests.
> +$node_publisher->safe_psql('postgres',
> + "SELECT pg_create_logical_replication_slot('test_slot', 'pgoutput')");
> +
> +$node_subscriber->safe_psql('postgres',
> + "CREATE SUBSCRIPTION tab_sub CONNECTION '$publisher_connstr'
> PUBLICATION tab_pub"
> +);
> +
>
> Why are those pub/sub prefixed "tab_"? They are not tables.
>
> Note that elsewhere in this same patch tap test there are other
> pub/subs called "tap_pub_part" and "tap_sub_part". So why are some
> "tap_" and some "tab_"?
>
> I guess those ones called "tab_pub" and "tab_sub" look like they've
> been accidentally changed by a global "tab" replacement, or were
> assumed to be typos when they were not.

Modified, additionally updated an incorrect test comment to reflect
that only tables are created, not schemas.
The attached patch has the changes for the same.

[1] - https://www.postgresql.org/message-id/CAA4eK1LLZayJBtrZEMt8PTXdbv_XB14u4PTS4pVBUgEUHPikKQ%40mail.gmail.com

Regards,
Vignesh

Attachment Content-Type Size
0001-Fix-few-issues-in-commit-fd366065e0.patch application/octet-stream 6.5 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-16 23:58:33
Message-ID: CAHut+PtVaOYVP1R0TOoNh5G9CUBurrP=6i7fJCdfWEZiqVCRvw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Vignesh.

Thanks for the fixes! Below are some more details about the un-fixed
ones, in case it makes any difference.

On Mon, Mar 16, 2026 at 9:56 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Mon, 16 Mar 2026 at 12:06, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >
...
> > 1b.
> > Anyway, this note is talking about *subscriptions* to multiple
> > publications, so I felt that it belongs in the CREATE SUBSCRIPTION
> > "Notes" section. Or, maybe on both pages.
>
> I felt this talks about publication, so this place is ok. We can do it
> like the way you are telling if others also feel that way.

OK. Just so others are aware, the CREATE SUBSCRIPTION page "Notes"
section [1] is already saying things like:

i) "If the subscription has several publications in which the same
table has been published with different WHERE clauses..."

ii) "Subscriptions having several publications in which the same table
has been published with different column lists..."

So, all I am suggesting is that CREATE SUBSCRIPTION should also have
exactly the same kind of worded note to describe behaviour for
subscriptions having several publications with clashing
included/excluded tables.

> > ======
> > src/backend/commands/tablecmds.c
> >
> > ATExecAttachPartition:
> >
> > 3.
> > + bool first = true;
> > + StringInfoData pubnames;
> > +
> > + initStringInfo(&pubnames);
> > +
> > + foreach_oid(pubid, exceptpuboids)
> > + {
> > + char *pubname = get_publication_name(pubid, false);
> > +
> > + if (!first)
> > + {
> > + /*
> > + * translator: This is a separator in a list of publication
> > + * names.
> > + */
> > + appendStringInfoString(&pubnames, _(", "));
> > + }
> > +
> > + first = false;
> > +
> > + appendStringInfo(&pubnames, _("\"%s\""), pubname);
> > + }
> >
> > 3a.
> > Why is appendStringInfo(&pubnames, _("\"%s\""), pubname) using the
> > "_(" macro?. AFAIK it does not make sense to call gettext() for a
> > pubname.
>
> I had seen that it is implemented similarly in logicalrep_get_attrs_str too:
> appendStringInfo(&attsbuf, _("\"%s\""), remoterel->attnames[i]);
>
> Amit also has mentioned this at [1].

OK, but AFAICT that logicalrep_get_attrs_str code is the original
mistaken usage. Copying it just makes 2 mistakes.

e.g. the purpose of using gettext (e.g. the "_(x)" macro) is for
marking the string for i18n translation. But there's nothing even to
translate here, it's just a format specifier in quotes.

Also, the fact that logicalrep_get_attrs_str was the one-and-only
usage of _(\"%s\") in the entire PG source indicates to me that it's
dubious.

> > 3b.
> > Postgres already has a function to make a CSV list of pubnames. Can't
> > we build a list of pubnames here, then just call the common
> > 'GetPublicationsStr' to get that as a CSV string. PSA a patch
> > demonstrating what I mean.
>
> The current implementation loops the publication only once. In the
> approach you suggested first you will loop through pubids and get the
> pubname then pass it to GetPublicationsStr and loop again. I felt the
> existing is better.

Sure. It's your call.

FWIW, I think the extra looping is insignificant because:
i) loops will be tiny (how many publications will be publishing the same table?)
ii) it is only used for an ERROR message; performance hardly matters.

OTOH, using the common function implementation is <10 lines instead of
>20 lines.

======
[1] https://www.postgresql.org/docs/devel/sql-createsubscription.html

Kind Regards
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-17 01:52:23
Message-ID: CAHut+Pvmbana0od++5ugquj-Yoi7MH3gOOQh72p1XeOg5Ni3Aw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Mar 16, 2026 at 8:39 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Mon, Mar 16, 2026 at 2:08 PM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >
> > IMO, a user will need to take care when using ALTER PUBLICATION ...
> > SET ALL TABLES that it does not destroy the publication of sequences
> > (and vice versa)
> >
> > -- Start with an "empty" publication and make it a "FOR ALL TABLES"
> > publication...
> > CREATE PUBLICATION pub;
> > ALTER PUBLICATION pub SET ALL TABLES;
> > -- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES"
> >
> >
> > -- give some table exceptions to it
> > ALTER PUBLICATION pub SET ALL TABLES EXCEPT TABLE(t1,t2);
> > -- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES
> > EXCEPT TABLE(t1,t2)"
> >
> >
> > -- add sequences to this
> > ALTER PUBLICATION pub ADD ALL SEQUENCES
> > -- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES
> > EXCEPT TABLE(t1,t2), FOR ALL SEQUENCES"
> >
> >
> > -- remove the table exception
> > -- here you cannot simply use SET ALL TABLES because you will lose the
> > ALL SEQUENCES part of the publication!!
>
> Though the patch is not doing that but the syntax intends that. So, we
> should have a variant like "Alter Publication pub1 Set All Tables, All
> Sequences" to retain both.

Right. Doing "SET ALL TABLES, ALL SEQUENCES" is another way to achieve
the same outcome using one ALTER command instead of two.

But this way requires adding the currently missing SET/ADD/DROP ALL
SEQUENCES syntax.

>
> > -- So, instead you need to do like below
> > ALTER PUBLICATION pub DROP ALL TABLES;
> > ALTER PUBLICATION pub ADD ALL TABLES;
> > -- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES, FOR
> > ALL SEQUENCES"
> >
>
> I think we can make a separate case for ADD/DROP rather than tie it
> along with this patch. For example, DROP ALL Tables could be used for
> ALL TABLES and non-ALL TABLES publication, for later it could mean to
> drop all the publicized tables and for earlier it just toggles the
> flag.
>

The basic expected SET/ADD/DROP behaviours are already very clear;
It's just that they are not yet implemented for "ALL TABLES" and "ALL
SEQUENCES". Ideally, those would be prerequisites for this EXCEPT
patch.

If they are done separately later, then it means in the interim, there
will be some publication clause combinations that can lead to dead
ends, where the user would be unable to modify the publication as they
want without dropping and recreating it.

Maybe that is OK. Perhaps having functionality gaps doesn't matter as
much as I think it does:
- e.g1. The FOR ALL SEQUENCES has existed for some months, and we
cannot use ALTER to change it. Nobody complained?
- e.g2. For years, it's been impossible to convert an "empty"
publication into a FOR ALL TABLES publication. Nobody complained?

OTOH, doing them in the right order is preferable to avoid churning
the ALTER PUBLICATION docs page synopsis/description.

------
Kind Regards,
Peter Smith.
Fujitsu Australia.


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-17 03:16:38
Message-ID: CAA4eK1J-eFrcDo9vKjRe1dHaYLGoQPCRpyU0VhHN9zLm5ECj-g@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 17, 2026 at 7:22 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> On Mon, Mar 16, 2026 at 8:39 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> > On Mon, Mar 16, 2026 at 2:08 PM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >
> > I think we can make a separate case for ADD/DROP rather than tie it
> > along with this patch. For example, DROP ALL Tables could be used for
> > ALL TABLES and non-ALL TABLES publication, for later it could mean to
> > drop all the publicized tables and for earlier it just toggles the
> > flag.
> >
>
> The basic expected SET/ADD/DROP behaviours are already very clear;
> It's just that they are not yet implemented for "ALL TABLES" and "ALL
> SEQUENCES". Ideally, those would be prerequisites for this EXCEPT
> patch.
>
> If they are done separately later, then it means in the interim, there
> will be some publication clause combinations that can lead to dead
> ends, where the user would be unable to modify the publication as they
> want without dropping and recreating it.
>
> Maybe that is OK. Perhaps having functionality gaps doesn't matter as
> much as I think it does:

Possible.

> - e.g1. The FOR ALL SEQUENCES has existed for some months, and we
> cannot use ALTER to change it. Nobody complained?
>

Isn't the same true FOR ALL TABLES which is there from the time
logical replication is introduced? So, we tried to follow the same for
ALL SEQUENCES case.

We can do extensions of the proposed or existing syntaxes based on the
user input in future. If we try to find all possible ways to set/reset
all the options provided for publications/subscriptions, we may find a
few more. At this stage, we want one way for users to change the
EXCEPT list which the proposed patch is providing.

> - e.g2. For years, it's been impossible to convert an "empty"
> publication into a FOR ALL TABLES publication. Nobody complained?
>

Right, so that indicates, there is no immediate need to support all
kinds of syntaxes.

> OTOH, doing them in the right order is preferable to avoid churning
> the ALTER PUBLICATION docs page synopsis/description.
>

That is a small price to pay as compared to building/maintaining more
variants when we don't see field demand for the same.

--
With Regards,
Amit Kapila.


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-17 03:25:30
Message-ID: CAA4eK1LpEO65Sugrf4=MZwZO8Us-Rihd6wEKD-eVHLfm-wLRtQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 17, 2026 at 5:29 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Thanks for the fixes! Below are some more details about the un-fixed
> ones, in case it makes any difference.
>
> On Mon, Mar 16, 2026 at 9:56 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > On Mon, 16 Mar 2026 at 12:06, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> > >
> ...
> > > 1b.
> > > Anyway, this note is talking about *subscriptions* to multiple
> > > publications, so I felt that it belongs in the CREATE SUBSCRIPTION
> > > "Notes" section. Or, maybe on both pages.
> >
> > I felt this talks about publication, so this place is ok. We can do it
> > like the way you are telling if others also feel that way.
>
> OK. Just so others are aware, the CREATE SUBSCRIPTION page "Notes"
> section [1] is already saying things like:
>
> i) "If the subscription has several publications in which the same
> table has been published with different WHERE clauses..."
>
> ii) "Subscriptions having several publications in which the same table
> has been published with different column lists..."
>
> So, all I am suggesting is that CREATE SUBSCRIPTION should also have
> exactly the same kind of worded note to describe behaviour for
> subscriptions having several publications with clashing
> included/excluded tables.
>

I don't know if that is required or not. Please wait to get the base
feature stabilized, we can add more docs later as well after some
inputs.

> > > ======
> > > src/backend/commands/tablecmds.c
> > >
> > > ATExecAttachPartition:
> > >
> > > 3.
> > > + bool first = true;
> > > + StringInfoData pubnames;
> > > +
> > > + initStringInfo(&pubnames);
> > > +
> > > + foreach_oid(pubid, exceptpuboids)
> > > + {
> > > + char *pubname = get_publication_name(pubid, false);
> > > +
> > > + if (!first)
> > > + {
> > > + /*
> > > + * translator: This is a separator in a list of publication
> > > + * names.
> > > + */
> > > + appendStringInfoString(&pubnames, _(", "));
> > > + }
> > > +
> > > + first = false;
> > > +
> > > + appendStringInfo(&pubnames, _("\"%s\""), pubname);
> > > + }
> > >
> > > 3a.
> > > Why is appendStringInfo(&pubnames, _("\"%s\""), pubname) using the
> > > "_(" macro?. AFAIK it does not make sense to call gettext() for a
> > > pubname.
> >
> > I had seen that it is implemented similarly in logicalrep_get_attrs_str too:
> > appendStringInfo(&attsbuf, _("\"%s\""), remoterel->attnames[i]);
> >
> > Amit also has mentioned this at [1].
>
> OK, but AFAICT that logicalrep_get_attrs_str code is the original
> mistaken usage. Copying it just makes 2 mistakes.
>
> e.g. the purpose of using gettext (e.g. the "_(x)" macro) is for
> marking the string for i18n translation. But there's nothing even to
> translate here, it's just a format specifier in quotes.
>
> Also, the fact that logicalrep_get_attrs_str was the one-and-only
> usage of _(\"%s\") in the entire PG source indicates to me that it's
> dubious.
>

I am not a translation expert, so not sure but will consider this
input after taking care of the pending main patch.

> > > 3b.
> > > Postgres already has a function to make a CSV list of pubnames. Can't
> > > we build a list of pubnames here, then just call the common
> > > 'GetPublicationsStr' to get that as a CSV string. PSA a patch
> > > demonstrating what I mean.
> >
> > The current implementation loops the publication only once. In the
> > approach you suggested first you will loop through pubids and get the
> > pubname then pass it to GetPublicationsStr and loop again. I felt the
> > existing is better.
>
> Sure. It's your call.
>
> FWIW, I think the extra looping is insignificant because:
> i) loops will be tiny (how many publications will be publishing the same table?)
>

I don't have a ready answer for this, the number could be large as well.

> ii) it is only used for an ERROR message; performance hardly matters.
>
> OTOH, using the common function implementation is <10 lines instead of
> >20 lines.
>

Hmm, this is another way to look at it but looping extra time over
publications to call existing function sounds redundant to me. I don't
want to argue what is the best way for this but if more people also
prefer this pattern then we can change it.

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-17 06:53:45
Message-ID: CALDaNm2OOgmNOPpABUU+AXzHhfrLG9HMfSd3jfNe=t3dc-kp1Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 16 Mar 2026 at 14:08, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Vignesh.
>
> Unfortunately, IMO there are some fundamental problems here due to
> there being no accounting for publications with FOR ALL SEQUENCES. So
> I am posting my review comments for just the docs part so you can see
> it from my PoV. Maybe this was already discussed earlier in the thread
> but I saw no mentions of it. AFAICT the discussion/posts were mostly
> focussed on the setting/resetting of EXCEPT TABLE but seem to be
> overlooking the bigger picture.
>
> Below review comments are for v63-0001 docs only.
>
> ======
> Commit Message
>
> 1.
> The first form replaces the current EXCEPT TABLE list with the specified
> tables. The second form clears the existing except table list. Like the
> creation syntax, only root partitioned tables can be specified in the
> exclusion list.
>
> ~
>
> IMO the second form is a long-time missing command from Postgres. For
> example, it is possible to create an "empty" publication. But without
> this "ALTER PUBLICATION name SET ALL TABLES" there was no way to
> convert that to be a "FOR ALL TABLES" publication. So really this
> feature was independently needed and should be done anyway
> irrespective of any side-effect it has for the EXCEPT TABLE list.
>
> Ideally the SET/ADD/DROP ALL TABLES can split out and done ahead of
> the EXCEPT TABLE stuff.
>
> Similarly, SET/ADD/DROP should be implemented also for FOR ALL
> SEQUENCES otherwise there is no way to manipulate those either.
>
> ======
> doc/src/sgml/ref/alter_publication.sgml
>
> 2.
> Implementing the "SET ALL TABLES" is only a start. You also need to
> have the other case:
>
> * ADD ALL TABLES
> * DROP ALL TABLES
>
> Note you might start out with something like "CREATE PUBLICATION pub
> FOR ALL TABLES, FOR ALL SEQUENCES" so you need to be able to be able
> to modify/remove the published TABLES part without overwriting
> published SEQUENCES part!!
>
> i.e The "SET" means set the publication; it doesn't mean add to the
> publication. So SET ALL TABLES obliterates any FOR ALL SEQUENCES.
>
> ~~~
>
> 3.
> +<phrase>where <replaceable
> class="parameter">publication_except_tables</replaceable> is:</phrase>
> +
> + [ EXCEPT TABLE ( [ ONLY ] <replaceable
> class="parameter">table_name</replaceable> [, ... ] ) ]
> +
>
> Hmm. Ideally, this should be part of 'publication_object' and
> publication_drop_object' because the ADD/DROP are also needed for the
> reasons given in my above review commentS.
>
> ~~~
>
> 4.
> <para>
> - The first three variants change which tables/schemas are part of the
> - publication. The <literal>SET</literal> clause will replace the list of
> - tables/schemas in the publication with the specified list; the existing
> - tables/schemas that were present in the publication will be removed. The
> + The first four variants modify which tables/schemas are included in the
> + publication, or which tables are excluded from it. The
> + <literal>SET ALL TABLES</literal> clause is used to update the
> + <literal>EXCEPT TABLE</literal> list of a <literal>FOR ALL TABLES</literal>
> + publication. If <literal>EXCEPT TABLE</literal> is specified with a list of
> + tables, the existing except table list is replaced with the
> specified tables.
> + If <literal>EXCEPT TABLE</literal> is omitted, the existing except table
> + list is cleared. The <literal>SET</literal> clause, when used with a
> + publication defined with <literal>FOR TABLE</literal> or
> + <literal>FOR TABLES IN SCHEMA</literal>, replaces the list of tables/schemas
> + in the publication with the specified list; the existing tables or schemas
> + that were present in the publication will be removed. The
>
> I find this all a bit dubious because nothing seems to be accounting
> for the possibility of "FOR ALL SEQUENCES" also in the publication...
> e.g this entire ALTER command should also have
>
> SET ALL SEQUENCES
> ADD ALL SEQUENCES
> DROP ALL SEQUENCE
>
> and
>
> SET ALL TABLES
> ADD ALL TABLES
> DROP ALL TABLES
>
> IMO, a user will need to take care when using ALTER PUBLICATION ...
> SET ALL TABLES that it does not destroy the publication of sequences
> (and vice versa)
>
> -- Start with an "empty" publication and make it a "FOR ALL TABLES"
> publication...
> CREATE PUBLICATION pub;
> ALTER PUBLICATION pub SET ALL TABLES;
> -- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES"
>
>
> -- give some table exceptions to it
> ALTER PUBLICATION pub SET ALL TABLES EXCEPT TABLE(t1,t2);
> -- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES
> EXCEPT TABLE(t1,t2)"
>
>
> -- add sequences to this
> ALTER PUBLICATION pub ADD ALL SEQUENCES
> -- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES
> EXCEPT TABLE(t1,t2), FOR ALL SEQUENCES"
>
>
> -- remove the table exception
> -- here you cannot simply use SET ALL TABLES because you will lose the
> ALL SEQUENCES part of the publication!!
> -- So, instead you need to do like below
> ALTER PUBLICATION pub DROP ALL TABLES;
> ALTER PUBLICATION pub ADD ALL TABLES;
> -- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES, FOR
> ALL SEQUENCES"
>
> ~~~
>
> 5.
> +</programlisting></para>
> +
> + <para>
> + Replace the publication's EXCEPT table list:
>
> /EXCEPT table list/EXCEPT TABLE list/
>
> ~~~
>
> 6.
> + <para>
> + Change the publication to include all tables by removing any existing
> + EXCEPT table list:
>
> The clearing of the EXCEPT TABLES is more like a side-effect, so I
> think this can be worded differently.
>
> SUGGESTION
> Reset the publication to be a FOR ALL TABLES publication with no
> excluded tables.

Thanks for the comments, the agreed comments have been addressed in
the v64 version patch attached.

Regards,
Vignesh

Attachment Content-Type Size
v64-0001-Add-support-for-EXCEPT-TABLE-in-ALTER-PUBLICATIO.patch application/octet-stream 35.7 KB

From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-17 11:01:43
Message-ID: CAJpy0uCN4gfP7fSt__KdW5wYQ82650Z6L4YLnjRHZTQ1yir1mg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 17, 2026 at 12:23 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> Thanks for the comments, the agreed comments have been addressed in
> the v64 version patch attached.
>

Please find a few comments:

1)
+ The
+ <literal>SET ALL TABLES</literal> clause is used to update the
+ <literal>EXCEPT TABLE</literal> list of a <literal>FOR ALL TABLES</literal>
+ publication. If <literal>EXCEPT TABLE</literal> is specified with a list of
+ tables, the existing except table list is replaced with the
specified tables.
+ If <literal>EXCEPT TABLE</literal> is omitted, the existing except table
+ list is cleared.

How about changing it to (or anything better to reflect new changes):

The SET ALL TABLES clause can transform an empty publication, or one
defined for ALL SEQUENCES (or both ALL TABLES and ALL SEQUENCES), into
a publication defined for ALL TABLES. Likewise, SET ALL SEQUENCES can
convert an empty publication, or one defined for ALL TABLES (or both
ALL TABLES and ALL SEQUENCES), into a publication defined for ALL
SEQUENCES.
In addition, SET ALL TABLES may be used to update the EXCEPT TABLE
list of a FOR ALL TABLES publication. If EXCEPT TABLE is specified
with a list of tables, the existing exclusion list is replaced with
the specified tables. If EXCEPT TABLE is omitted, the existing
exclusion list is cleared.

2)
+bool
+is_include_relation_publication(Oid pubid)

The name 'is_include_relation_publication' looks slightly odd to me.
Few options are: is_explicit_table_publication,
is_table_list_publication, is_table_publication. Or anything better if
you can think of?

3)
is_include_relation_publication:

+ /* If we find even one included relation, we are done */
+ if (!pubrel->prexcept)
+ {
+ result = true;
+ break;
+ }

we can break the loop irrespective of the 'prexcept' flag as we can
never have a combination of mixed prexcept entries for the same pub.
Whether all will be with prexcept=true or all will be false. Even a
loop is not needed. We can fetch the first entry alone (similar to
is_schema_publication) and if that is valid, we can check the flag and
return accordingly. Something like:

if (HeapTupleIsValid())
{
pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
result = !pubrel->prexcept
}

4)
publication_add_relation:
+ /*
+ * True if EXCEPT tables require explicit relcache invalidation. If
+ * 'puballtables' changes, global invalidation covers them.
+ */
+ inval_except_table = (stmt != NULL) &&
+ (stmt->for_all_tables == pub->alltables);

It took me some time to figure out why we don't need invalidation for
the case where we are converting ALL SEQ to ALL TABLEs EXCEPT(..). I
think it is worth adding more comments here. Suggestion:

/*
* Determine whether EXCEPT tables require explicit relcache invalidation.
*
* For CREATE PUBLICATION with EXCEPT tables, invalidation is not needed,
* since it is handled when marking the publication as ALL TABLES.
*
* For ALTER PUBLICATION, invalidation is needed only when adding an EXCEPT
* table to a publication already marked as ALL TABLES. For publications
* that were originally empty or defined as ALL SEQUENCES and are being
* converted to ALL TABLES, invalidation is skipped here, as it is handled
* when marking the publication as ALL TABLES.
*/

thanks
Shveta


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-17 12:05:32
Message-ID: CAA4eK1+mSpCzj+B2PW_68DJpXHA0KMgT9Nrz9P83_c1vdKya8g@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 17, 2026 at 4:31 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> 2)
> +bool
> +is_include_relation_publication(Oid pubid)
>
> The name 'is_include_relation_publication' looks slightly odd to me.
> Few options are: is_explicit_table_publication,
> is_table_list_publication, is_table_publication. Or anything better if
> you can think of?
>

+1 for is_table_publication() as it matches the existing function
is_schema_publication().

Few other comments:
=================
*
- The <literal>ADD TABLES IN SCHEMA</literal> and
- <literal>SET TABLES IN SCHEMA</literal> to a publication requires the
+ The <literal>ADD TABLES IN SCHEMA</literal>,
+ <literal>SET TABLES IN SCHEMA</literal>, and
+ <literal>SET ALL TABLES</literal> to a publication requires the
invoking user to be a superuser.

Do we need to mention SET ALL SEQUENCES variant as well?

*
AlterPublicationTables(stmt, tup, relations, pstate->p_sourcetext,
schemaidlist != NIL);
AlterPublicationSchemas(stmt, tup, schemaidlist);
+
+ if (stmt->for_all_tables || stmt->for_all_sequences)
+ {
+ bool nulls[Natts_pg_publication];
+ bool replaces[Natts_pg_publication];
+ Datum values[Natts_pg_publication];
+ bool dirty = false;
+
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));
+
+ if (stmt->for_all_tables != pubform->puballtables)
+ {
+ values[Anum_pg_publication_puballtables - 1] =
+ BoolGetDatum(stmt->for_all_tables);
+ replaces[Anum_pg_publication_puballtables - 1] = true;
+ dirty = true;
+ }
+
+ if (stmt->for_all_sequences != pubform->puballsequences)
+ {
+ values[Anum_pg_publication_puballsequences - 1] =
+ BoolGetDatum(stmt->for_all_sequences);
+ replaces[Anum_pg_publication_puballsequences - 1] = true;
+ dirty = true;
+ }
+
+ if (dirty)
+ {
+ tup = heap_modify_tuple(tup, RelationGetDescr(rel), values,
+ nulls, replaces);
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+ CommandCounterIncrement();
+
+ /* For ALL TABLES, we must invalidate all relcache entries */
+ if (replaces[Anum_pg_publication_puballtables - 1])
+ CacheInvalidateRelcacheAll();
+ }
+ }

Can we move this new code to a separate function, say
AlterPublicationAllFlags()?

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-17 15:51:15
Message-ID: CALDaNm32+c6RTE5xR6sJ=MZGgwEtzjkxpov_Hu70MXfbvmN+=Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, 17 Mar 2026 at 16:31, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Tue, Mar 17, 2026 at 12:23 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > Thanks for the comments, the agreed comments have been addressed in
> > the v64 version patch attached.
> >
>
> Please find a few comments:
>
>
> 1)
> + The
> + <literal>SET ALL TABLES</literal> clause is used to update the
> + <literal>EXCEPT TABLE</literal> list of a <literal>FOR ALL TABLES</literal>
> + publication. If <literal>EXCEPT TABLE</literal> is specified with a list of
> + tables, the existing except table list is replaced with the
> specified tables.
> + If <literal>EXCEPT TABLE</literal> is omitted, the existing except table
> + list is cleared.
>
> How about changing it to (or anything better to reflect new changes):
>
> The SET ALL TABLES clause can transform an empty publication, or one
> defined for ALL SEQUENCES (or both ALL TABLES and ALL SEQUENCES), into
> a publication defined for ALL TABLES. Likewise, SET ALL SEQUENCES can
> convert an empty publication, or one defined for ALL TABLES (or both
> ALL TABLES and ALL SEQUENCES), into a publication defined for ALL
> SEQUENCES.
> In addition, SET ALL TABLES may be used to update the EXCEPT TABLE
> list of a FOR ALL TABLES publication. If EXCEPT TABLE is specified
> with a list of tables, the existing exclusion list is replaced with
> the specified tables. If EXCEPT TABLE is omitted, the existing
> exclusion list is cleared.
>
> 2)
> +bool
> +is_include_relation_publication(Oid pubid)
>
> The name 'is_include_relation_publication' looks slightly odd to me.
> Few options are: is_explicit_table_publication,
> is_table_list_publication, is_table_publication. Or anything better if
> you can think of?
>
> 3)
> is_include_relation_publication:
>
> + /* If we find even one included relation, we are done */
> + if (!pubrel->prexcept)
> + {
> + result = true;
> + break;
> + }
>
> we can break the loop irrespective of the 'prexcept' flag as we can
> never have a combination of mixed prexcept entries for the same pub.
> Whether all will be with prexcept=true or all will be false. Even a
> loop is not needed. We can fetch the first entry alone (similar to
> is_schema_publication) and if that is valid, we can check the flag and
> return accordingly. Something like:
>
> if (HeapTupleIsValid())
> {
> pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
> result = !pubrel->prexcept
> }
>
>
> 4)
> publication_add_relation:
> + /*
> + * True if EXCEPT tables require explicit relcache invalidation. If
> + * 'puballtables' changes, global invalidation covers them.
> + */
> + inval_except_table = (stmt != NULL) &&
> + (stmt->for_all_tables == pub->alltables);
>
>
> It took me some time to figure out why we don't need invalidation for
> the case where we are converting ALL SEQ to ALL TABLEs EXCEPT(..). I
> think it is worth adding more comments here. Suggestion:
>
> /*
> * Determine whether EXCEPT tables require explicit relcache invalidation.
> *
> * For CREATE PUBLICATION with EXCEPT tables, invalidation is not needed,
> * since it is handled when marking the publication as ALL TABLES.
> *
> * For ALTER PUBLICATION, invalidation is needed only when adding an EXCEPT
> * table to a publication already marked as ALL TABLES. For publications
> * that were originally empty or defined as ALL SEQUENCES and are being
> * converted to ALL TABLES, invalidation is skipped here, as it is handled
> * when marking the publication as ALL TABLES.
> */

These comments are addressed in the v65 version patch attached. Also
the comments from [1] have been addressed in this.
[1] - https://www.postgresql.org/message-id/CAA4eK1%2BmSpCzj%2BB2PW_68DJpXHA0KMgT9Nrz9P83_c1vdKya8g%40mail.gmail.com

Regards,
Vignesh

Attachment Content-Type Size
v65-0001-Add-support-for-EXCEPT-TABLE-in-ALTER-PUBLICATIO.patch application/octet-stream 37.6 KB

From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-18 04:10:24
Message-ID: CAJpy0uCMnF25JNgx1vnQMV3FQoiiqdOJYwnCqYcOZ-g6B8+fWA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 17, 2026 at 9:21 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
>
> These comments are addressed in the v65 version patch attached. Also
> the comments from [1] have been addressed in this.
> [1] - https://www.postgresql.org/message-id/CAA4eK1%2BmSpCzj%2BB2PW_68DJpXHA0KMgT9Nrz9P83_c1vdKya8g%40mail.gmail.com
>

Thanks, few trivial things:

1)
In the doc we talk about the first two variants and then the third
variant. IIUC, you need to change variants to match the new details,
i.e.

Change these:
ALTER PUBLICATION name ADD publication_object [, ...]
ALTER PUBLICATION name SET { publication_object [, ...] |
publication_all_object [, ... ] }
ALTER PUBLICATION name DROP publication_drop_object [, ...]

to:
ALTER PUBLICATION name ADD publication_object [, ...]
ALTER PUBLICATION name DROP publication_drop_object [, ...]
ALTER PUBLICATION name SET { publication_object [, ...] |
publication_all_object [, ... ] }

or change the details to match variants.

2)

+ /*
+ * Publications contain either only EXCEPT entries or only included
+ * tables. So checking a single tuple is sufficient.
+ */
+ result = !pubrel->prexcept;

The command looks slightly misleading, can we please change it to:

For any publication, pg_publication_rel contains either only EXCEPT
entries or only explicitly included tables. Therefore, examining the
first tuple is sufficient to determine table inclusion.

3)
publication_add_relation() contains repetitive comments at both the
beginning and end of the function regarding invalidation of EXCEPT
tables. We can keep the first one (slightly rephrased, if needed, to
incorporate the second) and remove the latter.

thanks
Shveta


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-18 04:27:26
Message-ID: CAHut+PvDxbhexmbcRaxBa8X_7kH8v=Rcdokde_ESqXtXVJ4Waw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Mar 18, 2026 at 3:10 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Tue, Mar 17, 2026 at 9:21 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> >
> > These comments are addressed in the v65 version patch attached. Also
> > the comments from [1] have been addressed in this.
> > [1] - https://www.postgresql.org/message-id/CAA4eK1%2BmSpCzj%2BB2PW_68DJpXHA0KMgT9Nrz9P83_c1vdKya8g%40mail.gmail.com
> >
>
> Thanks, few trivial things:
>
> 1)
> In the doc we talk about the first two variants and then the third
> variant. IIUC, you need to change variants to match the new details,
> i.e.
>
> Change these:
> ALTER PUBLICATION name ADD publication_object [, ...]
> ALTER PUBLICATION name SET { publication_object [, ...] |
> publication_all_object [, ... ] }
> ALTER PUBLICATION name DROP publication_drop_object [, ...]
>
> to:
> ALTER PUBLICATION name ADD publication_object [, ...]
> ALTER PUBLICATION name DROP publication_drop_object [, ...]
> ALTER PUBLICATION name SET { publication_object [, ...] |
> publication_all_object [, ... ] }
>
> or change the details to match variants.
>

+1

(I was about to post the same comment)

Talking about "variants" like this forces the reader to keep referring
back to the synopsis to try to figure out what is actually being
described.

A simple improvement like below could help clarify things:
e.g. say "The third variant (DROP)" instead of just saying "The third variant"
e.g. say "The fourth variant (SET parameters)" instead of just saying
"The fourth variant"
etc.

Aside from that, AFAICT, the patch is a bit muddled about some variant numbers.

e.g.1 "The first two variants modify which tables/schemas are part of
the publication. The ADD and DROP clauses will add and remove one or
more tables/schemas from the publication."

No, because DROP is the 3rd variant, not in the "first two",

e.g.2. "The third variant either modifies the included tables/schemas
or marks the publication..."

No, the 3rd variant now is DROP. But this whole paragraph is referring
to SET objects.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-18 06:20:34
Message-ID: CAD21AoCuy_yAtzLa+cHEM5hRN3u8Ff0jXrZiyeBD9dc+bqhkLA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, Mar 14, 2026 at 2:35 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Fri, Mar 13, 2026 at 11:51 PM Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com> wrote:
> >
> > On Fri, Mar 13, 2026 at 2:51 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> > >
> > > On Fri, Mar 13, 2026 at 8:55 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> > > >
> > > > Hou-San (off-list) gave an interesting example of how it might look
> > > > when the example is combined with the hypothetical future ability to
> > > > exclude all schema tables from a "FOR ALL TABLES"
> > > > CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, t2, TABLES IN
> > > > SCHEMA s1);
> > > >
> > >
> > > So, if we follow this, in future, the syntax would look like:
> > > Create publication pub1 FOR ALL TABLES EXCEPT (TABLE t1, t2, TABLES IN
> > > SCHEMA s1, s2), ALL SEQUENCES EXCEPT (SEQUENCE s1);
> > >
> > > I think if we use the above syntax then one can also argue that why
> > > not use FOR ALL (TABLES, SEQUENCES) instead of ALL TABLES, ALL
> > > SEQUENCES.
> >
> > The same is true for the syntaxes of TABLE(t1, t2) and SCHEMA(s1, s2),
> > no? If we allow grouping the tables and the schemas by TABLE and
> > SCHEMA keywords respectively in exclusion lists, one could argue why
> > we don't allow it for the inclusion list.
> >
> > >
> > > Instead the current command would like:
> > > Create publication pub1 FOR ALL TABLES EXCEPT TABLE (t1, t2), EXCEPT
> > > TABLES IN SCHEMA (s1, s2), ALL SEQUENCES EXCEPT SEQUENCE (seq1, seq2);
> > >
> > > Though it is slightly lengthy it makes the syntax local such that the
> > > meaning of a clause is determined by what is inside it, not by
> > > something that appears ten words later.
> >
> > While it helps the syntax locality, I'm concerned that it could make
> > the context of the EXCEPT clause ambiguous. For example, IIUC the
> > above syntax rule would allow us to write:
> >
> > CREATE PUBLICATION pub1 FOR ALL TABLES EXCEPT TABLES IN SCHEMA (s1),
> > EXCEPT TABLE (t1);
> >
> > Regarding the second EXCEPT clause, while one might think it excludes
> > t1 from ALL TABLES, one might think it excludes t1 from the first
> > EXCLUDE clause (i.e., the publication actually includes t1 in the
> > publication).
> >
>
> According to me, the comma between EXCEPT clauses breaks such a chain
> of thought but others may think differently. The docs can clarify such
> a confusion if any but if multiple people interpret it the way you
> think, I am fine to go with the direction you are proposing. I am
> slightly worried that both syntaxes have some pros and cons, so even
> if we change to what you are suggesting, one can argue to go back to
> previous syntax as that also has some merits. So, I feel we can
> complete the pending patch [1] and try to get the opinion of some
> other people unless changing the code to support another alternative
> is difficult.

I agree to complete the pending ALTER PUBLICATION part first and then
have more discussion on it. As Vignesh showed in another email, the
changes are straightforward.

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-18 06:40:48
Message-ID: CAHut+PtQbK9USLepyzArXFoNuLok1MsBu_Jg4UT=koZocombFw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Vignesh.

Some review comments for patch v65-0001.

======
doc/src/sgml/ref/alter_publication.sgml

1.
It seems that SET ALL TABLES is not supported if the publication
already has FOR TABLE.

e.g
alter publication pub1 set all tables;
ERROR: publication "pub1" does not support ALL TABLES operations
DETAIL: This operation requires the publication to be defined as FOR
ALL TABLES/SEQUENCES or to be empty.

e.g.
alter publication pub2 set table t1;
ERROR: publication "pub2" is defined as FOR ALL TABLES
DETAIL: Tables or sequences cannot be added to or dropped from FOR
ALL TABLES publications.

I am not going to debate what rules are right or wrong. (Some rules do
seem a bit ad-hoc to me, but maybe they are just erring on the safety
side). But my point is that the documentation does not seem to say
anything much about what the rules are

e.g. it says "Adding/Setting any schema when the publication also
publishes a table with a column list, and vice versa is not
supported.", but OTOH it says nothing about what is
supported/unsupported for SET ALL TABLES.

======
src/backend/catalog/pg_publication.c

2.
+/*
+ * Returns true if the publication has explicitly included relation (i.e.,
+ * not marked as EXCEPT).
+ */
+bool
+is_table_publication(Oid pubid)

To me, an "explicitly included relation" is like when you say "FOR
TABLE t1", where the "t1" is explicitly named.

So it's not very clear whether you consider "FOR ALL TABLES" or a
"FOR TABLES IN SCHEMA" publication explicitly includes tables or not?

The function comment needs to be clearer.

~~~

publication_add_relation:

3.
+ /*
+ * Determine whether EXCEPT tables require explicit relcache invalidation.
+ *
+ * For CREATE PUBLICATION with EXCEPT tables, invalidation is not needed,
+ * since it is handled when marking the publication as ALL TABLES.
+ *
+ * For ALTER PUBLICATION, invalidation is needed only when adding an EXCEPT
+ * table to a publication already marked as ALL TABLES. For publications
+ * that were originally empty or defined as ALL SEQUENCES and are being
+ * converted to ALL TABLES, invalidation is skipped here, as it is handled
+ * when marking the publication as ALL TABLES.
+ */
+ inval_except_table = (stmt != NULL) &&
+ (stmt->for_all_tables == pub->alltables);

3a.
Why is this code done at the top of the function? Can you move it to
be adjacent to where it is getting used?

~

3b.
I think 'alter_stmt' or 'alter_pub_stmt' might be a more informative
name here, instead of the generic 'stmt'

======
src/backend/commands/publicationcmds.c

4.
- TransformPubWhereClauses(rels, queryString, pubform->pubviaroot);
+ if (isexcept)
+ oldrelids = GetExcludedPublicationTables(pubid,
+ PUBLICATION_PART_ROOT);
+ else
+ {
+ oldrelids = GetIncludedPublicationRelations(pubid,
+ PUBLICATION_PART_ROOT);

I felt there were some subtle things that the logic is using here:

e.g.
It seems that because this function is called...
And because it is SET ....
And because it is SET ALL TABLES ...
Then, the tables can only be those in the EXCEPT TABLE list

Maybe more comments about 'isexcept', and maybe an Assert(oldrelids !=
NIL); could help here (??)

~~~

AlterPublicationAllFlags:

5.
+ bool nulls[Natts_pg_publication];
+ bool replaces[Natts_pg_publication];
+ Datum values[Natts_pg_publication];
+ bool dirty = false;
+
+ if (!stmt->for_all_tables && !stmt->for_all_sequences)
+ return;
+
+ pubform = (Form_pg_publication) GETSTRUCT(tup);
+
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));

AFAIK, these memsets are not needed if you just say "= {0}" where
those vars are declared.

~~~

AlterPublication:

6.
+ relations = list_concat(relations, exceptrelations);
AlterPublicationTables(stmt, tup, relations, pstate->p_sourcetext,
schemaidlist != NIL);

I did not quite understand this list_concat.

Is this somehow asserting that `relations` must be empty when there
were `exceptrelations` and vice versa, because other combinations are
not supported by ALTER -- e.g. is this just a trick to so you can pass
the same parameter to AlterPublicationTables? This seems related to
the 'isexecpt' AlterPublicationTables function, which was also quite
subtle.

Bottom line is, I'm unsure what the logic is here, but it appears
overly tricky to me. Would more comments help?

======
src/backend/parser/gram.y

7.
+ * ALL TABLES [ EXCEPT TABLE ( table_name [, ...] ) ]

The CREATE/ALTER docs synopsis says "[ ONLY ] table_name [ * ]" which
is different from this comment. So are ONLY and * handled properly or
not?

======
src/include/nodes/parsenodes.h

8.
+ bool for_all_tables; /* True if SET ALL TABLES is specified */
+ bool for_all_sequences; /* True if SET ALL SEQUENCES is specified */

Maybe these comments do not need to mention the keyword "SET".

That way, in future if/when ADD/DROP get implemented, then this code
won't need to churn again.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-18 08:05:12
Message-ID: CAHut+Pux6Nme8ifQmyeXVQ0RYYkcM6=a1cSwkS9Ar-3F_XN4mQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Vignesh

Here are some review comments for v65-0001 (test code part)

======
src/test/regress/expected/publication.out

1.
+-- fail - SET ALL TABLES on a publication requires superuser privileges
+ALTER PUBLICATION testpub5 SET ALL TABLES EXCEPT TABLE (testpub_tbl1); -- fail
+ERROR: must be superuser to alter FOR ALL TABLES publication
+ALTER PUBLICATION testpub5 SET ALL TABLES; -- fail
+ERROR: must be superuser to alter FOR ALL TABLES publication
+SET ROLE regress_publication_user;
+DROP PUBLICATION testpub4, testpub5;

The error messages don't quite seem correct. e.g. You are not trying
"to alter FOR ALL TABLES publication". You are trying to alter a
publication to convert it to a "FOR ALL TABLES" publication.

======
src/test/regress/sql/publication.sql

2.
+-- fail - SET ALL TABLES is not allowed for a 'FOR TABLE' publication

I think these failure tests should be under the "-- SET ALL
TABLES/SEQUENCES" test comment.

~~~

3.
+-- fail - SET ALL TABLES is not allowed for a schema publication

I think these failure tests should be under the "-- SET ALL
TABLES/SEQUENCES" test comment.

~~~

4.
+CREATE PUBLICATION testpub_forall_tbls_seqs;

Add a comment to say this is creating an "empty" publication in
preparation for subsequent tests

~~~

5.
+-- Remove all the EXCEPT tables.
+ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES;
+\dRp+ testpub_foralltables_excepttable
+
+-- Replace the publication EXCEPT table list with a specific EXCEPT table.
+ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES
EXCEPT TABLE (testpub_tbl1);
+\dRp+ testpub_foralltables_excepttable

5a.
Are these test OK?
* The 1st test says "Remove EXCEPT" but was there any EXCEPT list to start with?
* The 2nd test say "Replace EXCEPT" but there was nothing replace
because previous test removed it.
* e.g. there seems not test that replaces one EXCEPT with a different EXCEPT

~

5b.
Shouldn't all these tests also all be under the "-- SET ALL
TABLES/SEQUENCES" test comment?

~~~

6.
+-- fail - SET ALL TABLES on a publication requires superuser privileges
+ALTER PUBLICATION testpub5 SET ALL TABLES EXCEPT TABLE (testpub_tbl1); -- fail
+ALTER PUBLICATION testpub5 SET ALL TABLES; -- fail

Shouldn't all these tests also all be under the "-- SET ALL
TABLES/SEQUENCES" test comment?

======
src/test/subscription/t/037_except.pl

7.
+# Verify that table synchronization occurs once tab1 is removed from the
+# EXCEPT TABLE clause via SET ALL TABLES EXCEPT TABLE.
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM tab1");
+is($result, qq(20),
+ 'check that the data is copied as the tab1 is removed from EXCEPT
TABLE clause'
+);

The comment is strangely worded. Talking about removing from EXCEPT
lists is confusing. How about?

-- Verify that table synchronization now happens for tab1.
-- tab1 is included now since the EXCEPT TABLE list is only (tab2).

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-18 08:14:21
Message-ID: CAA4eK1JfPVXh1rVQV1Y_YoaX52hEi0OVxyT2_HKfKcKd55pR0w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Mar 18, 2026 at 1:35 PM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> ======
> src/test/regress/expected/publication.out
>
> 1.
> +-- fail - SET ALL TABLES on a publication requires superuser privileges
> +ALTER PUBLICATION testpub5 SET ALL TABLES EXCEPT TABLE (testpub_tbl1); -- fail
> +ERROR: must be superuser to alter FOR ALL TABLES publication
> +ALTER PUBLICATION testpub5 SET ALL TABLES; -- fail
> +ERROR: must be superuser to alter FOR ALL TABLES publication
> +SET ROLE regress_publication_user;
> +DROP PUBLICATION testpub4, testpub5;
>
> The error messages don't quite seem correct. e.g. You are not trying
> "to alter FOR ALL TABLES publication". You are trying to alter a
> publication to convert it to a "FOR ALL TABLES" publication.
>

I also find this error message not conveying the proper information. I
suggest changing it to: "must be superuser to set ALL TABLES" and
"must be superuser to set ALL SEQUENCES" for all tables, sequences
cases respectively.

--
With Regards,
Amit Kapila.


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-18 08:58:49
Message-ID: CAA4eK1LCh7iCy2raNRrfVaS0LJaHxYokCUaNVue-qLfR=iG1PA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Mar 18, 2026 at 12:11 PM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> ======
> doc/src/sgml/ref/alter_publication.sgml
>
> 1.
> It seems that SET ALL TABLES is not supported if the publication
> already has FOR TABLE.
>
> e.g
> alter publication pub1 set all tables;
> ERROR: publication "pub1" does not support ALL TABLES operations
> DETAIL: This operation requires the publication to be defined as FOR
> ALL TABLES/SEQUENCES or to be empty.
>
> e.g.
> alter publication pub2 set table t1;
> ERROR: publication "pub2" is defined as FOR ALL TABLES
> DETAIL: Tables or sequences cannot be added to or dropped from FOR
> ALL TABLES publications.
>
> I am not going to debate what rules are right or wrong. (Some rules do
> seem a bit ad-hoc to me, but maybe they are just erring on the safety
> side). But my point is that the documentation does not seem to say
> anything much about what the rules are
>
> e.g. it says "Adding/Setting any schema when the publication also
> publishes a table with a column list, and vice versa is not
> supported.", but OTOH it says nothing about what is
> supported/unsupported for SET ALL TABLES.
>

Most of these rules pre-exist this patch, we can add more docs for
these but not sure if it is worth it.

> ======
> src/backend/catalog/pg_publication.c
>
> 2.
> +/*
> + * Returns true if the publication has explicitly included relation (i.e.,
> + * not marked as EXCEPT).
> + */
> +bool
> +is_table_publication(Oid pubid)
>
> To me, an "explicitly included relation" is like when you say "FOR
> TABLE t1", where the "t1" is explicitly named.
>
> So it's not very clear whether you consider "FOR ALL TABLES" or a
> "FOR TABLES IN SCHEMA" publication explicitly includes tables or not?
>
> The function comment needs to be clearer.
>

It is clear for me that it means ("FOR TABLE t1") and follows what we
wrote atop is_schema_publication.

>
> AlterPublication:
>
> 6.
> + relations = list_concat(relations, exceptrelations);
> AlterPublicationTables(stmt, tup, relations, pstate->p_sourcetext,
> schemaidlist != NIL);
>
> I did not quite understand this list_concat.
>
> Is this somehow asserting that `relations` must be empty when there
> were `exceptrelations` and vice versa, because other combinations are
> not supported by ALTER -- e.g. is this just a trick to so you can pass
> the same parameter to AlterPublicationTables? This seems related to
> the 'isexecpt' AlterPublicationTables function, which was also quite
> subtle.
>
> Bottom line is, I'm unsure what the logic is here, but it appears
> overly tricky to me. Would more comments help?
>

The logic is quite simple here, we need to treat both types of
included/excluded relations the same w.r.t recording them in catalog.
The only difference is for excluded relations, except flag will be
true. I feel adding comments for such simple stuff is not required,
otherwise, the code will be filled with comments explaining simple
things which one can easily make out if she understands the logic
behind the code.

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-18 13:21:02
Message-ID: CALDaNm1tKuU479T=winBqoMb3MzO3Mta2juk8W3t2R5ps0_zyg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 18 Mar 2026 at 12:11, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Vignesh.
>
> Some review comments for patch v65-0001.
>
> ======
> doc/src/sgml/ref/alter_publication.sgml
>
> 1.
> It seems that SET ALL TABLES is not supported if the publication
> already has FOR TABLE.
>
> e.g
> alter publication pub1 set all tables;
> ERROR: publication "pub1" does not support ALL TABLES operations
> DETAIL: This operation requires the publication to be defined as FOR
> ALL TABLES/SEQUENCES or to be empty.
>
> e.g.
> alter publication pub2 set table t1;
> ERROR: publication "pub2" is defined as FOR ALL TABLES
> DETAIL: Tables or sequences cannot be added to or dropped from FOR
> ALL TABLES publications.
>
> I am not going to debate what rules are right or wrong. (Some rules do
> seem a bit ad-hoc to me, but maybe they are just erring on the safety
> side). But my point is that the documentation does not seem to say
> anything much about what the rules are
>
> e.g. it says "Adding/Setting any schema when the publication also
> publishes a table with a column list, and vice versa is not
> supported.", but OTOH it says nothing about what is
> supported/unsupported for SET ALL TABLES.

Amit has already replied to this at [1].

> ======
> src/backend/catalog/pg_publication.c
>
> 2.
> +/*
> + * Returns true if the publication has explicitly included relation (i.e.,
> + * not marked as EXCEPT).
> + */
> +bool
> +is_table_publication(Oid pubid)
>
> To me, an "explicitly included relation" is like when you say "FOR
> TABLE t1", where the "t1" is explicitly named.
>
> So it's not very clear whether you consider "FOR ALL TABLES" or a
> "FOR TABLES IN SCHEMA" publication explicitly includes tables or not?
>
> The function comment needs to be clearer.

Amit has already replied to this at [1].

> ~~~
>
> publication_add_relation:
>
> 3.
> + /*
> + * Determine whether EXCEPT tables require explicit relcache invalidation.
> + *
> + * For CREATE PUBLICATION with EXCEPT tables, invalidation is not needed,
> + * since it is handled when marking the publication as ALL TABLES.
> + *
> + * For ALTER PUBLICATION, invalidation is needed only when adding an EXCEPT
> + * table to a publication already marked as ALL TABLES. For publications
> + * that were originally empty or defined as ALL SEQUENCES and are being
> + * converted to ALL TABLES, invalidation is skipped here, as it is handled
> + * when marking the publication as ALL TABLES.
> + */
> + inval_except_table = (stmt != NULL) &&
> + (stmt->for_all_tables == pub->alltables);
>
> 3a.
> Why is this code done at the top of the function? Can you move it to
> be adjacent to where it is getting used?

Modified

> ~
>
> 3b.
> I think 'alter_stmt' or 'alter_pub_stmt' might be a more informative
> name here, instead of the generic 'stmt'

Modified

> ======
> src/backend/commands/publicationcmds.c
>
> 4.
> - TransformPubWhereClauses(rels, queryString, pubform->pubviaroot);
> + if (isexcept)
> + oldrelids = GetExcludedPublicationTables(pubid,
> + PUBLICATION_PART_ROOT);
> + else
> + {
> + oldrelids = GetIncludedPublicationRelations(pubid,
> + PUBLICATION_PART_ROOT);
>
> I felt there were some subtle things that the logic is using here:
>
> e.g.
> It seems that because this function is called...
> And because it is SET ....
> And because it is SET ALL TABLES ...
> Then, the tables can only be those in the EXCEPT TABLE list
>
> Maybe more comments about 'isexcept', and maybe an Assert(oldrelids !=
> NIL); could help here (??)

Updated comments

> ~~~
>
> AlterPublicationAllFlags:
>
> 5.
> + bool nulls[Natts_pg_publication];
> + bool replaces[Natts_pg_publication];
> + Datum values[Natts_pg_publication];
> + bool dirty = false;
> +
> + if (!stmt->for_all_tables && !stmt->for_all_sequences)
> + return;
> +
> + pubform = (Form_pg_publication) GETSTRUCT(tup);
> +
> + memset(values, 0, sizeof(values));
> + memset(nulls, false, sizeof(nulls));
> + memset(replaces, false, sizeof(replaces));
>
> AFAIK, these memsets are not needed if you just say "= {0}" where
> those vars are declared.

modified

> AlterPublication:
>
> 6.
> + relations = list_concat(relations, exceptrelations);
> AlterPublicationTables(stmt, tup, relations, pstate->p_sourcetext,
> schemaidlist != NIL);
>
> I did not quite understand this list_concat.
>
> Is this somehow asserting that `relations` must be empty when there
> were `exceptrelations` and vice versa, because other combinations are
> not supported by ALTER -- e.g. is this just a trick to so you can pass
> the same parameter to AlterPublicationTables? This seems related to
> the 'isexecpt' AlterPublicationTables function, which was also quite
> subtle.
>
> Bottom line is, I'm unsure what the logic is here, but it appears
> overly tricky to me. Would more comments help?

Amit has already replied to this at [1].

> ======
> src/backend/parser/gram.y
>
> 7.
> + * ALL TABLES [ EXCEPT TABLE ( table_name [, ...] ) ]
>
> The CREATE/ALTER docs synopsis says "[ ONLY ] table_name [ * ]" which
> is different from this comment. So are ONLY and * handled properly or
> not?

It is handled, Is there any issue with the code? It is documented that
way to keep it consistent with CreatePublicationStmt and ALTER
PUBLICATION ADD/DROP/SET pub_obj.

> ======
> src/include/nodes/parsenodes.h
>
> 8.
> + bool for_all_tables; /* True if SET ALL TABLES is specified */
> + bool for_all_sequences; /* True if SET ALL SEQUENCES is specified */
>
> Maybe these comments do not need to mention the keyword "SET".
>
> That way, in future if/when ADD/DROP get implemented, then this code
> won't need to churn again.

Modified

The attached v66 version patch has the changes for the same.

The comments from [2] have also been addressed in the attached patch.
[1] - https://www.postgresql.org/message-id/CAA4eK1LCh7iCy2raNRrfVaS0LJaHxYokCUaNVue-qLfR%3DiG1PA%40mail.gmail.com
[2] - https://www.postgresql.org/message-id/CAJpy0uCMnF25JNgx1vnQMV3FQoiiqdOJYwnCqYcOZ-g6B8%2BfWA%40mail.gmail.com

Regards,
Vignesh

Attachment Content-Type Size
v66-0001-Add-support-for-EXCEPT-TABLE-in-ALTER-PUBLICATIO.patch application/octet-stream 38.0 KB

From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-18 13:23:53
Message-ID: CALDaNm0V-+qN4KX0DcAQ2Yd8Otpq7eGVwNJ0g7Q4Got-diOhfQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 18 Mar 2026 at 09:57, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> On Wed, Mar 18, 2026 at 3:10 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > On Tue, Mar 17, 2026 at 9:21 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > >
> > >
> > > These comments are addressed in the v65 version patch attached. Also
> > > the comments from [1] have been addressed in this.
> > > [1] - https://www.postgresql.org/message-id/CAA4eK1%2BmSpCzj%2BB2PW_68DJpXHA0KMgT9Nrz9P83_c1vdKya8g%40mail.gmail.com
> > >
> >
> > Thanks, few trivial things:
> >
> > 1)
> > In the doc we talk about the first two variants and then the third
> > variant. IIUC, you need to change variants to match the new details,
> > i.e.
> >
> > Change these:
> > ALTER PUBLICATION name ADD publication_object [, ...]
> > ALTER PUBLICATION name SET { publication_object [, ...] |
> > publication_all_object [, ... ] }
> > ALTER PUBLICATION name DROP publication_drop_object [, ...]
> >
> > to:
> > ALTER PUBLICATION name ADD publication_object [, ...]
> > ALTER PUBLICATION name DROP publication_drop_object [, ...]
> > ALTER PUBLICATION name SET { publication_object [, ...] |
> > publication_all_object [, ... ] }
> >
> > or change the details to match variants.
> >
>
> +1
>
> (I was about to post the same comment)
>
> Talking about "variants" like this forces the reader to keep referring
> back to the synopsis to try to figure out what is actually being
> described.
>
> A simple improvement like below could help clarify things:
> e.g. say "The third variant (DROP)" instead of just saying "The third variant"
> e.g. say "The fourth variant (SET parameters)" instead of just saying
> "The fourth variant"
> etc.
>
> Aside from that, AFAICT, the patch is a bit muddled about some variant numbers.
>
> e.g.1 "The first two variants modify which tables/schemas are part of
> the publication. The ADD and DROP clauses will add and remove one or
> more tables/schemas from the publication."
>
> No, because DROP is the 3rd variant, not in the "first two",
>
> e.g.2. "The third variant either modifies the included tables/schemas
> or marks the publication..."
>
> No, the 3rd variant now is DROP. But this whole paragraph is referring
> to SET objects.

The order issue has been fixed in the v66 version patch attached at
[1]. I felt the variant related detailing improvement can be handled
separately if required after the patch is completed.
[1] - https://www.postgresql.org/message-id/CALDaNm1tKuU479T%3DwinBqoMb3MzO3Mta2juk8W3t2R5ps0_zyg%40mail.gmail.com

Regards,
Vignesh


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-18 13:26:32
Message-ID: CALDaNm32XwrrMLJ3a31eU7h_y2mjP8NzbAXwwiuthkxD+X5rhA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 18 Mar 2026 at 13:35, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Vignesh
>
> Here are some review comments for v65-0001 (test code part)
>
> ======
> src/test/regress/expected/publication.out
>
> 1.
> +-- fail - SET ALL TABLES on a publication requires superuser privileges
> +ALTER PUBLICATION testpub5 SET ALL TABLES EXCEPT TABLE (testpub_tbl1); -- fail
> +ERROR: must be superuser to alter FOR ALL TABLES publication
> +ALTER PUBLICATION testpub5 SET ALL TABLES; -- fail
> +ERROR: must be superuser to alter FOR ALL TABLES publication
> +SET ROLE regress_publication_user;
> +DROP PUBLICATION testpub4, testpub5;
>
> The error messages don't quite seem correct. e.g. You are not trying
> "to alter FOR ALL TABLES publication". You are trying to alter a
> publication to convert it to a "FOR ALL TABLES" publication.

Modified the error message

> ======
> src/test/regress/sql/publication.sql
>
> 2.
> +-- fail - SET ALL TABLES is not allowed for a 'FOR TABLE' publication
>
> I think these failure tests should be under the "-- SET ALL
> TABLES/SEQUENCES" test comment.

Modified

> 3.
> +-- fail - SET ALL TABLES is not allowed for a schema publication
>
> I think these failure tests should be under the "-- SET ALL
> TABLES/SEQUENCES" test comment.

Modified

> 4.
> +CREATE PUBLICATION testpub_forall_tbls_seqs;
>
> Add a comment to say this is creating an "empty" publication in
> preparation for subsequent tests

Modified

> 5.
> +-- Remove all the EXCEPT tables.
> +ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES;
> +\dRp+ testpub_foralltables_excepttable
> +
> +-- Replace the publication EXCEPT table list with a specific EXCEPT table.
> +ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES
> EXCEPT TABLE (testpub_tbl1);
> +\dRp+ testpub_foralltables_excepttable
>
> 5a.
> Are these test OK?
> * The 1st test says "Remove EXCEPT" but was there any EXCEPT list to start with?
> * The 2nd test say "Replace EXCEPT" but there was nothing replace
> because previous test removed it.
> * e.g. there seems not test that replaces one EXCEPT with a different EXCEPT

There is an except table testpub_tbl1 already present

> 5b.
> Shouldn't all these tests also all be under the "-- SET ALL
> TABLES/SEQUENCES" test comment?

Modified

> 6.
> +-- fail - SET ALL TABLES on a publication requires superuser privileges
> +ALTER PUBLICATION testpub5 SET ALL TABLES EXCEPT TABLE (testpub_tbl1); -- fail
> +ALTER PUBLICATION testpub5 SET ALL TABLES; -- fail
>
> Shouldn't all these tests also all be under the "-- SET ALL
> TABLES/SEQUENCES" test comment?

I felt this comes under permission category, exisiting is ok.

> ======
> src/test/subscription/t/037_except.pl
>
> 7.
> +# Verify that table synchronization occurs once tab1 is removed from the
> +# EXCEPT TABLE clause via SET ALL TABLES EXCEPT TABLE.
> +$result =
> + $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM tab1");
> +is($result, qq(20),
> + 'check that the data is copied as the tab1 is removed from EXCEPT
> TABLE clause'
> +);
>
> The comment is strangely worded. Talking about removing from EXCEPT
> lists is confusing. How about?
>
> -- Verify that table synchronization now happens for tab1.
> -- tab1 is included now since the EXCEPT TABLE list is only (tab2).

Modified

These comments have been fixed in the v66 version at [1].
[1] - https://www.postgresql.org/message-id/CALDaNm1tKuU479T%3DwinBqoMb3MzO3Mta2juk8W3t2R5ps0_zyg%40mail.gmail.com

Regards,
Vignesh


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-20 02:21:34
Message-ID: CALDaNm3jpYs7ALcU6m5=Li=udidjZoW5dMpyCFs8QHGaf0S8+A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 18 Mar 2026 at 18:51, vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> On Wed, 18 Mar 2026 at 12:11, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >
> > Hi Vignesh.
> >
> > Some review comments for patch v65-0001.
> >
> > ======
> > doc/src/sgml/ref/alter_publication.sgml
> >
> > 1.
> > It seems that SET ALL TABLES is not supported if the publication
> > already has FOR TABLE.
> >
> > e.g
> > alter publication pub1 set all tables;
> > ERROR: publication "pub1" does not support ALL TABLES operations
> > DETAIL: This operation requires the publication to be defined as FOR
> > ALL TABLES/SEQUENCES or to be empty.
> >
> > e.g.
> > alter publication pub2 set table t1;
> > ERROR: publication "pub2" is defined as FOR ALL TABLES
> > DETAIL: Tables or sequences cannot be added to or dropped from FOR
> > ALL TABLES publications.
> >
> > I am not going to debate what rules are right or wrong. (Some rules do
> > seem a bit ad-hoc to me, but maybe they are just erring on the safety
> > side). But my point is that the documentation does not seem to say
> > anything much about what the rules are
> >
> > e.g. it says "Adding/Setting any schema when the publication also
> > publishes a table with a column list, and vice versa is not
> > supported.", but OTOH it says nothing about what is
> > supported/unsupported for SET ALL TABLES.
>
> Amit has already replied to this at [1].
>
> > ======
> > src/backend/catalog/pg_publication.c
> >
> > 2.
> > +/*
> > + * Returns true if the publication has explicitly included relation (i.e.,
> > + * not marked as EXCEPT).
> > + */
> > +bool
> > +is_table_publication(Oid pubid)
> >
> > To me, an "explicitly included relation" is like when you say "FOR
> > TABLE t1", where the "t1" is explicitly named.
> >
> > So it's not very clear whether you consider "FOR ALL TABLES" or a
> > "FOR TABLES IN SCHEMA" publication explicitly includes tables or not?
> >
> > The function comment needs to be clearer.
>
> Amit has already replied to this at [1].
>
> > ~~~
> >
> > publication_add_relation:
> >
> > 3.
> > + /*
> > + * Determine whether EXCEPT tables require explicit relcache invalidation.
> > + *
> > + * For CREATE PUBLICATION with EXCEPT tables, invalidation is not needed,
> > + * since it is handled when marking the publication as ALL TABLES.
> > + *
> > + * For ALTER PUBLICATION, invalidation is needed only when adding an EXCEPT
> > + * table to a publication already marked as ALL TABLES. For publications
> > + * that were originally empty or defined as ALL SEQUENCES and are being
> > + * converted to ALL TABLES, invalidation is skipped here, as it is handled
> > + * when marking the publication as ALL TABLES.
> > + */
> > + inval_except_table = (stmt != NULL) &&
> > + (stmt->for_all_tables == pub->alltables);
> >
> > 3a.
> > Why is this code done at the top of the function? Can you move it to
> > be adjacent to where it is getting used?
>
> Modified
>
> > ~
> >
> > 3b.
> > I think 'alter_stmt' or 'alter_pub_stmt' might be a more informative
> > name here, instead of the generic 'stmt'
>
> Modified
>
> > ======
> > src/backend/commands/publicationcmds.c
> >
> > 4.
> > - TransformPubWhereClauses(rels, queryString, pubform->pubviaroot);
> > + if (isexcept)
> > + oldrelids = GetExcludedPublicationTables(pubid,
> > + PUBLICATION_PART_ROOT);
> > + else
> > + {
> > + oldrelids = GetIncludedPublicationRelations(pubid,
> > + PUBLICATION_PART_ROOT);
> >
> > I felt there were some subtle things that the logic is using here:
> >
> > e.g.
> > It seems that because this function is called...
> > And because it is SET ....
> > And because it is SET ALL TABLES ...
> > Then, the tables can only be those in the EXCEPT TABLE list
> >
> > Maybe more comments about 'isexcept', and maybe an Assert(oldrelids !=
> > NIL); could help here (??)
>
> Updated comments
>
> > ~~~
> >
> > AlterPublicationAllFlags:
> >
> > 5.
> > + bool nulls[Natts_pg_publication];
> > + bool replaces[Natts_pg_publication];
> > + Datum values[Natts_pg_publication];
> > + bool dirty = false;
> > +
> > + if (!stmt->for_all_tables && !stmt->for_all_sequences)
> > + return;
> > +
> > + pubform = (Form_pg_publication) GETSTRUCT(tup);
> > +
> > + memset(values, 0, sizeof(values));
> > + memset(nulls, false, sizeof(nulls));
> > + memset(replaces, false, sizeof(replaces));
> >
> > AFAIK, these memsets are not needed if you just say "= {0}" where
> > those vars are declared.
>
> modified
>
> > AlterPublication:
> >
> > 6.
> > + relations = list_concat(relations, exceptrelations);
> > AlterPublicationTables(stmt, tup, relations, pstate->p_sourcetext,
> > schemaidlist != NIL);
> >
> > I did not quite understand this list_concat.
> >
> > Is this somehow asserting that `relations` must be empty when there
> > were `exceptrelations` and vice versa, because other combinations are
> > not supported by ALTER -- e.g. is this just a trick to so you can pass
> > the same parameter to AlterPublicationTables? This seems related to
> > the 'isexecpt' AlterPublicationTables function, which was also quite
> > subtle.
> >
> > Bottom line is, I'm unsure what the logic is here, but it appears
> > overly tricky to me. Would more comments help?
>
> Amit has already replied to this at [1].
>
> > ======
> > src/backend/parser/gram.y
> >
> > 7.
> > + * ALL TABLES [ EXCEPT TABLE ( table_name [, ...] ) ]
> >
> > The CREATE/ALTER docs synopsis says "[ ONLY ] table_name [ * ]" which
> > is different from this comment. So are ONLY and * handled properly or
> > not?
>
> It is handled, Is there any issue with the code? It is documented that
> way to keep it consistent with CreatePublicationStmt and ALTER
> PUBLICATION ADD/DROP/SET pub_obj.
>
> > ======
> > src/include/nodes/parsenodes.h
> >
> > 8.
> > + bool for_all_tables; /* True if SET ALL TABLES is specified */
> > + bool for_all_sequences; /* True if SET ALL SEQUENCES is specified */
> >
> > Maybe these comments do not need to mention the keyword "SET".
> >
> > That way, in future if/when ADD/DROP get implemented, then this code
> > won't need to churn again.
>
> Modified
>
> The attached v66 version patch has the changes for the same.

While reviewing the patch I noticed couple of small improvements that
could be done:
1) changed "may be used " to "can be used" as that is the convention followed:
In addition,
+ <literal>SET ALL TABLES</literal> may be used to update the
+ <literal>EXCEPT TABLE</literal> list of a <literal>FOR ALL TABLES</literal>
+ publication.

2) This condition was slightly difficult to understand while reading,
simplified it:
Changed:
- if (!pri->except)
+ inval_except_table = (alter_stmt != NULL) &&
+ (alter_stmt->for_all_tables == pub->alltables);
to:
- if (!pri->except)
+ inval_except_table = (alter_stmt != NULL) && pub->alltables &&
+ (alter_stmt->for_all_tables && pri->except);

The attached v67 patch has the changes for the same.

Regards,
Vignesh

Attachment Content-Type Size
v67-0001-Add-support-for-EXCEPT-TABLE-in-ALTER-PUBLICATIO.patch application/octet-stream 38.0 KB

From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-20 05:55:56
Message-ID: CAJpy0uCWS=ybBKG-kRAfdWEe1VBNj+VqpAUUoT8MPaNS7EggiA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Mar 20, 2026 at 7:51 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
>
> The attached v67 patch has the changes for the same.
>

It looks good to me.

thanks
Shveta


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-20 11:56:02
Message-ID: CAA4eK1LMM-P4NatbkjG-96B7hHC7KYrJ8XTsCZQy0jLO9Qj4Bw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Mar 20, 2026 at 11:26 AM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> On Fri, Mar 20, 2026 at 7:51 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> >
> > The attached v67 patch has the changes for the same.
> >
>
> It looks good to me.
>

Pushed.

--
With Regards,
Amit Kapila.


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-23 07:05:02
Message-ID: CAJpy0uAyf71QSYitBf4WbCYq22HDR6LPdxB12TpTgTRpczwphw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

I would like to summarize the discussion/feedback for the EXCEPT
syntax implemented in [1].

1)
The currently implemented syntax is ([1]):

CREATE PUBLICATION pub FOR ALL TABLES EXCEPT TABLE (a, b, c);

There were concerns about why the TABLE keyword and the parentheses
'()' are required. These have been answered in [2].

Please review the discussion there.

2)
Another feedback on current syntax was to move the TABLE keyword
inside the parentheses:

CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, TABLE t2,
TABLES IN SCHEMA s1);
CREATE PUBLICATION pub FOR TABLES IN SCHEMA s1 EXCEPT (TABLE t1, TABLE
t2), TABLE t3;

While this approach is workable, a downside is the repeated use of the
TABLE keyword inside the parentheses, which can become verbose. But it
can then be optimized to have:

CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, t2, t3);

This could be extended further in the future:

CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, t2, TABLES IN
SCHEMA s1, s2);

This approach gives users flexibility to mix styles, for example:

EXCEPT (TABLE t1, TABLE t2, TABLE t3)
EXCEPT (TABLE t1, t2, t3)
EXCEPT (TABLE t1, t2, TABLE t3)
EXCEPT (TABLE t1, TABLES IN SCHEMA s1, s2, TABLE t2, t3)

While flexible, this can reduce clarity due to mixed styles, making
the statement harder to read. If extended further, the syntax could
evolve into something like:

CREATE PUBLICATION pub1 FOR
ALL TABLES
EXCEPT (TABLE t1, t2, TABLES IN SCHEMA s1, s2),
ALL SEQUENCES
EXCEPT (SEQUENCE s1);

At this point, one might also question why not allow something like:
FOR ALL (TABLES, SEQUENCES).

Additionally, this shows a potential drift toward less structured
syntax. Instead, with the syntax already implemented in [1], its
future extension would look like:

CREATE PUBLICATION pub1 FOR
ALL TABLES
EXCEPT TABLE (t1, t2),
EXCEPT TABLES IN SCHEMA (s1, s2),
ALL SEQUENCES
EXCEPT SEQUENCE (seq1, seq2);

Although slightly more verbose, this approach keeps each clause
self-contained and explicit. The meaning of each part is determined
locally, rather than depending on elements appearing far in the
statement.

The current syntax in [1] is simple and easy to follow. We have
retained the current implementation for now, while remaining open to
further discussion and suggestions.

[1]:
https://www.postgresql.org/message-id/CALDaNm2-Ob9qPR%2BvqUSVMkxYO8RW4LQ_S1XiB0Y7xa54U%3DDqbA%40mail.gmail.com
https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=fd366065e06ae953c4f2d973d5c5f0474f3b87b6

[2]: https://www.postgresql.org/message-id/CAJpy0uB20MhJJEaPJdm31t4fykJ%2BfChA_76jU2P9HX5knbJvAA%40mail.gmail.com

thanks
Shveta


From: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-24 14:20:18
Message-ID: CAFiTN-s5PW121mBGKin20YEQpZkWefMehmP=v+0onzEaMQpwdw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Mar 23, 2026 at 12:35 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> I would like to summarize the discussion/feedback for the EXCEPT
> syntax implemented in [1].
>
> 1)
> The currently implemented syntax is ([1]):
>
> CREATE PUBLICATION pub FOR ALL TABLES EXCEPT TABLE (a, b, c);
>
> There were concerns about why the TABLE keyword and the parentheses
> '()' are required. These have been answered in [2].
>
> Please review the discussion there.
>
> 2)
> Another feedback on current syntax was to move the TABLE keyword
> inside the parentheses:
>
> CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, TABLE t2,
> TABLES IN SCHEMA s1);
> CREATE PUBLICATION pub FOR TABLES IN SCHEMA s1 EXCEPT (TABLE t1, TABLE
> t2), TABLE t3;
>
> While this approach is workable, a downside is the repeated use of the
> TABLE keyword inside the parentheses, which can become verbose. But it
> can then be optimized to have:
>
> CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, t2, t3);
>
> This could be extended further in the future:
>
> CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, t2, TABLES IN
> SCHEMA s1, s2);
>
> This approach gives users flexibility to mix styles, for example:
>
> EXCEPT (TABLE t1, TABLE t2, TABLE t3)
> EXCEPT (TABLE t1, t2, t3)
> EXCEPT (TABLE t1, t2, TABLE t3)
> EXCEPT (TABLE t1, TABLES IN SCHEMA s1, s2, TABLE t2, t3)
>
> While flexible, this can reduce clarity due to mixed styles, making
> the statement harder to read. If extended further, the syntax could
> evolve into something like:
>
> CREATE PUBLICATION pub1 FOR
> ALL TABLES
> EXCEPT (TABLE t1, t2, TABLES IN SCHEMA s1, s2),
> ALL SEQUENCES
> EXCEPT (SEQUENCE s1);
>
> At this point, one might also question why not allow something like:
> FOR ALL (TABLES, SEQUENCES).
>
> Additionally, this shows a potential drift toward less structured
> syntax. Instead, with the syntax already implemented in [1], its
> future extension would look like:
>
> CREATE PUBLICATION pub1 FOR
> ALL TABLES
> EXCEPT TABLE (t1, t2),
> EXCEPT TABLES IN SCHEMA (s1, s2),
> ALL SEQUENCES
> EXCEPT SEQUENCE (seq1, seq2);
>
> Although slightly more verbose, this approach keeps each clause
> self-contained and explicit. The meaning of each part is determined
> locally, rather than depending on elements appearing far in the
> statement.
>
> The current syntax in [1] is simple and easy to follow. We have
> retained the current implementation for now, while remaining open to
> further discussion and suggestions.
>
> [1]:
> https://www.postgresql.org/message-id/CALDaNm2-Ob9qPR%2BvqUSVMkxYO8RW4LQ_S1XiB0Y7xa54U%3DDqbA%40mail.gmail.com
> https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=fd366065e06ae953c4f2d973d5c5f0474f3b87b6
>
> [2]: https://www.postgresql.org/message-id/CAJpy0uB20MhJJEaPJdm31t4fykJ%2BfChA_76jU2P9HX5knbJvAA%40mail.gmail.com

Thanks for the summary. While I find the current implementation
simpler and more intuitive, and would prefer it if we were designing
this from scratch, we must consider the existing patterns for table
inclusion. Since the inclusion syntax already supports a mixed
approach, users will likely expect the same flexibility for
exclusions. For the sake of consistency across the features, I believe
we should move toward the mixed approach, despite my preference for
the current structured style. Of course, this is just my opinion, and
others' mileage may vary.

--
Regards,
Dilip Kumar
Google


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-26 06:10:58
Message-ID: CAA4eK1LBf5asit18HcqcFinOkdCjD6Lk2Eid9PDhtH6acwYb8w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 24, 2026 at 7:50 PM Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:
>
> On Mon, Mar 23, 2026 at 12:35 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> >
> > I would like to summarize the discussion/feedback for the EXCEPT
> > syntax implemented in [1].
> >
> > 1)
> > The currently implemented syntax is ([1]):
> >
> > CREATE PUBLICATION pub FOR ALL TABLES EXCEPT TABLE (a, b, c);
> >
> > There were concerns about why the TABLE keyword and the parentheses
> > '()' are required. These have been answered in [2].
> >
> > Please review the discussion there.
> >
> > 2)
> > Another feedback on current syntax was to move the TABLE keyword
> > inside the parentheses:
> >
> > CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, TABLE t2,
> > TABLES IN SCHEMA s1);
> > CREATE PUBLICATION pub FOR TABLES IN SCHEMA s1 EXCEPT (TABLE t1, TABLE
> > t2), TABLE t3;
> >
> > While this approach is workable, a downside is the repeated use of the
> > TABLE keyword inside the parentheses, which can become verbose. But it
> > can then be optimized to have:
> >
> > CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, t2, t3);
> >
> > This could be extended further in the future:
> >
> > CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, t2, TABLES IN
> > SCHEMA s1, s2);
> >
> > This approach gives users flexibility to mix styles, for example:
> >
> > EXCEPT (TABLE t1, TABLE t2, TABLE t3)
> > EXCEPT (TABLE t1, t2, t3)
> > EXCEPT (TABLE t1, t2, TABLE t3)
> > EXCEPT (TABLE t1, TABLES IN SCHEMA s1, s2, TABLE t2, t3)
> >
> > While flexible, this can reduce clarity due to mixed styles, making
> > the statement harder to read. If extended further, the syntax could
> > evolve into something like:
> >
> > CREATE PUBLICATION pub1 FOR
> > ALL TABLES
> > EXCEPT (TABLE t1, t2, TABLES IN SCHEMA s1, s2),
> > ALL SEQUENCES
> > EXCEPT (SEQUENCE s1);
> >
> > At this point, one might also question why not allow something like:
> > FOR ALL (TABLES, SEQUENCES).
> >
> > Additionally, this shows a potential drift toward less structured
> > syntax. Instead, with the syntax already implemented in [1], its
> > future extension would look like:
> >
> > CREATE PUBLICATION pub1 FOR
> > ALL TABLES
> > EXCEPT TABLE (t1, t2),
> > EXCEPT TABLES IN SCHEMA (s1, s2),
> > ALL SEQUENCES
> > EXCEPT SEQUENCE (seq1, seq2);
> >
> > Although slightly more verbose, this approach keeps each clause
> > self-contained and explicit. The meaning of each part is determined
> > locally, rather than depending on elements appearing far in the
> > statement.
> >
> > The current syntax in [1] is simple and easy to follow. We have
> > retained the current implementation for now, while remaining open to
> > further discussion and suggestions.
> >
> > [1]:
> > https://www.postgresql.org/message-id/CALDaNm2-Ob9qPR%2BvqUSVMkxYO8RW4LQ_S1XiB0Y7xa54U%3DDqbA%40mail.gmail.com
> > https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=fd366065e06ae953c4f2d973d5c5f0474f3b87b6
> >
> > [2]: https://www.postgresql.org/message-id/CAJpy0uB20MhJJEaPJdm31t4fykJ%2BfChA_76jU2P9HX5knbJvAA%40mail.gmail.com
>
>
> Thanks for the summary. While I find the current implementation
> simpler and more intuitive, and would prefer it if we were designing
> this from scratch, we must consider the existing patterns for table
> inclusion. Since the inclusion syntax already supports a mixed
> approach, users will likely expect the same flexibility for
> exclusions. For the sake of consistency across the features, I believe
> we should move toward the mixed approach, despite my preference for
> the current structured style.
>

IIUC, you think that we should change the current syntax "CREATE
PUBLICATION pub FOR ALL TABLES EXCEPT TABLE (a, b, c);" to "CREATE
PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE a, b, c);".

By now multiple people (Dilip Kumar, Peter Smith, Sawada Masahiko)
have preferred the alternate syntax, to move TABLE inside () to make
specifying inclusion and exclusion list in a similar way. Unless we
have more feedback, I think we can change it now.

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-26 15:24:37
Message-ID: CALDaNm3cdoT58E3QtYCwBbzyxYJjoS2k7Q0EgzR9ta6fyDGHSg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, 26 Mar 2026 at 11:41, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Tue, Mar 24, 2026 at 7:50 PM Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:
> >
> > On Mon, Mar 23, 2026 at 12:35 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> > >
> > > I would like to summarize the discussion/feedback for the EXCEPT
> > > syntax implemented in [1].
> > >
> > > 1)
> > > The currently implemented syntax is ([1]):
> > >
> > > CREATE PUBLICATION pub FOR ALL TABLES EXCEPT TABLE (a, b, c);
> > >
> > > There were concerns about why the TABLE keyword and the parentheses
> > > '()' are required. These have been answered in [2].
> > >
> > > Please review the discussion there.
> > >
> > > 2)
> > > Another feedback on current syntax was to move the TABLE keyword
> > > inside the parentheses:
> > >
> > > CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, TABLE t2,
> > > TABLES IN SCHEMA s1);
> > > CREATE PUBLICATION pub FOR TABLES IN SCHEMA s1 EXCEPT (TABLE t1, TABLE
> > > t2), TABLE t3;
> > >
> > > While this approach is workable, a downside is the repeated use of the
> > > TABLE keyword inside the parentheses, which can become verbose. But it
> > > can then be optimized to have:
> > >
> > > CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, t2, t3);
> > >
> > > This could be extended further in the future:
> > >
> > > CREATE PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE t1, t2, TABLES IN
> > > SCHEMA s1, s2);
> > >
> > > This approach gives users flexibility to mix styles, for example:
> > >
> > > EXCEPT (TABLE t1, TABLE t2, TABLE t3)
> > > EXCEPT (TABLE t1, t2, t3)
> > > EXCEPT (TABLE t1, t2, TABLE t3)
> > > EXCEPT (TABLE t1, TABLES IN SCHEMA s1, s2, TABLE t2, t3)
> > >
> > > While flexible, this can reduce clarity due to mixed styles, making
> > > the statement harder to read. If extended further, the syntax could
> > > evolve into something like:
> > >
> > > CREATE PUBLICATION pub1 FOR
> > > ALL TABLES
> > > EXCEPT (TABLE t1, t2, TABLES IN SCHEMA s1, s2),
> > > ALL SEQUENCES
> > > EXCEPT (SEQUENCE s1);
> > >
> > > At this point, one might also question why not allow something like:
> > > FOR ALL (TABLES, SEQUENCES).
> > >
> > > Additionally, this shows a potential drift toward less structured
> > > syntax. Instead, with the syntax already implemented in [1], its
> > > future extension would look like:
> > >
> > > CREATE PUBLICATION pub1 FOR
> > > ALL TABLES
> > > EXCEPT TABLE (t1, t2),
> > > EXCEPT TABLES IN SCHEMA (s1, s2),
> > > ALL SEQUENCES
> > > EXCEPT SEQUENCE (seq1, seq2);
> > >
> > > Although slightly more verbose, this approach keeps each clause
> > > self-contained and explicit. The meaning of each part is determined
> > > locally, rather than depending on elements appearing far in the
> > > statement.
> > >
> > > The current syntax in [1] is simple and easy to follow. We have
> > > retained the current implementation for now, while remaining open to
> > > further discussion and suggestions.
> > >
> > > [1]:
> > > https://www.postgresql.org/message-id/CALDaNm2-Ob9qPR%2BvqUSVMkxYO8RW4LQ_S1XiB0Y7xa54U%3DDqbA%40mail.gmail.com
> > > https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=fd366065e06ae953c4f2d973d5c5f0474f3b87b6
> > >
> > > [2]: https://www.postgresql.org/message-id/CAJpy0uB20MhJJEaPJdm31t4fykJ%2BfChA_76jU2P9HX5knbJvAA%40mail.gmail.com
> >
> >
> > Thanks for the summary. While I find the current implementation
> > simpler and more intuitive, and would prefer it if we were designing
> > this from scratch, we must consider the existing patterns for table
> > inclusion. Since the inclusion syntax already supports a mixed
> > approach, users will likely expect the same flexibility for
> > exclusions. For the sake of consistency across the features, I believe
> > we should move toward the mixed approach, despite my preference for
> > the current structured style.
> >
>
> IIUC, you think that we should change the current syntax "CREATE
> PUBLICATION pub FOR ALL TABLES EXCEPT TABLE (a, b, c);" to "CREATE
> PUBLICATION pub FOR ALL TABLES EXCEPT (TABLE a, b, c);".
>
> By now multiple people (Dilip Kumar, Peter Smith, Sawada Masahiko)
> have preferred the alternate syntax, to move TABLE inside () to make
> specifying inclusion and exclusion list in a similar way. Unless we
> have more feedback, I think we can change it now.

Attached patch has the changes for the same.

Regards,
Vignesh

Attachment Content-Type Size
0001-Change-syntax-of-EXCEPT-TABLE-clause-in-publication-.patch application/octet-stream 24.3 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-27 01:36:14
Message-ID: CAHut+PthJx_gZJNgF=mWSpkWjQJ58KyhrZ7D7CkX_TVq12wv7A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Mar 27, 2026 at 2:24 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
...
> > By now multiple people (Dilip Kumar, Peter Smith, Sawada Masahiko)
> > have preferred the alternate syntax, to move TABLE inside () to make
> > specifying inclusion and exclusion list in a similar way. Unless we
> > have more feedback, I think we can change it now.
>
> Attached patch has the changes for the same.
>

Hi Vignesh.

Here are some review comments for the new syntax patch 0001.

======
doc/src/sgml/ref/create_publication.sgml

1.
- ALL TABLES [ EXCEPT TABLE ( <replaceable
class="parameter">except_table_object</replaceable> [, ... ] ) ]
+ ALL TABLES [ EXCEPT ( TABLE <replaceable
class="parameter">except_table_object</replaceable> [, ... ] ) ]

I don't think this is correct. To have the same flexibility as the
TABLE inclusion lists, the TABLE keyword needs to be inside the
<except_table_object>, and there need to be more ellipses there too.

e.g. Like this:

and publication_all_object is one of:
ALL TABLES [ EXCEPT ( except_table_object [, ... ] ) ]
ALL SEQUENCES

and except_table_object is:
TABLE { [ ONLY ] table_name [ * ] } [, ...]

~~~

2.
The CREATE PUBLICATION page still refers to "EXCEPT TABLE" in multiple places.

Perhaps now it should be called "EXCEPT (TABLE) clause" or just
"EXCEPT clause" or something else.

======
doc/src/sgml/ref/alter_publication.sgml

3.
- ALL TABLES [ EXCEPT TABLE ( <replaceable
class="parameter">except_table_object</replaceable> [, ... ] ) ]
+ ALL TABLES [ EXCEPT ( TABLE <replaceable
class="parameter">except_table_object</replaceable> [, ... ] ) ]

This ALTER PUBLICATION synopsis should have the same/similar changes
as in the above review comment above for the CREATE PUBLICATION
synopsis.

e.g.

and publication_all_object is one of:
ALL TABLES [ EXCEPT ( except_table_object [, ... ] ) ]
ALL SEQUENCES

and except_table_object is:
TABLE { [ ONLY ] table_name [ * ] } [, ...]

~~~

4.
Also, similar to the earlier review comment, this ALTER PUBLICATION
page still refers to "EXCEPT TABLE" in multiple places.

Perhaps now it should be called "EXCEPT (TABLE) clause" or just "EXCEPT clause".

======
src/backend/parser/gram.y

5.
- EXCEPT TABLE '(' pub_except_obj_list ')' { $$ = $4; }
+ EXCEPT '(' TABLE pub_except_obj_list ')' { $$ = $4; }

Same review comment as my above synopsis comments.

This patch implementation only supports EXCEPT (TABLE t1,t2,t3);

Specifically, it doesn't have the same flexibility you get from a
table inclusion list.

e.g. IMO cmd should also work for:
EXCEPT (TABLE t1, TABLE t2,t3);
etc.

======
src/bin/pg_dump/pg_dump.c

6.
Code comment still refers to "EXCEPT TABLE clause", but it doesn't
look like that anymore.

======
src/test/regress/sql/publication.sql

7.
Comments still refer to "EXCEPT TABLE" and "EXCEPT TABLE clause", but
it doesn't look like that anymore.

~~~

8.
There needs to be additional tests to confirm that the syntax has the
same flexibility as TABLE inclusion lists do

e.g. all these variations below are valid and equivalent:
... EXCEPT (TABLE t1, t2, t3, t4);
... EXCEPT (TABLE t1, t2, TABLE t3, t4);
... EXCEPT (TABLE t1, t2, TABLE t3, t4);
... EXCEPT (TABLE t1, TABLE t2, TABLE t3, TABLE t4);

======
src/test/subscription/t/037_except.pl

9.
Comments still refer to "EXCEPT TABLE", but it doesn't look like that anymore.

======
(more files)

10.
There are still more source files (not currently part of this patch)
that are still calling this the "EXCEPT TABLE" clause, even though the
syntax is different now.

e.g. "src/backend/commands/publicationcmds.c" and others.

Need to search the master source to find every affected comment.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-27 03:49:38
Message-ID: CAA4eK1Jjm+w3hEGgsDu_r1Pysez=8mmtGu6=XwPE4MuH+eYG8Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Mar 27, 2026 at 7:06 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> 8.
> There needs to be additional tests to confirm that the syntax has the
> same flexibility as TABLE inclusion lists do
>
> e.g. all these variations below are valid and equivalent:
> ... EXCEPT (TABLE t1, t2, t3, t4);
> ... EXCEPT (TABLE t1, t2, TABLE t3, t4);
> ... EXCEPT (TABLE t1, t2, TABLE t3, t4);
> ... EXCEPT (TABLE t1, TABLE t2, TABLE t3, TABLE t4);
>

From all of the above, test with any one variant is okay. Let's not
add tests unless they test some different variant of syntax.

--
With Regards,
Amit Kapila.


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-27 05:49:36
Message-ID: CAJpy0uApqCwNJig2Lbe8sFN-6behDBZ0OF2iXh-SQbsksLFDEQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Thu, Mar 26, 2026 at 8:54 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
>
> Attached patch has the changes for the same.
>

I reviewed the EXCEPT patch and don’t have additional comments beyond
what Peter has already mentioned. The feedback mainly falls into two
categories:

1) Update the doc and comments to reference the correct clause instead
of “EXCEPT TABLE.”
2) Add more flexibility in the syntax to allow optional TABLE keywords
with each table name, enabling mixed styles in the future.

thanks
Shveta


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-27 07:50:14
Message-ID: CANhcyEVLp5kbaVR4=nh1jR4YWqv7YpVx_SnYoshbnOrnY79_fg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 27 Mar 2026 at 07:06, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> On Fri, Mar 27, 2026 at 2:24 AM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> ...
> > > By now multiple people (Dilip Kumar, Peter Smith, Sawada Masahiko)
> > > have preferred the alternate syntax, to move TABLE inside () to make
> > > specifying inclusion and exclusion list in a similar way. Unless we
> > > have more feedback, I think we can change it now.
> >
> > Attached patch has the changes for the same.
> >
>
> Hi Vignesh.
>
> Here are some review comments for the new syntax patch 0001.
>
> ======
> doc/src/sgml/ref/create_publication.sgml
>
> 1.
> - ALL TABLES [ EXCEPT TABLE ( <replaceable
> class="parameter">except_table_object</replaceable> [, ... ] ) ]
> + ALL TABLES [ EXCEPT ( TABLE <replaceable
> class="parameter">except_table_object</replaceable> [, ... ] ) ]
>
> I don't think this is correct. To have the same flexibility as the
> TABLE inclusion lists, the TABLE keyword needs to be inside the
> <except_table_object>, and there need to be more ellipses there too.
>
> e.g. Like this:
>
> and publication_all_object is one of:
> ALL TABLES [ EXCEPT ( except_table_object [, ... ] ) ]
> ALL SEQUENCES
>
> and except_table_object is:
> TABLE { [ ONLY ] table_name [ * ] } [, ...]
>
> ~~~
>
> 2.
> The CREATE PUBLICATION page still refers to "EXCEPT TABLE" in multiple places.
>
> Perhaps now it should be called "EXCEPT (TABLE) clause" or just
> "EXCEPT clause" or something else.
>
> ======
> doc/src/sgml/ref/alter_publication.sgml
>
> 3.
> - ALL TABLES [ EXCEPT TABLE ( <replaceable
> class="parameter">except_table_object</replaceable> [, ... ] ) ]
> + ALL TABLES [ EXCEPT ( TABLE <replaceable
> class="parameter">except_table_object</replaceable> [, ... ] ) ]
>
> This ALTER PUBLICATION synopsis should have the same/similar changes
> as in the above review comment above for the CREATE PUBLICATION
> synopsis.
>
> e.g.
>
> and publication_all_object is one of:
> ALL TABLES [ EXCEPT ( except_table_object [, ... ] ) ]
> ALL SEQUENCES
>
> and except_table_object is:
> TABLE { [ ONLY ] table_name [ * ] } [, ...]
>
> ~~~
>
> 4.
> Also, similar to the earlier review comment, this ALTER PUBLICATION
> page still refers to "EXCEPT TABLE" in multiple places.
>
> Perhaps now it should be called "EXCEPT (TABLE) clause" or just "EXCEPT clause".
>
> ======
> src/backend/parser/gram.y
>
> 5.
> - EXCEPT TABLE '(' pub_except_obj_list ')' { $$ = $4; }
> + EXCEPT '(' TABLE pub_except_obj_list ')' { $$ = $4; }
>
> Same review comment as my above synopsis comments.
>
> This patch implementation only supports EXCEPT (TABLE t1,t2,t3);
>
> Specifically, it doesn't have the same flexibility you get from a
> table inclusion list.
>
> e.g. IMO cmd should also work for:
> EXCEPT (TABLE t1, TABLE t2,t3);
> etc.
>
> ======
> src/bin/pg_dump/pg_dump.c
>
> 6.
> Code comment still refers to "EXCEPT TABLE clause", but it doesn't
> look like that anymore.
>
> ======
> src/test/regress/sql/publication.sql
>
> 7.
> Comments still refer to "EXCEPT TABLE" and "EXCEPT TABLE clause", but
> it doesn't look like that anymore.
>
> ~~~
>
> 8.
> There needs to be additional tests to confirm that the syntax has the
> same flexibility as TABLE inclusion lists do
>
> e.g. all these variations below are valid and equivalent:
> ... EXCEPT (TABLE t1, t2, t3, t4);
> ... EXCEPT (TABLE t1, t2, TABLE t3, t4);
> ... EXCEPT (TABLE t1, t2, TABLE t3, t4);
> ... EXCEPT (TABLE t1, TABLE t2, TABLE t3, TABLE t4);
>
I have not tested all the scenarios as per Amit's suggestion in [1]. I
have just modified an existing test.

> ======
> src/test/subscription/t/037_except.pl
>
> 9.
> Comments still refer to "EXCEPT TABLE", but it doesn't look like that anymore.
>
> ======
> (more files)
>
> 10.
> There are still more source files (not currently part of this patch)
> that are still calling this the "EXCEPT TABLE" clause, even though the
> syntax is different now.
>
> e.g. "src/backend/commands/publicationcmds.c" and others.
>
> Need to search the master source to find every affected comment.
>
Hi Peter,

I have addressed the comments. Attached the updated patch.

[1]: https://www.postgresql.org/message-id/CAA4eK1Jjm+w3hEGgsDu_r1Pysez=8mmtGu6=XwPE4MuH+eYG8Q@mail.gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v2-0001-Change-syntax-of-EXCEPT-TABLE-clause-in-publicati.patch application/octet-stream 46.6 KB

From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-27 09:23:39
Message-ID: CAJpy0uCMhxUdEZMqDuSHXeAMES1gH56r-tkhR1J79A_f3wrLkg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Mar 27, 2026 at 1:20 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
>
> I have addressed the comments. Attached the updated patch.
>
> [1]: https://www.postgresql.org/message-id/CAA4eK1Jjm+w3hEGgsDu_r1Pysez=8mmtGu6=XwPE4MuH+eYG8Q@mail.gmail.com
>

The patch looks fine to me, just one trivial thing:

/*
* Similar with preprocess_pubobj_list(), but used for the EXCEPT clause.
*/

with -->to

thanks
Shveta


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-27 12:33:53
Message-ID: CAA4eK1+4ZNF-MGheeTtYF9TdfNBnKKJ8DivWZsXBnuJVkqfa0g@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Mar 27, 2026 at 1:20 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> I have addressed the comments. Attached the updated patch.
>

I got following crash:

postgres=# create publication pub1 for all tables except (t1, t2);
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.

Server Log:
ERROR: syntax error at or near "table" at character 47
[client backend] STATEMENT: create publication pub1 for all tables
except table (t1, t2);
TRAP: failed Assert("pubobj->pubobjtype ==
PUBLICATIONOBJ_EXCEPT_TABLE"), File: "../src/backend/parser/gram.y",
Line: 20795, PID: 7512
abort() has been called[postmaster] LOG: client backend (PID 7512)
was terminated by exception 0xC0000409
[postmaster] DETAIL: Failed process was running: create publication
pub1 for all tables except (t1, t2);
[postmaster] HINT: See C include file "ntstatus.h" for a description
of the hexadecimal value.

BTW, why do we need preprocess_except_pubobj_list?

--
With Regards,
Amit Kapila.


From: SATYANARAYANA NARLAPURAM <satyanarlapuram(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-27 19:03:46
Message-ID: CAHg+QDe+7J0e1JLjpqe-NxVJMWXH6UDtqugrm+DP7rHEJLrBqQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi,

On Fri, Mar 27, 2026 at 12:50 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
wrote:

>
> I have addressed the comments. Attached the updated patch.
>
> [1]:
> https://www.postgresql.org/message-id/CAA4eK1Jjm+w3hEGgsDu_r1Pysez=8mmtGu6=XwPE4MuH+eYG8Q@mail.gmail.com

A few minor comments:

1. Add a negative test for missing table keyword for example EXCEPT (t1, t2)
2. NIT comment, remove the extra space between parenthesis and TABLE below

else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL",
"TABLES"))
- COMPLETE_WITH("EXCEPT TABLE (", "WITH (");
+ COMPLETE_WITH("EXCEPT ( TABLE", "WITH (");

3. for pg_dump, to improve readability can you just add TABLE keyword for
every tables in the except list?

- /* Include EXCEPT TABLE clause if there are except_tables. */
+ /* Include EXCEPT (TABLE) clause if there are except_tables. */
for (SimplePtrListCell *cell = pubinfo->except_tables.head; cell; cell =
cell->next)
{
TableInfo *tbinfo = (TableInfo *) cell->ptr;

if (++n_except == 1)
- appendPQExpBufferStr(query, " EXCEPT TABLE (");
+ appendPQExpBufferStr(query, " EXCEPT (TABLE ");
else
appendPQExpBufferStr(query, ", ");

4. Is the Assert needed below, code already produces error message.

+ Assert(pubobj->pubobjtype == PUBLICATIONOBJ_EXCEPT_TABLE);
+
+ if (pubobj->pubobjtype == PUBLICATIONOBJ_CONTINUATION)
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid publication object list"),
+ errdetail("TABLE must be specified before a standalone table."),
+ parser_errposition(pubobj->location));

Thanks,
Satya


From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-27 20:49:34
Message-ID: CANhcyEUQvEK+HOH6Y8Fy30fNvC631ZopWKhwgskXjKnuXiGV5Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, 27 Mar 2026 at 18:04, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Fri, Mar 27, 2026 at 1:20 PM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > I have addressed the comments. Attached the updated patch.
> >
>
> I got following crash:
>
> postgres=# create publication pub1 for all tables except (t1, t2);
> server closed the connection unexpectedly
> This probably means the server terminated abnormally
> before or while processing the request.
> The connection to the server was lost. Attempting reset: Failed.
>
> Server Log:
> ERROR: syntax error at or near "table" at character 47
> [client backend] STATEMENT: create publication pub1 for all tables
> except table (t1, t2);
> TRAP: failed Assert("pubobj->pubobjtype ==
> PUBLICATIONOBJ_EXCEPT_TABLE"), File: "../src/backend/parser/gram.y",
> Line: 20795, PID: 7512
> abort() has been called[postmaster] LOG: client backend (PID 7512)
> was terminated by exception 0xC0000409
> [postmaster] DETAIL: Failed process was running: create publication
> pub1 for all tables except (t1, t2);
> [postmaster] HINT: See C include file "ntstatus.h" for a description
> of the hexadecimal value.
This crash is happening because we hit the Assert(pubobj->pubobjtype
== PUBLICATIONOBJ_EXCEPT_TABLE).
In the above example the first table is specified without the TABLE
keyword and hence its pubobjtype is PUBLICATIONOBJ_CONTINUATION.
I have updated the Assert and also added a test case for the above scenario.

>
> BTW, why do we need preprocess_except_pubobj_list?
>
It is needed to check if the first table in the EXCEPT list is
specified with TABLE Keyword.
For example: create publication pub1 for all tables except (t1, t2);
This should throw an error because t1 is specified without the TABLE keyword.

We have a similar logic for FOR TABLE or FOR TABLES IN SCHEMA
publications in 'preprocess_pubobj_list'

I have attached the latest version here. I have also addressed the
comment shared by Shveta in [1].
[1]: https://www.postgresql.org/message-id/CAJpy0uCMhxUdEZMqDuSHXeAMES1gH56r-tkhR1J79A_f3wrLkg@mail.gmail.com

Thanks,
Shlok Kyal

Attachment Content-Type Size
v3-0001-Change-syntax-of-EXCEPT-TABLE-clause-in-publicati.patch application/octet-stream 47.3 KB

From: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
To: SATYANARAYANA NARLAPURAM <satyanarlapuram(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-27 20:50:57
Message-ID: CANhcyEXdc6R6MrrC-Co_mmWLkync9q0GodCgegcC3VUC=k3Hbw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Sat, 28 Mar 2026 at 00:33, SATYANARAYANA NARLAPURAM
<satyanarlapuram(at)gmail(dot)com> wrote:
>
> Hi,
>
> On Fri, Mar 27, 2026 at 12:50 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>>
>>
>> I have addressed the comments. Attached the updated patch.
>>
>> [1]: https://www.postgresql.org/message-id/CAA4eK1Jjm+w3hEGgsDu_r1Pysez=8mmtGu6=XwPE4MuH+eYG8Q@mail.gmail.com
>
>
> A few minor comments:
>
> 1. Add a negative test for missing table keyword for example EXCEPT (t1, t2)
> 2. NIT comment, remove the extra space between parenthesis and TABLE below
>
> else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES"))
> - COMPLETE_WITH("EXCEPT TABLE (", "WITH (");
> + COMPLETE_WITH("EXCEPT ( TABLE", "WITH (");
>
> 3. for pg_dump, to improve readability can you just add TABLE keyword for every tables in the except list?
>
> - /* Include EXCEPT TABLE clause if there are except_tables. */
> + /* Include EXCEPT (TABLE) clause if there are except_tables. */
> for (SimplePtrListCell *cell = pubinfo->except_tables.head; cell; cell = cell->next)
> {
> TableInfo *tbinfo = (TableInfo *) cell->ptr;
>
> if (++n_except == 1)
> - appendPQExpBufferStr(query, " EXCEPT TABLE (");
> + appendPQExpBufferStr(query, " EXCEPT (TABLE ");
> else
> appendPQExpBufferStr(query, ", ");
>
> 4. Is the Assert needed below, code already produces error message.
>
> + Assert(pubobj->pubobjtype == PUBLICATIONOBJ_EXCEPT_TABLE);
> +
> + if (pubobj->pubobjtype == PUBLICATIONOBJ_CONTINUATION)
> + ereport(ERROR,
> + errcode(ERRCODE_SYNTAX_ERROR),
> + errmsg("invalid publication object list"),
> + errdetail("TABLE must be specified before a standalone table."),
> + parser_errposition(pubobj->location));
I think the Assert should stay as a defensive check to ensure this
function is only used for EXCEPT (TABLE) cases.

Thanks for reviewing the patch. I have addressed the remaining
comments and attached the patch in [1].
[1]: https://www.postgresql.org/message-id/CANhcyEUQvEK%2BHOH6Y8Fy30fNvC631ZopWKhwgskXjKnuXiGV5Q%40mail.gmail.com

Thanks,
Shlok Kyal


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-30 02:31:33
Message-ID: CAHut+PuUnDZ4ki8nCK6SkHOn8iP6N1Vm24jzWtEqRG9a_GMxrw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok.

Here are some review comments for the patch v3-0001.

(not yet reviewed the test code)

======
doc/src/sgml/ref/alter_publication.sgml

synopsis:

1.
- [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
+ TABLE [ ONLY ] <replaceable
class="parameter">table_name</replaceable> [ * ]

This is still not correct because it is missing the ellipsis that is
needed within 'except_table_object'. e.g, the currently documented
synopsis would not permit FOR ALL TABLE EXCEPT (TABLE t1,t2,t3);

You might describe that using one of these ways:

i)
TABLE { [ ONLY ] table_name [ * ] } [, ...]

ii)
TABLE [ ONLY ] table_name [ * ] [, ...]

iii)
TABLE table [,...]
and table is:
[ ONLY ] table_name [ * ]

======
doc/src/sgml/ref/create_publication.sgml

synopsis:

2.
Same synopsis problem as described in the above review comment. It is
missing the ellipsis that is needed within 'except_table_object'.

~~~

EXCEPT:

3.
<varlistentry id="sql-createpublication-params-for-except-table">
- <term><literal>EXCEPT TABLE</literal></term>
+ <term><literal>EXCEPT</literal></term>
<listitem>

The 'EXCEPT' clause is not really at the same level as all the other
ones, because it can only be applied to the FOR ALL TABLES. So, I felt
maybe 'EXCEPT' might make more sense as a sublist entry under the FOR
ALL TABLES clause.

Moving this would also eliminate some of the current repetition:
e.g. "Tables listed in EXCEPT clause are excluded from the publication."
e.g. "This clause specifies a list of tables to be excluded from the
publication."

======
src/backend/catalog/pg_publication.c

GetAllPublicationRelations:

4.
- * in EXCEPT TABLE clause.
+ * in EXCEPT clause.

/in EXCEPT clause/in the EXCEPT clause/

======
src/backend/parser/gram.y

5.
static void preprocess_pubobj_list(List *pubobjspec_list,
core_yyscan_t yyscanner);
+static void preprocess_except_pubobj_list(List *pubexceptobjspec_list,
+ core_yyscan_t yyscanner);

The new function and the parameter names do not match as they do in
the existing function. e.g. Should this new function instead be called
'preprocess_pubexceptobj_list'?

~~~

preprocess_except_pubobj_list:

6.
+ ListCell *cell;
+ PublicationObjSpec *pubobj;

Why is this function referring to PublicationObjSpec instead of
PublicationExceptObjSpec. Is it correct?

~~~

7.
+ if (pubobj->pubobjtype == PUBLICATIONOBJ_CONTINUATION)
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid publication object list"),
+ errdetail("TABLE must be specified before a standalone table."),
+ parser_errposition(pubobj->location));

If this was intended to mimic code from the existing function, then I
felt it should say "standalone table name." instead of "standalone
table.".

======
src/bin/pg_dump/pg_dump.c

8.
if (++n_except == 1)
- appendPQExpBufferStr(query, " EXCEPT TABLE (");
+ appendPQExpBufferStr(query, " EXCEPT (TABLE ");
else
- appendPQExpBufferStr(query, ", ");
+ appendPQExpBufferStr(query, ", TABLE ");

You don't need the TABLE keyword in 2 places like that.

SUGGESTION
if (++n_except == 1)
appendPQExpBufferStr(query, " EXCEPT (");
else
appendPQExpBufferStr(query, ", ");
appendPQExpBuffer(query, "TABLE ONLY %s", fmtQualifiedDumpable(tbinfo));

======
src/bin/pg_dump/t/002_pg_dump.pl

9.
'CREATE PUBLICATION pub10' => {
create_order => 92,
create_sql =>
- 'CREATE PUBLICATION pub10 FOR ALL TABLES EXCEPT TABLE
(dump_test.test_inheritance_parent);',
+ 'CREATE PUBLICATION pub10 FOR ALL TABLES EXCEPT (TABLE
dump_test.test_inheritance_parent);',
regexp => qr/^
- \QCREATE PUBLICATION pub10 FOR ALL TABLES EXCEPT TABLE (ONLY
dump_test.test_inheritance_parent, ONLY
dump_test.test_inheritance_child) WITH (publish = 'insert, update,
delete, truncate');\E
+ \QCREATE PUBLICATION pub10 FOR ALL TABLES EXCEPT (TABLE ONLY
dump_test.test_inheritance_parent, TABLE ONLY
dump_test.test_inheritance_child) WITH (publish = 'insert, update,
delete, truncate');\E
/xm,
like => { %full_runs, section_post_data => 1, },

(Maybe this question is unrelated to the current patch.)

Why is the expected result explicitly including ONLY children like
that instead of saying "EXCEPT (TABLE
dump_test.test_inheritance_parent *)"?

======
src/bin/psql/tab-complete.in.c

10.
- else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL",
"TABLES", "EXCEPT", "TABLE", "(", MatchAnyN) && ends_with(prev_wd,
','))
+ else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL",
"TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && ends_with(prev_wd,
','))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
- else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL",
"TABLES", "EXCEPT", "TABLE", "(", MatchAnyN) && !ends_with(prev_wd,
','))
+ else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL",
"TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && !ends_with(prev_wd,
','))
COMPLETE_WITH(")");

The CREATE PUBLICATION seems to have tab-completion logic for the ','
separator and closing ')'. But I did not see any similar
tab-completion logic for the EXCEPT clause in ALTER PUBLICATION. Is
this maybe another issue independent of this patch?

======
src/test/regress/expected/publication.out
src/test/regress/sql/publication.sql
src/test/subscription/t/037_except.pl

(I will review these later)

======
GENERAL

11.
The file src/backend/commands/publicationcmds.c still refers to
"(EXCEPT TABLES)".

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-30 03:59:29
Message-ID: CAJpy0uDfzcW6q1tUedu5aPBf2EjYm_k_JhzFdE0KR2adhWt2fA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Mar 30, 2026 at 8:02 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok.
>
> Here are some review comments for the patch v3-0001.
>
> (not yet reviewed the test code)
>
>
> ======
> doc/src/sgml/ref/alter_publication.sgml
>
> synopsis:
>
> 1.
> - [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
> + TABLE [ ONLY ] <replaceable
> class="parameter">table_name</replaceable> [ * ]
>
> This is still not correct because it is missing the ellipsis that is
> needed within 'except_table_object'. e.g, the currently documented
> synopsis would not permit FOR ALL TABLE EXCEPT (TABLE t1,t2,t3);
>
> You might describe that using one of these ways:
>
> i)
> TABLE { [ ONLY ] table_name [ * ] } [, ...]
>

But isn't '{' is used to indicate a group of options, usually combined
with | to show choices. Examples:

TABLES IN SCHEMA { schema_name | CURRENT_SCHEMA } [, ... ]

ALTER PUBLICATION name OWNER TO { new_owner | CURRENT_ROLE |
CURRENT_USER | SESSION_USER }

In our case, I don't see such an option list. Let me know if I have
misunderstood.

thanks
Shveta


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-30 04:07:19
Message-ID: CAA4eK1Kb5Mg_MPDAZGb4PofRryXLjEFRd2k3aV=KCW-kmmkwvw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Mar 30, 2026 at 8:02 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> ~~~
>
> EXCEPT:
>
> 3.
> <varlistentry id="sql-createpublication-params-for-except-table">
> - <term><literal>EXCEPT TABLE</literal></term>
> + <term><literal>EXCEPT</literal></term>
> <listitem>
>
> The 'EXCEPT' clause is not really at the same level as all the other
> ones, because it can only be applied to the FOR ALL TABLES. So, I felt
> maybe 'EXCEPT' might make more sense as a sublist entry under the FOR
> ALL TABLES clause.
>

Possible but in future it would be applicable for all the three
variants listed above: FOR TABLES IN SCHEMA, FOR ALL TABLES, FOR ALL
SEQUENCES. So, don't think making it as a sublist for "FOR ALL TABLE"
is a good idea. I find keeping it at its current place okay as it is
also an independent clause.

--
With Regards,
Amit Kapila.


From: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-30 04:11:33
Message-ID: CAFiTN-shuXJjuSYqm4+Eyc08_Zzdaerf=yTHsYL6=zMEWKhf_w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Mar 30, 2026 at 9:37 AM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Mon, Mar 30, 2026 at 8:02 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >
> > ~~~
> >
> > EXCEPT:
> >
> > 3.
> > <varlistentry id="sql-createpublication-params-for-except-table">
> > - <term><literal>EXCEPT TABLE</literal></term>
> > + <term><literal>EXCEPT</literal></term>
> > <listitem>
> >
> > The 'EXCEPT' clause is not really at the same level as all the other
> > ones, because it can only be applied to the FOR ALL TABLES. So, I felt
> > maybe 'EXCEPT' might make more sense as a sublist entry under the FOR
> > ALL TABLES clause.
> >
>
> Possible but in future it would be applicable for all the three
> variants listed above: FOR TABLES IN SCHEMA, FOR ALL TABLES, FOR ALL
> SEQUENCES. So, don't think making it as a sublist for "FOR ALL TABLE"
> is a good idea. I find keeping it at its current place okay as it is
> also an independent clause.

Keeping it independent makes sense, as it will allow for easier future
expansion.

--
Regards,
Dilip Kumar
Google


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-30 04:36:58
Message-ID: CAJpy0uC1Lq01mu8OuXzWkMHSAVUAxs_bdVdoqqu4VDW1PemteA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

preprocess_except_pubobj_list:

+ Assert(pubobj->pubobjtype == PUBLICATIONOBJ_EXCEPT_TABLE ||
+ pubobj->pubobjtype == PUBLICATIONOBJ_CONTINUATION);
+

We need Sanity check on each object of the list rather than on first
object alone i.e. each object should have type EXCEPT or its
continuation. Thus it makes more sense to move Assert inside 'for
loop' and add a comment too:
<please feel free to change comment if needed>

foreach(cell, pubexceptobjspec_list)
{
pubobj = (PublicationObjSpec *) lfirst(cell);

/*
* The object type must be either PUBLICATIONOBJ_EXCEPT_TABLE or
* PUBLICATIONOBJ_CONTINUATION. It cannot be PUBLICATIONOBJ_TABLE,
* PUBLICATIONOBJ_TABLES_IN_SCHEMA or
* PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA here.
*/
Assert(pubobj->pubobjtype == PUBLICATIONOBJ_EXCEPT_TABLE ||
pubobj->pubobjtype == PUBLICATIONOBJ_CONTINUATION);
.....

thanks
Shveta


From: "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Skipping schema changes in publication
Date: 2026-03-30 05:51:23
Message-ID: TY4PR01MB169072D244423BED52C8D5B249452A@TY4PR01MB16907.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Saturday, March 28, 2026 4:50 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
>
> On Fri, 27 Mar 2026 at 18:04, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> >
> >
> > BTW, why do we need preprocess_except_pubobj_list?
> >
> It is needed to check if the first table in the EXCEPT list is specified with TABLE
> Keyword.
> For example: create publication pub1 for all tables except (t1, t2); This should
> throw an error because t1 is specified without the TABLE keyword.
>
> We have a similar logic for FOR TABLE or FOR TABLES IN SCHEMA
> publications in 'preprocess_pubobj_list'

The preprocess_pubobj_list function was originally introduced to handle mixed
object types (SCHEMA and TABLE) in the main list, allowing type-specific
processing per item. However, the EXCEPT clause currently only supports TABLE
objects. So strictly speaking, we don't need a similar preprocessing function
here, at least not until we support other object types in the EXCEPT clause. We
could implement the same logic directly in bison code, as shown in the attached
example.

>
> I have attached the latest version here. I have also addressed the comment
> shared by Shveta in [1].
> [1]: https://www.postgresql.org/message-
> id/CAJpy0uCMhxUdEZMqDuSHXeAMES1gH56r-
> tkhR1J79A_f3wrLkg(at)mail(dot)gmail(dot)com

Best Regards,
Hou zj

Attachment Content-Type Size
v1-0001-simplify-gram.y-atop-of-your-patch_patch application/octet-stream 3.6 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-30 05:58:15
Message-ID: CAHut+PvV_Yvm3VYWrbP=TL5_yvKUbQJbv=P3yt09odEV+1igYg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Shlok.

Here are the remainder of my review comments for patch v3-0001.

These are for the test code only.

======
src/test/regress/sql/publication.sql

Missing Test case:

1.
AFAICT, there are currently no test cases for ALTER PUBLICATION that
are using variations of the syntax having multiple TABLE keywords.
e.g. "EXCEPT (TABLE t1,t2,t3, TABLE t4)".

IOW, the flexible syntax is being tested for CREATE PUBLICATION, but
not for ALTER PUBLICATION.

~~~

2.
--- Replace the existing EXCEPT TABLE list (testpub_tbl1) with a new
--- EXCEPT TABLE list containing only (testpub_tbl2).
-ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES
EXCEPT TABLE (testpub_tbl2);
+-- Replace the existing table list in EXCEPT clause (testpub_tbl1) with a new
+-- table list containing only (testpub_tbl2).
+ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES
EXCEPT (TABLE testpub_tbl2);

The comment seems wrong because, IIUC, the existing exclude-list at
this point would be "(TABLE testpub_tbl1, testpub_tbl2, TABLE
testpub_tbl3)".

Also /in EXCEPT clause/in the EXCEPT clause/

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-30 09:13:48
Message-ID: CAA4eK1K0uHt-o=OAqh2qT7gDyef-BrHb=Z-94kCB8dH8r3SDeA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Mar 30, 2026 at 11:21 AM Zhijie Hou (Fujitsu)
<houzj(dot)fnst(at)fujitsu(dot)com> wrote:
>
> On Saturday, March 28, 2026 4:50 AM Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com> wrote:
> >
> > On Fri, 27 Mar 2026 at 18:04, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
> > >
> > >
> > > BTW, why do we need preprocess_except_pubobj_list?
> > >
> > It is needed to check if the first table in the EXCEPT list is specified with TABLE
> > Keyword.
> > For example: create publication pub1 for all tables except (t1, t2); This should
> > throw an error because t1 is specified without the TABLE keyword.
> >
> > We have a similar logic for FOR TABLE or FOR TABLES IN SCHEMA
> > publications in 'preprocess_pubobj_list'
>
> The preprocess_pubobj_list function was originally introduced to handle mixed
> object types (SCHEMA and TABLE) in the main list, allowing type-specific
> processing per item. However, the EXCEPT clause currently only supports TABLE
> objects. So strictly speaking, we don't need a similar preprocessing function
> here, at least not until we support other object types in the EXCEPT clause.
>

Fair enough. We could extend it later as and when required. I have one
minor comment:

*
+ | pub_except_obj_list ',' TABLE PublicationExceptObjSpec
+ { $$ = lappend($1, $4); }
| pub_except_obj_list ',' PublicationExceptObjSpec

Can we encapsulate 'TABLE PublicationExceptObjSpec' and
'PublicationExceptObjSpec' into separate 'opt_tbl_except_obj_spec'?

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-30 14:44:30
Message-ID: CALDaNm0wV2Jd558jWG2EWVAjCiuaAEUrP4i2FWBKqob=1Y9-2A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, 30 Mar 2026 at 08:02, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Shlok.
>
> Here are some review comments for the patch v3-0001.
>
> (not yet reviewed the test code)
>
>
> ======
> doc/src/sgml/ref/alter_publication.sgml
>
> synopsis:
>
> 1.
> - [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
> + TABLE [ ONLY ] <replaceable
> class="parameter">table_name</replaceable> [ * ]
>
> This is still not correct because it is missing the ellipsis that is
> needed within 'except_table_object'. e.g, the currently documented
> synopsis would not permit FOR ALL TABLE EXCEPT (TABLE t1,t2,t3);
>
> You might describe that using one of these ways:
>
> i)
> TABLE { [ ONLY ] table_name [ * ] } [, ...]
>
> ii)
> TABLE [ ONLY ] table_name [ * ] [, ...]
>
> iii)
> TABLE table [,...]
> and table is:
> [ ONLY ] table_name [ * ]

Modified

> ======
> doc/src/sgml/ref/create_publication.sgml
>
> synopsis:
>
> 2.
> Same synopsis problem as described in the above review comment. It is
> missing the ellipsis that is needed within 'except_table_object'.

The previous comment fixes this issue

> ~~~
>
> EXCEPT:
>
> 3.
> <varlistentry id="sql-createpublication-params-for-except-table">
> - <term><literal>EXCEPT TABLE</literal></term>
> + <term><literal>EXCEPT</literal></term>
> <listitem>
>
> The 'EXCEPT' clause is not really at the same level as all the other
> ones, because it can only be applied to the FOR ALL TABLES. So, I felt
> maybe 'EXCEPT' might make more sense as a sublist entry under the FOR
> ALL TABLES clause.
>
> Moving this would also eliminate some of the current repetition:
> e.g. "Tables listed in EXCEPT clause are excluded from the publication."
> e.g. "This clause specifies a list of tables to be excluded from the
> publication."

Amit has replied to this at [1].

> ======
> src/backend/catalog/pg_publication.c
>
> GetAllPublicationRelations:
>
> 4.
> - * in EXCEPT TABLE clause.
> + * in EXCEPT clause.
>
> /in EXCEPT clause/in the EXCEPT clause/

modified

> ======
> src/backend/parser/gram.y
>
> 5.
> static void preprocess_pubobj_list(List *pubobjspec_list,
> core_yyscan_t yyscanner);
> +static void preprocess_except_pubobj_list(List *pubexceptobjspec_list,
> + core_yyscan_t yyscanner);
>
> The new function and the parameter names do not match as they do in
> the existing function. e.g. Should this new function instead be called
> 'preprocess_pubexceptobj_list'?

The function has been removed now because of Hou-san's improvement
suggestion at [2].

> ~~~
>
> preprocess_except_pubobj_list:
>
> 6.
> + ListCell *cell;
> + PublicationObjSpec *pubobj;
>
> Why is this function referring to PublicationObjSpec instead of
> PublicationExceptObjSpec. Is it correct?

The function has been removed now because of Hou-san's improvement
suggestion at [2].

> ~~~
>
> 7.
> + if (pubobj->pubobjtype == PUBLICATIONOBJ_CONTINUATION)
> + ereport(ERROR,
> + errcode(ERRCODE_SYNTAX_ERROR),
> + errmsg("invalid publication object list"),
> + errdetail("TABLE must be specified before a standalone table."),
> + parser_errposition(pubobj->location));
>
> If this was intended to mimic code from the existing function, then I
> felt it should say "standalone table name." instead of "standalone
> table.".

The function has been removed now because of Hou-san's improvement
suggestion at [2].

> ======
> src/bin/pg_dump/pg_dump.c
>
> 8.
> if (++n_except == 1)
> - appendPQExpBufferStr(query, " EXCEPT TABLE (");
> + appendPQExpBufferStr(query, " EXCEPT (TABLE ");
> else
> - appendPQExpBufferStr(query, ", ");
> + appendPQExpBufferStr(query, ", TABLE ");
>
> You don't need the TABLE keyword in 2 places like that.
>
> SUGGESTION
> if (++n_except == 1)
> appendPQExpBufferStr(query, " EXCEPT (");
> else
> appendPQExpBufferStr(query, ", ");
> appendPQExpBuffer(query, "TABLE ONLY %s", fmtQualifiedDumpable(tbinfo));

Modified

> ======
> src/bin/pg_dump/t/002_pg_dump.pl
>
> 9.
> 'CREATE PUBLICATION pub10' => {
> create_order => 92,
> create_sql =>
> - 'CREATE PUBLICATION pub10 FOR ALL TABLES EXCEPT TABLE
> (dump_test.test_inheritance_parent);',
> + 'CREATE PUBLICATION pub10 FOR ALL TABLES EXCEPT (TABLE
> dump_test.test_inheritance_parent);',
> regexp => qr/^
> - \QCREATE PUBLICATION pub10 FOR ALL TABLES EXCEPT TABLE (ONLY
> dump_test.test_inheritance_parent, ONLY
> dump_test.test_inheritance_child) WITH (publish = 'insert, update,
> delete, truncate');\E
> + \QCREATE PUBLICATION pub10 FOR ALL TABLES EXCEPT (TABLE ONLY
> dump_test.test_inheritance_parent, TABLE ONLY
> dump_test.test_inheritance_child) WITH (publish = 'insert, update,
> delete, truncate');\E
> /xm,
> like => { %full_runs, section_post_data => 1, },
>
> (Maybe this question is unrelated to the current patch.)
>
> Why is the expected result explicitly including ONLY children like
> that instead of saying "EXCEPT (TABLE
> dump_test.test_inheritance_parent *)"?

This behavior is kept similar to how it is handled for table publication
ex:
CREATE TABLE test_inheritance_parent (col1 int NOT NULL, col2 int
CHECK (col2 >= 42));
CREATE TABLE test_inheritance_child (col1 int NOT NULL, CONSTRAINT
test_inheritance_child CHECK (col2 >= 142857) ) INHERITS
(test_inheritance_parent);
CREATE PUBLICATION pub10 FOR TABLE test_inheritance_parent;

Dump outputs the following:
--
-- Name: pub10 test_inheritance_child; Type: PUBLICATION TABLE;
Schema: public; Owner: vignesh
--
ALTER PUBLICATION pub10 ADD TABLE ONLY public.test_inheritance_child;

--
-- Name: pub10 test_inheritance_parent; Type: PUBLICATION TABLE;
Schema: public; Owner: vignesh
--
ALTER PUBLICATION pub10 ADD TABLE ONLY public.test_inheritance_parent;

> ======
> src/bin/psql/tab-complete.in.c
>
> 10.
> - else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL",
> "TABLES", "EXCEPT", "TABLE", "(", MatchAnyN) && ends_with(prev_wd,
> ','))
> + else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL",
> "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && ends_with(prev_wd,
> ','))
> COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
> - else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL",
> "TABLES", "EXCEPT", "TABLE", "(", MatchAnyN) && !ends_with(prev_wd,
> ','))
> + else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL",
> "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && !ends_with(prev_wd,
> ','))
> COMPLETE_WITH(")");
>
> The CREATE PUBLICATION seems to have tab-completion logic for the ','
> separator and closing ')'. But I did not see any similar
> tab-completion logic for the EXCEPT clause in ALTER PUBLICATION. Is
> this maybe another issue independent of this patch?

Modified

> ======
> src/test/regress/expected/publication.out
> src/test/regress/sql/publication.sql
> src/test/subscription/t/037_except.pl
>
> (I will review these later)
>
> ======
> GENERAL
>
> 11.
> The file src/backend/commands/publicationcmds.c still refers to
> "(EXCEPT TABLES)".

Modified

The v4 version patch has the changes for the same.
The v4 version also addresses the comments provided by Peter at [3]
and Amit at [4].

[1] - https://www.postgresql.org/message-id/CAA4eK1Kb5Mg_MPDAZGb4PofRryXLjEFRd2k3aV%3DKCW-kmmkwvw%40mail.gmail.com
[2] - https://www.postgresql.org/message-id/TY4PR01MB169072D244423BED52C8D5B249452A%40TY4PR01MB16907.jpnprd01.prod.outlook.com
[3] - https://www.postgresql.org/message-id/CAHut%2BPvV_Yvm3VYWrbP%3DTL5_yvKUbQJbv%3DP3yt09odEV%2B1igYg%40mail.gmail.com
[4] - https://www.postgresql.org/message-id/CAA4eK1K0uHt-o%3DOAqh2qT7gDyef-BrHb%3DZ-94kCB8dH8r3SDeA%40mail.gmail.com

Regards,
Vignesh

Attachment Content-Type Size
v4-0001-Change-syntax-of-EXCEPT-TABLE-clause-in-publicati.patch application/octet-stream 50.0 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-31 00:29:39
Message-ID: CAHut+Pv+sE82few1Chv4wBGnTR548n_FrzGyabL0w_1TOG6GCA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi Vignesh.

Some review comments for patch v4-0001.

======
doc/src/sgml/ref/alter_publication.sgml

1.
- [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
+ TABLE <replaceable class="parameter">table_object</replaceable> [, ... ]
+
+<phrase>and <replaceable class="parameter">table_object</replaceable>
is:</phrase>
+
+ [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]

With the introduction of 'table_object' I expected that
'table_and_columns' and 'publication_drop_object' would also make use
of it. Why not?

======
doc/src/sgml/ref/create_publication.sgml

2.
- [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
+ TABLE <replaceable class="parameter">table_object</replaceable> [, ... ]
+
+<phrase>and <replaceable class="parameter">table_object</replaceable>
is:</phrase>
+
+ [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]

With the introduction of 'table_object' I expected that
'table_and_columns' would also make use of it. Why not?

======
src/backend/parser/gram.y

3.
@@ -11399,7 +11399,7 @@ pub_obj_list: PublicationObjSpec
;

opt_pub_except_clause:
- EXCEPT TABLE '(' pub_except_obj_list ')' { $$ = $4; }
+ EXCEPT '(' TABLE pub_except_obj_list ')' { $$ = $4; }
| /*EMPTY*/ { $$ = NIL; }
;

@@ -11439,8 +11439,8 @@ PublicationExceptObjSpec:

pub_except_obj_list: PublicationExceptObjSpec
{ $$ = list_make1($1); }
- | pub_except_obj_list ',' PublicationExceptObjSpec
- { $$ = lappend($1, $3); }
+ | pub_except_obj_list ',' opt_table PublicationExceptObjSpec
+ { $$ = lappend($1, $4); }
;

IMO we should put 'table' in all those table-specific production names:
e.g. opt_pub_except_clause ==> opt_pub_except_table_clause
e.g. pub_except_obj_list ==> pub_except_tableobj_list
e.g. PublicationExceptObjSpec ==> PublicationExceptTableObjSpec

IIUC, in future when "FOR ALL SEQUENCES EXCEPT (SEQUENCES ...)" and/or
"FOR ALL SCHEMAS EXCEPT (SCHEMA ...)" are implemented then these names
won't be much good anymore, so I thought they should be made
table-specific now to avoid churning them later.

======
src/bin/psql/tab-complete.in.c

4.
- COMPLETE_WITH("EXCEPT TABLE (");
+ COMPLETE_WITH("EXCEPT ( TABLE");

(this is in several places in ALTER and CREATE)

In v3 the space in "( TABLE" was changed to "(TABLE", but now in v4
the space is back again. AFAICT the v3 change was in response to
review [1] (comment #2). Was it reverted deliberately?

======
[1] https://www.postgresql.org/message-id/CAHg%2BQDe%2B7J0e1JLjpqe-NxVJMWXH6UDtqugrm%2BDP7rHEJLrBqQ%40mail.gmail.com

Kind Regards,
Peter Smith.
Fujitsu Australia


From: "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>
To: 'Peter Smith' <smithpb2250(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Skipping schema changes in publication
Date: 2026-03-31 03:54:37
Message-ID: OS9PR01MB12149CC87E864D982B5619365F553A@OS9PR01MB12149.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Dear Peter,

> ======
> src/bin/psql/tab-complete.in.c
>
> 4.
> - COMPLETE_WITH("EXCEPT TABLE (");
> + COMPLETE_WITH("EXCEPT ( TABLE");
>
> (this is in several places in ALTER and CREATE)
>
> In v3 the space in "( TABLE" was changed to "(TABLE", but now in v4
> the space is back again. AFAICT the v3 change was in response to
> review [1] (comment #2). Was it reverted deliberately?

I think it's proper to have the blank before/after the parentheses. See the
existing example.

```
/* ALTER TABLE <name> SPLIT PARTITION <name> */
else if (Matches("ALTER", "TABLE", MatchAny, "SPLIT", "PARTITION", MatchAny))
COMPLETE_WITH("INTO ( PARTITION");
```

Also, if we type till `CREATE PUBLICATION pub WITH` and type tab several times,
the suggested string is something like below:

```
CREATE PUBLICATION pub WITH ( PUBLISH
```

It means normally the blank exists in between the term.

Best regards,
Hayato Kuroda
FUJITSU LIMITED


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-31 03:55:31
Message-ID: CAA4eK1K7KaAB_CLVHDPE8UzAYRYPzJwpGMEwcEU=1yzS0SyNyQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 31, 2026 at 6:00 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Vignesh.
>
> Some review comments for patch v4-0001.
>
> ======
> doc/src/sgml/ref/alter_publication.sgml
>
> 1.
> - [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ *
]
> + TABLE <replaceable class="parameter">table_object</replaceable> [,
... ]
> +
> +<phrase>and <replaceable class="parameter">table_object</replaceable>
> is:</phrase>
> +
> + [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
>
> With the introduction of 'table_object' I expected that
> 'table_and_columns' and 'publication_drop_object' would also make use
> of it. Why not?
>
> ======
> doc/src/sgml/ref/create_publication.sgml
>
> 2.
> - [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ *
]
> + TABLE <replaceable class="parameter">table_object</replaceable> [,
... ]
> +
> +<phrase>and <replaceable class="parameter">table_object</replaceable>
> is:</phrase>
> +
> + [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
>
> With the introduction of 'table_object' I expected that
> 'table_and_columns' would also make use of it. Why not?
>

These sound like worth considering but let's do them as a separate patch,
otherwise, the main patch may take more time.

>
> ======
> src/backend/parser/gram.y
>
> 3.
> @@ -11399,7 +11399,7 @@ pub_obj_list: PublicationObjSpec
> ;
>
> opt_pub_except_clause:
> - EXCEPT TABLE '(' pub_except_obj_list ')' { $$ = $4; }
> + EXCEPT '(' TABLE pub_except_obj_list ')' { $$ = $4; }
> | /*EMPTY*/ { $$ = NIL; }
> ;
>
> @@ -11439,8 +11439,8 @@ PublicationExceptObjSpec:
>
> pub_except_obj_list: PublicationExceptObjSpec
> { $$ = list_make1($1); }
> - | pub_except_obj_list ',' PublicationExceptObjSpec
> - { $$ = lappend($1, $3); }
> + | pub_except_obj_list ',' opt_table PublicationExceptObjSpec
> + { $$ = lappend($1, $4); }
> ;
>
> IMO we should put 'table' in all those table-specific production names:
> e.g. opt_pub_except_clause ==> opt_pub_except_table_clause
> e.g. pub_except_obj_list ==> pub_except_tableobj_list
> e.g. PublicationExceptObjSpec ==> PublicationExceptTableObjSpec
>
> IIUC, in future when "FOR ALL SEQUENCES EXCEPT (SEQUENCES ...)" and/or
> "FOR ALL SCHEMAS EXCEPT (SCHEMA ...)" are implemented then these names
> won't be much good anymore, so I thought they should be made
> table-specific now to avoid churning them later.

I think if/when we need to further extend this feature, we need to go back
to the previous approach of using something akin to the
preprocess_pub_all_objtype_list() kind of function. Consider when we need
to support EXCEPT (TABLES IN SCHEMA s1, TABLE t1) kind of cases, the
current code may or may not be the best way to realize it. So, I think for
now we can leave discussion on this to future extensions of this feature.

--
With Regards,
Amit Kapila.


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-31 04:22:40
Message-ID: CAHut+Ptzir7Xdb_CRDiiume+Y7bbkg+JAx4JucXAwaPKqHpZRA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 31, 2026 at 2:54 PM Hayato Kuroda (Fujitsu)
<kuroda(dot)hayato(at)fujitsu(dot)com> wrote:
>
> Dear Peter,
>
> > ======
> > src/bin/psql/tab-complete.in.c
> >
> > 4.
> > - COMPLETE_WITH("EXCEPT TABLE (");
> > + COMPLETE_WITH("EXCEPT ( TABLE");
> >
> > (this is in several places in ALTER and CREATE)
> >
> > In v3 the space in "( TABLE" was changed to "(TABLE", but now in v4
> > the space is back again. AFAICT the v3 change was in response to
> > review [1] (comment #2). Was it reverted deliberately?
>
> I think it's proper to have the blank before/after the parentheses. See the
> existing example.
>
> ```
> /* ALTER TABLE <name> SPLIT PARTITION <name> */
> else if (Matches("ALTER", "TABLE", MatchAny, "SPLIT", "PARTITION", MatchAny))
> COMPLETE_WITH("INTO ( PARTITION");
> ```
>
> Also, if we type till `CREATE PUBLICATION pub WITH` and type tab several times,
> the suggested string is something like below:
>
> ```
> CREATE PUBLICATION pub WITH ( PUBLISH
> ```
>
> It means normally the blank exists in between the term.
>

OK. I didn't really have an opinion about it. I was only pointing out
it was changed in v3 and then changed again in v4 so I was just
checking if it was deliberate.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-31 08:45:11
Message-ID: CAA4eK1+pbxedyZMMmN4R+Pi+aj3+sAcMyk-DNe36b9gBBk2_og@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Mar 30, 2026 at 8:14 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> The v4 version patch has the changes for the same.
> The v4 version also addresses the comments provided by Peter at [3]
> and Amit at [4].
>

Pushed the latest version.

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-03-31 09:30:30
Message-ID: CALDaNm1CiBYcteE_jjPA4BPHfX30dg9eTTTkJgkjY5tgE7t=bQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, 31 Mar 2026 at 06:00, Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> Hi Vignesh.
>
> Some review comments for patch v4-0001.
>
> ======
> doc/src/sgml/ref/alter_publication.sgml
>
> 1.
> - [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
> + TABLE <replaceable class="parameter">table_object</replaceable> [, ... ]
> +
> +<phrase>and <replaceable class="parameter">table_object</replaceable>
> is:</phrase>
> +
> + [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
>
> With the introduction of 'table_object' I expected that
> 'table_and_columns' and 'publication_drop_object' would also make use
> of it. Why not?
>
> ======
> doc/src/sgml/ref/create_publication.sgml
>
> 2.
> - [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
> + TABLE <replaceable class="parameter">table_object</replaceable> [, ... ]
> +
> +<phrase>and <replaceable class="parameter">table_object</replaceable>
> is:</phrase>
> +
> + [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
>
> With the introduction of 'table_object' I expected that
> 'table_and_columns' would also make use of it. Why not?
>

Thanks for the comments. This is addressed in the 002 patch attached.
The 001 patch has the rebased version of the patch at [1] to fix
Peter's earlier comments at [2].

[1] - https://www.postgresql.org/message-id/CALDaNm0mYT55pjdyN-yY%3D5dSOfMVx307CtP3xYqzWVa0MPRtLQ%40mail.gmail.com
[2] - https://www.postgresql.org/message-id/CAHut%2BPvw-XNBnW-ymGdWpLxaEime7_EdOihcUheGyZvw73kcgg%40mail.gmail.com

Regards,
Vignesh-

Attachment Content-Type Size
0002-Reuse-table_object-in-publication-command-syntax.patch application/octet-stream 2.9 KB
0001-Fix-few-issues-in-commit-fd366065e0.patch application/octet-stream 7.3 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-04-01 00:42:55
Message-ID: CAHut+PuzgDiBcD6rp_31RzqbGLpMwqGrNKznFUA_fpBpZYPe9Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Tue, Mar 31, 2026 at 8:30 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
...
>
> Thanks for the comments. This is addressed in the 002 patch attached.
> The 001 patch has the rebased version of the patch at [1] to fix
> Peter's earlier comments at [2].
>
> [1] - https://www.postgresql.org/message-id/CALDaNm0mYT55pjdyN-yY%3D5dSOfMVx307CtP3xYqzWVa0MPRtLQ%40mail.gmail.com
> [2] - https://www.postgresql.org/message-id/CAHut%2BPvw-XNBnW-ymGdWpLxaEime7_EdOihcUheGyZvw73kcgg%40mail.gmail.com
>

Hi Vignesh.

Thanks for following up on my outstanding review comments.

//////
Patch 0001 - Fix few issues in commit fd366065e0

This did not address the review comment 3a about the redundant macro
'_("\"%s\"")', but that one might be better handled in a separate
thread anyway. I can post a separate thread for that one later.

So, patch 0001 LGTM.

//////
Patch 0002 - Reuse table_object in publication command syntax

LGTM.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-04-01 02:15:38
Message-ID: CAA4eK1LG9ezz2QHMfaAKeWqCaRLRaDtu6-kBgrCRq14UaB3ECA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Apr 1, 2026 at 6:13 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> On Tue, Mar 31, 2026 at 8:30 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> ...
> >
> > Thanks for the comments. This is addressed in the 002 patch attached.
> > The 001 patch has the rebased version of the patch at [1] to fix
> > Peter's earlier comments at [2].
> >
> > [1] - https://www.postgresql.org/message-id/CALDaNm0mYT55pjdyN-yY%3D5dSOfMVx307CtP3xYqzWVa0MPRtLQ%40mail.gmail.com
> > [2] - https://www.postgresql.org/message-id/CAHut%2BPvw-XNBnW-ymGdWpLxaEime7_EdOihcUheGyZvw73kcgg%40mail.gmail.com
> >
>
> Hi Vignesh.
>
> Thanks for following up on my outstanding review comments.
>
> //////
> Patch 0001 - Fix few issues in commit fd366065e0
>
> This did not address the review comment 3a about the redundant macro
> '_("\"%s\"")', but that one might be better handled in a separate
> thread anyway. I can post a separate thread for that one later.
>

Yes, as it uses an existing code as an example, it is better to start
a separate thread. I was planning to do some research by myself after
finishing the pending tasks here but feel free to start if you have
formed your thoughts on it.

--
With Regards,
Amit Kapila.


From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-04-01 03:55:53
Message-ID: CAHut+PsXKQbyAhQLRHX0aANkJZPWsYpz4TQQba1WFM7dvSwXNg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Apr 1, 2026 at 1:15 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> On Wed, Apr 1, 2026 at 6:13 AM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
> >
...
> > Hi Vignesh.
> >
> > Thanks for following up on my outstanding review comments.
> >
> > //////
> > Patch 0001 - Fix few issues in commit fd366065e0
> >
> > This did not address the review comment 3a about the redundant macro
> > '_("\"%s\"")', but that one might be better handled in a separate
> > thread anyway. I can post a separate thread for that one later.
> >
>
> Yes, as it uses an existing code as an example, it is better to start
> a separate thread. I was planning to do some research by myself after
> finishing the pending tasks here but feel free to start if you have
> formed your thoughts on it.
>

New thread for this is here [1].

======
[1] https://www.postgresql.org/message-id/CAHut%2BPvp7jYcaiZ3pXedXgLcWZWDBLXFUK05JtZpGv3Mj%3DUOjw%40mail.gmail.com

Kind Regards,
Peter Smith.
Fujitsu Australia.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-04-20 12:13:15
Message-ID: CALDaNm2VghC-CSyS6jwyMMcpwSWjQ09t9AkkL0Sz7dsb1VGF3A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

Hi,

When changing a table to UNLOGGED, tables that appear in publications
via EXCEPT clauses (prexcept = true) are currently allowed, but their
entries remain in pg_publication_rel.

For example:
postgres=# create table t1(c1 int);
CREATE TABLE
postgres=# create publication pub1 for all tables except (table t1);
CREATE PUBLICATION
postgres=# alter table t1 set unlogged;
ALTER TABLE
postgres=# \d t1
Unlogged table "public.t1"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
c1 | integer | | |
Except publications:
"pub1"

Since UNLOGGED tables are not supported in publications, this leaves
stale catalog entries. This patch removes such entries from
pg_publication_rel when the table is changed to UNLOGGED, and emits a
NOTICE to inform the user.

Another option considered was to throw an error when setting such
tables to UNLOGGED. However, allowing the operation was preferred,
since UNLOGGED tables do not generate WAL and are not replicated
anyway, so blocking the operation would be unnecessarily restrictive.

Attached patch has the changes for the same.

Thoughts?

Regards,
Vignesh

Attachment Content-Type Size
v1-0001-Handle-EXCEPT-publications-when-changing-table-to.patch application/octet-stream 6.2 KB

From: Peter Smith <smithpb2250(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-04-22 02:58:08
Message-ID: CAHut+PvPRrm7GLp1i9qTiYqs8Okbh6vkhkkahiM2=Lo6e9qXTA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Apr 20, 2026 at 10:13 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> Hi,
>
> When changing a table to UNLOGGED, tables that appear in publications
> via EXCEPT clauses (prexcept = true) are currently allowed, but their
> entries remain in pg_publication_rel.
>
> For example:
> postgres=# create table t1(c1 int);
> CREATE TABLE
> postgres=# create publication pub1 for all tables except (table t1);
> CREATE PUBLICATION
> postgres=# alter table t1 set unlogged;
> ALTER TABLE
> postgres=# \d t1
> Unlogged table "public.t1"
> Column | Type | Collation | Nullable | Default
> --------+---------+-----------+----------+---------
> c1 | integer | | |
> Except publications:
> "pub1"
>
> Since UNLOGGED tables are not supported in publications, this leaves
> stale catalog entries. This patch removes such entries from
> pg_publication_rel when the table is changed to UNLOGGED, and emits a
> NOTICE to inform the user.
>
> Another option considered was to throw an error when setting such
> tables to UNLOGGED. However, allowing the operation was preferred,
> since UNLOGGED tables do not generate WAL and are not replicated
> anyway, so blocking the operation would be unnecessarily restrictive.
>
> Attached patch has the changes for the same.
>
> Thoughts?
>

Hi Vignesh -

A couple of review comments for patch v1-0001.

======
Background: I found when altering a published table from LOGGED to UNLOGGED...

- If it was published by "FOR ALL TABLES" then it just becomes
unpublished *silently*.
- Ditto if it was published by "FOR TABLES IN SCHEMA"
- It seems you only got an error on ALTER LOGGED->UNLOGGED when the
published table was specifically published by "FOR TABLE".

======
src/backend/commands/tablecmds.c

1.
+ /* Find all publications associated with the relation. */
+ pubrellist = SearchSysCacheList1(PUBLICATIONRELMAP,
+ ObjectIdGetDatum(RelationGetRelid(rel)));

This comment seems misleading. IIUC, it's only going to find relations
specifically mentioned by name in the command. Any relations that are
associated with the publication due to "FOR ALL TABLES" or "FOR TABLES
IN SCHEMA" are not known.

~~~

2.
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot change table \"%s\" to unlogged because it is part of
a publication",
+ RelationGetRelationName(rel)),
+ errdetail("Unlogged relations cannot be replicated.")))

This does not seem like a very good error message in the first place
(yes, I know this patch did not change it).

e.g.

a) It says it is "part of a publication", but it does not tell the
user which ones. Maybe list them in the message or provide a HINT to
say use \d to show them.

b) It mixes terminology, first calling it a 'table', and then calling
it a 'relation'

~~~

3.
+ ereport(NOTICE,
+ errmsg("relation \"%s\" removed from publication \"%s\" due to being
changed to UNLOGGED",
+ RelationGetRelationName(rel), pubname));

After some consideration, I think that this really should be an ERROR
too, not just a NOTICE.

Otherwise, if the user toggled the excluded table from
LOGGED->UNLOGGED->LOGGED, then the same table would go from being
excluded to being included! The consequences of publishing something
that was originally *specifically* excluded by the user might be very
bad, so IMO it's better to prevent that from happening -- i.e. sharing
the same ERROR code that was there before.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: vignesh C <vignesh21(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(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 <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Skipping schema changes in publication
Date: 2026-04-22 09:54:28
Message-ID: CAJpy0uAX90WXUY4LDJfmKs4bWPn-OzFYi6grXJYh-Fdagb2w_w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Apr 20, 2026 at 5:43 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> Hi,
>
> When changing a table to UNLOGGED, tables that appear in publications
> via EXCEPT clauses (prexcept = true) are currently allowed, but their
> entries remain in pg_publication_rel.
>
> For example:
> postgres=# create table t1(c1 int);
> CREATE TABLE
> postgres=# create publication pub1 for all tables except (table t1);
> CREATE PUBLICATION
> postgres=# alter table t1 set unlogged;
> ALTER TABLE
> postgres=# \d t1
> Unlogged table "public.t1"
> Column | Type | Collation | Nullable | Default
> --------+---------+-----------+----------+---------
> c1 | integer | | |
> Except publications:
> "pub1"
>
> Since UNLOGGED tables are not supported in publications, this leaves
> stale catalog entries. This patch removes such entries from
> pg_publication_rel when the table is changed to UNLOGGED, and emits a
> NOTICE to inform the user.
>
> Another option considered was to throw an error when setting such
> tables to UNLOGGED. However, allowing the operation was preferred,
> since UNLOGGED tables do not generate WAL and are not replicated
> anyway, so blocking the operation would be unnecessarily restrictive.
>
> Attached patch has the changes for the same.
>

The main concern of removal table form EXCEPT-list is that once the
table is changed back to LOGGED, there is no internal way to add it to
the EXCEPT list again.

OTOH, raising an ERROR does not seem like a good solution either. When
a user converts a table to UNLOGGED, they are effectively excluding it
from publications. Therefore, throwing an error for the purpose that
"table is part of EXCEPT, cannot convert it to UNLOGGED" does not
appear appropriate, since both actions ultimately exclude the table
from publication. I think we can keep the current behavior unchanged
as it causes no harm.

Alternatively, if we want to remove the table from the EXCEPT list:
1) may be a WARNING is better?
2) the error message can be improved; the current one ([1]) seems uninformative.
3) And we can also add DETAIL saying add it to EXCEPT list manually if
needed later(something on this line).

Thoughts?

[1]:
+ ereport(NOTICE,
+ errmsg("relation \"%s\" removed from publication \"%s\" due to being
changed to UNLOGGED",
+ RelationGetRelationName(rel), pubname));

thanks
Shveta


From: "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>
Cc: Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Skipping schema changes in publication
Date: 2026-04-22 10:02:56
Message-ID: TYRPR01MB1419559BE4B38E6EF24EF84BA942D2@TYRPR01MB14195.jpnprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wednesday, April 22, 2026 5:54 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> On Mon, Apr 20, 2026 at 5:43 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> >
> > Hi,
> >
> > When changing a table to UNLOGGED, tables that appear in publications
> > via EXCEPT clauses (prexcept = true) are currently allowed, but their
> > entries remain in pg_publication_rel.
> >
> > For example:
> > postgres=# create table t1(c1 int);
> > CREATE TABLE
> > postgres=# create publication pub1 for all tables except (table t1);
> > CREATE PUBLICATION postgres=# alter table t1 set unlogged; ALTER TABLE
> > postgres=# \d t1
> > Unlogged table "public.t1"
> > Column | Type | Collation | Nullable | Default
> > --------+---------+-----------+----------+---------
> > c1 | integer | | |
> > Except publications:
> > "pub1"
> >
> > Since UNLOGGED tables are not supported in publications, this leaves
> > stale catalog entries. This patch removes such entries from
> > pg_publication_rel when the table is changed to UNLOGGED, and emits a
> > NOTICE to inform the user.
> >
> > Another option considered was to throw an error when setting such
> > tables to UNLOGGED. However, allowing the operation was preferred,
> > since UNLOGGED tables do not generate WAL and are not replicated
> > anyway, so blocking the operation would be unnecessarily restrictive.
> >
> > Attached patch has the changes for the same.
> >
>
> The main concern of removal table form EXCEPT-list is that once the table is
> changed back to LOGGED, there is no internal way to add it to the EXCEPT list
> again.
>
> OTOH, raising an ERROR does not seem like a good solution either. When a
> user converts a table to UNLOGGED, they are effectively excluding it from
> publications. Therefore, throwing an error for the purpose that "table is part
> of EXCEPT, cannot convert it to UNLOGGED" does not appear appropriate,
> since both actions ultimately exclude the table from publication. I think we
> can keep the current behavior unchanged as it causes no harm.

I also personally prefer keeping the current behavior, as there is no harm in
doing so, and I'm not sure whether reporting one more ERROR would make users
happy.

Best Regards,
Hou zj


From: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
To: "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-04-22 11:32:01
Message-ID: CAA4eK1LvFapjAoDuFmpNi3yjiydk_K5d_QHK=gbiDJNqJOU=2A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, Apr 22, 2026 at 3:33 PM Zhijie Hou (Fujitsu)
<houzj(dot)fnst(at)fujitsu(dot)com> wrote:
>
> On Wednesday, April 22, 2026 5:54 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> > On Mon, Apr 20, 2026 at 5:43 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > >
> > > Hi,
> > >
> > > When changing a table to UNLOGGED, tables that appear in publications
> > > via EXCEPT clauses (prexcept = true) are currently allowed, but their
> > > entries remain in pg_publication_rel.
> > >
> > > For example:
> > > postgres=# create table t1(c1 int);
> > > CREATE TABLE
> > > postgres=# create publication pub1 for all tables except (table t1);
> > > CREATE PUBLICATION postgres=# alter table t1 set unlogged; ALTER TABLE
> > > postgres=# \d t1
> > > Unlogged table "public.t1"
> > > Column | Type | Collation | Nullable | Default
> > > --------+---------+-----------+----------+---------
> > > c1 | integer | | |
> > > Except publications:
> > > "pub1"
> > >
> > > Since UNLOGGED tables are not supported in publications, this leaves
> > > stale catalog entries. This patch removes such entries from
> > > pg_publication_rel when the table is changed to UNLOGGED, and emits a
> > > NOTICE to inform the user.
> > >
> > > Another option considered was to throw an error when setting such
> > > tables to UNLOGGED. However, allowing the operation was preferred,
> > > since UNLOGGED tables do not generate WAL and are not replicated
> > > anyway, so blocking the operation would be unnecessarily restrictive.
> > >
> > > Attached patch has the changes for the same.
> > >
> >
> > The main concern of removal table form EXCEPT-list is that once the table is
> > changed back to LOGGED, there is no internal way to add it to the EXCEPT list
> > again.
> >
> > OTOH, raising an ERROR does not seem like a good solution either. When a
> > user converts a table to UNLOGGED, they are effectively excluding it from
> > publications. Therefore, throwing an error for the purpose that "table is part
> > of EXCEPT, cannot convert it to UNLOGGED" does not appear appropriate,
> > since both actions ultimately exclude the table from publication. I think we
> > can keep the current behavior unchanged as it causes no harm.
>
> I also personally prefer keeping the current behavior, as there is no harm in
> doing so, and I'm not sure whether reporting one more ERROR would make users
> happy.
>

+1.

--
With Regards,
Amit Kapila.


From: vignesh C <vignesh21(at)gmail(dot)com>
To: "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>
Cc: shveta malik <shveta(dot)malik(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Shlok Kyal <shlok(dot)kyal(dot)oss(at)gmail(dot)com>, Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, YeXiu <1518981153(at)qq(dot)com>, Ian Lawrence Barwick <barwick(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Skipping schema changes in publication
Date: 2026-04-23 04:50:08
Message-ID: CALDaNm2-m31TLX25Y2y_PvANQMRij=fkK-JS5dFzKSVVtu1MCw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Lists: pgsql-hackers

On Wed, 22 Apr 2026 at 15:33, Zhijie Hou (Fujitsu)
<houzj(dot)fnst(at)fujitsu(dot)com> wrote:
>
> On Wednesday, April 22, 2026 5:54 PM shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
> > On Mon, Apr 20, 2026 at 5:43 PM vignesh C <vignesh21(at)gmail(dot)com> wrote:
> > >
> > > Hi,
> > >
> > > When changing a table to UNLOGGED, tables that appear in publications
> > > via EXCEPT clauses (prexcept = true) are currently allowed, but their
> > > entries remain in pg_publication_rel.
> > >
> > > For example:
> > > postgres=# create table t1(c1 int);
> > > CREATE TABLE
> > > postgres=# create publication pub1 for all tables except (table t1);
> > > CREATE PUBLICATION postgres=# alter table t1 set unlogged; ALTER TABLE
> > > postgres=# \d t1
> > > Unlogged table "public.t1"
> > > Column | Type | Collation | Nullable | Default
> > > --------+---------+-----------+----------+---------
> > > c1 | integer | | |
> > > Except publications:
> > > "pub1"
> > >
> > > Since UNLOGGED tables are not supported in publications, this leaves
> > > stale catalog entries. This patch removes such entries from
> > > pg_publication_rel when the table is changed to UNLOGGED, and emits a
> > > NOTICE to inform the user.
> > >
> > > Another option considered was to throw an error when setting such
> > > tables to UNLOGGED. However, allowing the operation was preferred,
> > > since UNLOGGED tables do not generate WAL and are not replicated
> > > anyway, so blocking the operation would be unnecessarily restrictive.
> > >
> > > Attached patch has the changes for the same.
> > >
> >
> > The main concern of removal table form EXCEPT-list is that once the table is
> > changed back to LOGGED, there is no internal way to add it to the EXCEPT list
> > again.
> >
> > OTOH, raising an ERROR does not seem like a good solution either. When a
> > user converts a table to UNLOGGED, they are effectively excluding it from
> > publications. Therefore, throwing an error for the purpose that "table is part
> > of EXCEPT, cannot convert it to UNLOGGED" does not appear appropriate,
> > since both actions ultimately exclude the table from publication. I think we
> > can keep the current behavior unchanged as it causes no harm.
>
> I also personally prefer keeping the current behavior, as there is no harm in
> doing so, and I'm not sure whether reporting one more ERROR would make users
> happy.

Thanks Hou-san, Amit, and Shveta for your inputs. Based on the
feedback, let's keep the current behavior unchanged

Regards,
Vignesh