On Fri, Sep 4, 2026 at 9:00 PM Noah Misch <[email protected]> wrote: > > On Thu, Nov 20, 2025 at 03:09:36PM -0800, Masahiko Sawada wrote: > > Pushed. > > This became commit 266543a. It doesn't account for the publisher version, so > replicating v18->v19 w/ publish_via_partition_root fails at tablesync w/ > "ERROR: cannot copy from partitioned table".
Good catch. I've attached the patch to fix it. > I think commit 266543a also changes the behavior w/ foreign table partitions. > A v19 subscriber will fail w/ "cannot copy from foreign table", whereas an > older subscriber would have completed tablesync but handled no further foreign > table changes. This consequence of 266543a is a net good, since the v18 > subscriber behavior is mostly a bug. Let's keep it. If someone really needs > the v18 subscriber behavior, adding a no-op row filter achieves that. Agreed. Regards, -- Masahiko Sawada Amazon Web Services: https://aws.amazon.com
From c9f09d70b02b95e929261d0a293c692e7247fc2f Mon Sep 17 00:00:00 2001 From: Masahiko Sawada <[email protected]> Date: Tue, 8 Sep 2026 10:18:13 -0700 Subject: [PATCH v1] Fix tablesync failure for partitioned tables on older publishers. Commit 266543a made initial table synchronization use "COPY table TO" for a partitioned table, but decided that from the relation kind alone. A partitioned table is only accepted there since v19, so a v19 subscriber replicating from an older publisher with publish_via_partition_root failed at table sync. Check the publisher version, and fall back to the "COPY (SELECT ...) TO" variant otherwise. Backpatch to v19, where 266543a changed the initial table synchronization. Reported-by: Noah Misch <[email protected]> Reviewed-by: Discussion: https://postgr.es/m/[email protected] Backpatch-through: 19 --- src/backend/replication/logical/tablesync.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c index e5101997cd3..4015e861a64 100644 --- a/src/backend/replication/logical/tablesync.c +++ b/src/backend/replication/logical/tablesync.c @@ -1084,6 +1084,7 @@ copy_table(Relation rel) ParseState *pstate; List *options = NIL; bool gencol_published = false; + int server_version = walrcv_server_version(LogRepWorkerWalRcvConn); /* Get the publisher relation info. */ fetch_remote_table_info(get_namespace_name(RelationGetNamespace(rel)), @@ -1100,9 +1101,14 @@ copy_table(Relation rel) /* Start copy on the publisher. */ initStringInfo(&cmd); - /* Regular or partitioned table with no row filter or generated columns */ - if ((lrel.relkind == RELKIND_RELATION || lrel.relkind == RELKIND_PARTITIONED_TABLE) - && qual == NIL && !gencol_published) + /* + * Regular or partitioned table with no row filter or generated columns. + * + * "COPY table TO" on a partitioned table is supported since v19. + */ + if ((lrel.relkind == RELKIND_RELATION || + (lrel.relkind == RELKIND_PARTITIONED_TABLE && server_version >= 190000)) && + qual == NIL && !gencol_published) { appendStringInfo(&cmd, "COPY %s", quote_qualified_identifier(lrel.nspname, lrel.relname)); @@ -1182,8 +1188,7 @@ copy_table(Relation rel) * Prior to v16, initial table synchronization will use text format even * if the binary option is enabled for a subscription. */ - if (walrcv_server_version(LogRepWorkerWalRcvConn) >= 160000 && - MySubscription->binary) + if (server_version >= 160000 && MySubscription->binary) { appendStringInfoString(&cmd, " WITH (FORMAT binary)"); options = list_make1(makeDefElem("format", -- 2.55.0
