Skip to content

1.5.0

Choose a tag to compare

@palermo-git palermo-git released this 03 Nov 02:07

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.attnames in physical column order; PG12–15 explicitly excludes generated columns, and pre-12 queries never reference attgenerated. pglogical discovery honors pglogical.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_conflict error 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-NULL set_row_filter predicates 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/0 is removed; callers supply the probed version to table_columns/1. Discovery rows grow from six to seven elements with row_filter. keyset_chunk/5 and keyless_scan/3 accept that predicate; their shorter forms remain available. pglogical callers of table_columns_for/3 must 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 = stored includes 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_columns error 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_filter text (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 attnames may 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: attnames plus pg_attribute cannot recover whether each list was explicit. The stream fails closed; no additional column is exposed.