Skip to content

fix: restore ALTER INDEX ... ATTACH PARTITION with indices and constraints - #1094

Merged
kvch merged 4 commits into
xataio:mainfrom
siriusfreak:fix/attach-partition-ordering
Aug 19, 2026
Merged

fix: restore ALTER INDEX ... ATTACH PARTITION with indices and constraints#1094
kvch merged 4 commits into
xataio:mainfrom
siriusfreak:fix/attach-partition-ordering

Conversation

@siriusfreak

Copy link
Copy Markdown
Contributor

Fixes the partitioned-index half of #1093.

The problem

parseDump classifies dump lines by prefix. ALTER INDEX … ATTACH PARTITION matches none of the special cases — it starts with ALTER INDEX, not ALTER TABLE or CREATE INDEX — so it falls through to default and lands in the filtered segment. That segment is restored before indicesAndConstraints, where the parent index is created, so every attach fails with relation does not exist. The error is bucketed as ignorable and never retried, and the parent index stays indisvalid = false on the target.

Why it is worth fixing beyond the index

An invalid index is not usable as a constraint either, so a partitioned table's PRIMARY KEY does not exist on the target. That means:

  • no replica identity for UPDATE/DELETE;
  • no conflict target for INSERT — buildOnConflictQuery returns "" when there are no primary key columns;
  • with strict_mode: false, those changes are dropped and the checkpoint advanced.

So a load that reports success leaves a table that silently stops replicating. We hit this on a JFrog Artifactory schema, where jfbus_events is partitioned; the only trace was one line of restore: N errors ignored.

The change

Route the statement into indicesAndConstraints, which puts it after the CREATE INDEX it depends on — pg_dump already emits the parent index first, so ordering within the segment is preserved. Kept narrow: no change to error classification, though as noted on the issue that is the reason both this and the extension case were invisible, and I would be glad to follow up separately if you want it.

Verification

Unit test added alongside the existing parseDump cases: it asserts the table attachment stays in filtered, the index attachment moves to indicesAndConstraints, and that it lands after the parent CREATE INDEX.

End to end, against the reproduction from #1093 — a partitioned table with a primary key and a secondary index, snapshotted into an empty target:

before after
ignored errors 5, incl. 4 × does not exist 1, no does not exist
pg_index WHERE NOT indisvalid jfbus_events_pkey, jfbus_events_topic_partition_event_id empty
rows 5000 5000

go test ./pkg/snapshot/... passes.

siriusfreak and others added 2 commits August 13, 2026 21:00
…aints

parseDump classifies dump lines by prefix, and `ALTER INDEX ... ATTACH
PARTITION` matches none of the special cases, so it falls through to the default
and lands in the filtered segment. That segment is restored before
indicesAndConstraints, where the parent index is created, so every attach fails
with "relation does not exist". The error is bucketed as ignorable and never
retried, leaving the parent index indisvalid on the target.

For a partitioned table's PRIMARY KEY that is more than a missing index: an
invalid index is not usable as a constraint, so the table has no key on the
target, hence no replica identity for UPDATE/DELETE and no conflict target for
INSERT — buildOnConflictQuery returns "" without primary key columns. With
strict_mode false those changes are then dropped and the checkpoint advanced,
so a load that reports success produces a table that silently stops
replicating.

Routing the statement into indicesAndConstraints puts it after the CREATE INDEX
it depends on, which pg_dump already emits first.

Verified against the reproduction in xataio#1093: a partitioned table with a primary
key and a secondary index, snapshotted into an empty target. Before, 5 ignored
errors and both partitioned indexes invalid; after, no "does not exist" errors,
`pg_index WHERE NOT indisvalid` empty, all rows present.
@kvch
kvch enabled auto-merge (squash) August 19, 2026 19:05
@kvch
kvch merged commit dfbaab8 into xataio:main Aug 19, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants