Skip to content

Backport snapshot/restore fixes to v1.1.x (#906, #908, #909, #907, #910)#966

Merged
kvch merged 5 commits into
v1.1.xfrom
backport/snapshot-restore-fixes-v1.1.x
Jul 6, 2026
Merged

Backport snapshot/restore fixes to v1.1.x (#906, #908, #909, #907, #910)#966
kvch merged 5 commits into
v1.1.xfrom
backport/snapshot-restore-fixes-v1.1.x

Conversation

@kvch

@kvch kvch commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Backports the following snapshot/restore fixes from main to the v1.1.x release branch.

PR Commit Fix
#906 2cf967b Skip legacy public PL/pgSQL handler functions on snapshot restore
#908 5f1d6e3 Refresh materialized views after data restore
#909 bce8ea8 Use ONLY for CTID snapshot queries to exclude inherited child rows
#907 1b090aa Restore CLUSTER ON statements after their referenced indexes
#910 6b3bb8a Type int4range/int8range values before insert/COPY

kvch and others added 5 commits July 6, 2026 11:46
## Problem
Databases created on/upgraded through older PostgreSQL versions can
carry leftover `public.plpgsql_call_handler()` and
`public.plpgsql_validator(oid)` C-language function definitions that
point at `$libdir/plpgsql`. These are normally provided by the `plpgsql`
extension itself; restoring them as ordinary user functions on the
target conflicts/errors during a snapshot restore.

## Fix
`parseDump` now detects and skips these two legacy handler function
definitions while preserving all genuine user-defined functions.

## Testing
- Unit:
`TestSnapshotGenerator_parseDumpSkipsLegacyPublicPLPGSQLHandlers`
(confirms a normal `keep_me()` function survives)
- Integration: `Test_SnapshotToPostgres_SkipsLegacyPLPGSQLHandlers`
- `go test ./pkg/snapshot/generator/postgres/schema/pgdumprestore/...`

---
Cherry-picked from
[@danddanddand](https://github.com/danddanddand/pgstream)
(`fix/skip-legacy-plpgsql-handlers`).

---------

Co-authored-by: dand <daniel.dent@borderconnect.com>
(cherry picked from commit 2cf967b)
## Problem
pgstream dumps schema with materialized views created `WITH NO DATA`,
and matview contents are not part of the data copy. As a result,
restored materialized views were empty on the target. Additionally, a
unique index on a matview cannot be built until the matview has data,
and dependent matviews must be refreshed in dependency order.

## Fix
- Track materialized views while parsing the schema dump.
- Keep matview indexes with the view restore section (not the general
index section).
- Emit `REFRESH MATERIALIZED VIEW ... WITH DATA` statements (preserving
`\connect` context and creation order) and run them after table data has
been copied.

## Testing
- Unit:
`TestSnapshotGenerator_parseDumpMovesMaterializedViewIndexesToViews`,
`...RefreshesMaterializedViewsInCreationOrder`,
`...CreateSnapshotRefreshesMaterializedViewsAfterViews`
- Integration: `Test_SnapshotToPostgres_MaterializedViewRefresh`
- `go test ./pkg/snapshot/generator/postgres/schema/pgdumprestore/...`

---
Cherry-picked from
[@danddanddand](https://github.com/danddanddand/pgstream)
(`fix/refresh-materialized-views`).

---
**Update:** the refresh is now **opt-in** and disabled by default
(refreshing can be expensive on large views). Enable it with:
- YAML:
`source.postgres.snapshot.schema.pgdump_pgrestore.refresh_materialized_views:
true`
- Env: `PGSTREAM_POSTGRES_SNAPSHOT_REFRESH_MATERIALIZED_VIEWS=true`

---------

Co-authored-by: dand <daniel.dent@borderconnect.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
(cherry picked from commit 5f1d6e3)
)

## Problem
The CTID page-range data snapshot uses `SELECT * FROM <table> WHERE ctid
BETWEEN ...` and `SELECT MAX(ctid) FROM <table>`. For a
legacy-inheritance parent table (`CREATE TABLE ... INHERITS`), these
implicitly span the parent **plus all child heaps**, so CTIDs aren't
unique to the parent's storage: page ranges overlap and child rows get
copied through the parent (and again when the child is snapshotted on
its own).

## Fix
Add `ONLY` to the page-range and max-CTID queries so each snapshot is
confined to the selected table's own heap, matching pgstream's per-table
snapshot model.

Note: this is a no-op for plain tables and leaf partitions, and does not
affect declaratively partitioned parents (`relkind='p'`), which are
already excluded from this path by the `relkind='r'` filter in
`getTableInfo`.

## Testing
- Unit: `TestSnapshotQueriesDoNotIncludeInheritedRows`
- Integration:
`Test_SnapshotToPostgres_SelectedParentTableDoesNotCopyInheritedRows`
- `go test ./pkg/snapshot/generator/postgres/data/...`

---
Cherry-picked from
[@danddanddand](https://github.com/danddanddand/pgstream)
(`fix/snapshot-only-table-pages`).

---------

Co-authored-by: dand <daniel.dent@borderconnect.com>
(cherry picked from commit bce8ea8)
## Problem
`ALTER TABLE ... CLUSTER ON <index>` references an index. During
snapshot restore it could be emitted before the index was created,
causing the restore to fail.

## Fix
Route `ALTER TABLE ... CLUSTER ON ...` statements into the
indices/constraints restore phase so the referenced index always exists
first.

## Testing
- Unit: `TestSnapshotGenerator_parseDumpMovesClusterOnToConstraints`
(asserts CLUSTER ON is ordered after CREATE INDEX)
- Integration: `Test_SnapshotToPostgres_ClusteredIndex`
- `go test ./pkg/snapshot/generator/postgres/schema/pgdumprestore/...`

---
Cherry-picked from
[@danddanddand](https://github.com/danddanddand/pgstream)
(`fix/restore-cluster-after-indexes`).

---------

Co-authored-by: dand <daniel.dent@borderconnect.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
(cherry picked from commit 1b090aa)
## Problem
When an `int4range`/`int8range` value arrives as `pgtype.Range[any]`,
`pgx` cannot encode it to the binary wire format for the target column
(the bounds are untyped `any`), so inserts and bulk COPY fail.

## Fix
Normalize `int4range` and `int8range` values from `pgtype.Range[any]`
into typed `pgtype.Range[int32]` / `pgtype.Range[int64]` before
insert/COPY handling (`tstzrange` already had handling).

---
Cherry-picked from
[@danddanddand](https://github.com/danddanddand/pgstream)
(`fix/type-integer-range-values`).

Co-authored-by: dand <daniel.dent@borderconnect.com>
(cherry picked from commit 6b3bb8a)
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

⚠️ Note: Baseline coverage from v1.1.x branch is not available (artifact may be expired). Showing current coverage for changed files only.

Merging this branch will increase overall coverage

Impacted Packages Coverage Δ 🤖
github.com/xataio/pgstream/cmd/config 83.97% (+83.97%) 🌟
github.com/xataio/pgstream/pkg/snapshot/generator/postgres/data 78.48% (+78.48%) 🌟
github.com/xataio/pgstream/pkg/snapshot/generator/postgres/schema/pgdumprestore 89.22% (+89.22%) 🌟
github.com/xataio/pgstream/pkg/stream/integration 0.00% (ø)
github.com/xataio/pgstream/pkg/wal/processor/postgres 79.81% (+79.81%) 🌟

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/xataio/pgstream/cmd/config/config_env.go 87.15% (+87.15%) 288 (+288) 251 (+251) 37 (+37) 🌟
github.com/xataio/pgstream/cmd/config/config_yaml.go 87.38% (+87.38%) 206 (+206) 180 (+180) 26 (+26) 🌟
github.com/xataio/pgstream/pkg/snapshot/generator/postgres/data/pg_snapshot_generator.go 84.47% (+84.47%) 206 (+206) 174 (+174) 32 (+32) 🌟
github.com/xataio/pgstream/pkg/snapshot/generator/postgres/schema/pgdumprestore/snapshot_pg_dump_restore_generator.go 84.65% (+84.65%) 404 (+404) 342 (+342) 62 (+62) 🌟
github.com/xataio/pgstream/pkg/wal/processor/postgres/postgres_wal_dml_adapter.go 94.06% (+94.06%) 202 (+202) 190 (+190) 12 (+12) 🌟

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

Changed unit test files

  • github.com/xataio/pgstream/cmd/config/helper_test.go
  • github.com/xataio/pgstream/pkg/snapshot/generator/postgres/data/pg_snapshot_generator_test.go
  • github.com/xataio/pgstream/pkg/snapshot/generator/postgres/schema/pgdumprestore/snapshot_pg_dump_restore_generator_test.go
  • github.com/xataio/pgstream/pkg/stream/integration/snapshot_pg_integration_test.go
  • github.com/xataio/pgstream/pkg/wal/processor/postgres/postgres_wal_dml_adapter_bulk_test.go

@kvch kvch requested review from exekias and tsg July 6, 2026 09:54
@kvch kvch merged commit fe9a20d into v1.1.x Jul 6, 2026
8 checks passed
@kvch kvch deleted the backport/snapshot-restore-fixes-v1.1.x branch July 6, 2026 09:56
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