Repository navigation
1.5.0
Snapshots now select the same columns and rows as the change stream. Full details in the CHANGELOG and ADR-0002. 1.5.1 restores table_columns/0 and the six-column table_columns_for/1 row shape that this release changed, so upgrade to 1.5.1. Published to Hex on 2026-10-10; this GitHub release was created afterward.
Security
-
Snapshot reads respect publication column lists. Initial and incremental snapshots no longer read columns outside the publication column list. PostgreSQL 15+ pgoutput discovery uses
pg_publication_tables.attnamesin physical column order; PG12–15 explicitly excludes generated columns, and pre-12 queries never referenceattgenerated. pglogical discovery honorspglogical.replication_set_table.set_att_list; wal2json retains all configured-table columns because it has no publication column-list facility. Conflicting multi-publication or replication-set column lists halt with the value-free:snapshot_column_list_conflicterror before any snapshot row is read or delivered. Identical lists are accepted, never combined into a broader list. Unpublished key columns are never added to the projection: incremental snapshots use the whole-table path when the complete primary key is unavailable. PostgreSQL refuses UPDATE/DELETE when a publication omits required replica-identity columns. -
Snapshot reads respect server row filters. Initial snapshots in both checkpoint modes, incremental keyset chunks, and whole-table windows select the same rows as INSERT changes. PG15+ publication predicates combine with OR only among publications with
pubinsert; an unfiltered INSERT publication removes the predicate. With no INSERT publication, no snapshot rows are delivered. pglogical 2.4.8 non-NULLset_row_filterpredicates combine with AND, even beside an unfiltered set. Predicate text comes only from server catalogs (pg_get_expr), parenthesized before composition. wal2json has table filters, not a server row-filter facility.
Changed
- Public discovery API changes require 1.5.0.
QueryBuilder.table_columns/0is removed; callers supply the probed version totable_columns/1. Discovery rows grow from six to seven elements withrow_filter.keyset_chunk/5andkeyless_scan/3accept that predicate; their shorter forms remain available. pglogical callers oftable_columns_for/3must supply the probed version. - Generated columns on PostgreSQL 12+: snapshot records now match stream records. A no-list publication omits generated columns from snapshots just as pgoutput does. On PG18,
publish_generated_columns = storedincludes stored generated columns in both. Users who previously consumed these columns only from snapshots must account for their omission or opt into PG18's stored mode.
Fixed
- A table with columns but no publishable projection halts with the typed
:snapshot_no_publishable_columnserror naming the table before snapshot delivery. Zero-column and all-dropped tables retain 1.4.2's empty reset. - Invalid explicit table identifiers preserve
:invalid_identifier; snapshot discovery reuses the already-probed server version and refuses an unprobed version.[:replicant, :pipeline, :halted]exposes the structural reason, including incremental snapshot column-list refusals. - Progress tokens contain PK bounds (row data) and
row_filtertext (publication configuration). Persist them without logging either. - Verification for this repair: live PostgreSQL 18.6 column/row parity; offline PG12–15 generated-column selection. PG12–15 and pglogical live regressions remain version/plugin-gated.
Known limitations
- PG15 dropped columns: identical effective
attnamesmay pass snapshot discovery while pgoutput rejects an explicit full live-column list combined with an implicit list. PG15 counts dropped attribute slots when collapsing a full list. This is documented only in ADR-0002:attnamespluspg_attributecannot recover whether each list was explicit. The stream fails closed; no additional column is exposed.