On Tue, Feb 10, 2026 at 11:11 PM vignesh C <[email protected]> wrote:
>
> On Tue, 10 Feb 2026 at 11:35, shveta malik <[email protected]> wrote:
> >
> > On Mon, Feb 9, 2026 at 11:52 AM David G. Johnston
> > <[email protected]> wrote:
> > >
> > > On Sunday, February 8, 2026, Amit Kapila <[email protected]> wrote:
> > >>
> > >> On Mon, Feb 9, 2026 at 6:41 AM Peter Smith <[email protected]> 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


Reply via email to