Skip to content

API-created publications silently skip partitioned table data #758

Description

@ttatsato

Bug report

  • I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

Describe the bug

crates/etl-api/src/data/publications.rs builds publication DDL using
FOR TABLE ONLY ... (and SET TABLE ONLY ... on update), which causes
two issues when partitioned tables are involved.

Bug 1: ONLY is only applied to the first table

In PostgreSQL grammar:

TABLE table_and_columns [, ... ]
table_and_columns := [ ONLY ] table_name [ * ] [ ( column_name [, ...] ) ] [ WHERE ( expression ) ]

ONLY is a per-table prefix, not a clause-wide modifier. Today the code emits:

  CREATE PUBLICATION p FOR TABLE ONLY t1, t2, t3 WITH (publish_via_partition_root = true);

…which is parsed as: ONLY t1, then t2 and t3 with descendants included.
Behavior is silently inconsistent depending on table order.

Relevant code:

  • create_publication — publications.rs:23-53
  • update_publication — publications.rs:55-79

Bug 2: ONLY and publish_via_partition_root = true are contradictory for partitioned roots

publish_via_partition_root = true is the supported configuration for partitioned tables in this project.
That validation tells users to set publish_via_partition_root = true, but the API-created publication uses FOR TABLE ONLY <partitioned_root>, which excludes the partitions from the publication entirely.

Result: even when pipeline.rs validates the publication as "correctly configured", changes on the underlying partitions are not replicated, because the partitions are not part of the publication.

This is invisible at create time and only manifests as missing data downstream.

To Reproduce

CREATE TABLE parent (id int, ts date) PARTITION BY RANGE (ts);
CREATE TABLE parent_p1 PARTITION OF parent FOR VALUES FROM ('2026-01-01') TO ('2026-02-01');

-- What the API emits today:
CREATE PUBLICATION p FOR TABLE ONLY parent
  WITH (publish_via_partition_root = true);

INSERT INTO parent VALUES (1, '2026-01-15');  -- routed to parent_p1

SELECT schemaname, tablename FROM pg_publication_tables WHERE pubname = 'p';
--   schemaname | tablename
--  ------------+-----------
--   public     | parent
--
-- parent_p1 is NOT in the publication, so its DML is not replicated,
-- even though publish_via_partition_root = true is set.

Expected behavior

My current thinking is to drop ONLY entirely from the publication creation/update paths. Rationale:
The publish_via_partition_root = true contract from #410 assumes partitions are part of the publication, which FOR TABLE <root> (without ONLY) gives us.

Screenshots

System information

Additional context

Affected sites:

  • create_publication — publications.rs:32
  • update_publication — publications.rs:63
  • (Will also need to be applied consistently to the new ADD/DROP/SET TABLE
    endpoints introduced in feat(etl-api): Add publication endpoints #748.)

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions