Revision history for pg_checksums

1.2.0   2026-10-18

    - Add partitioned index support.  pg_index_physical_checksum() and
      pg_index_logical_checksum() now aggregate the checksums of all leaf
      indexes instead of returning NULL for the partitioned parent.  Each leaf
      contributes combine(leaf checksum, leaf OID) to an order-independent
      aggregate, and the parent OID is folded in at the end; logical
      aggregation does the same for B-tree leaves.
    - Add pg_table_content_checksum(regclass).  It does not require a primary
      key and does not include relation OIDs, so it can be used for tables
      without a PK and for content comparison across databases.  Duplicate
      rows are preserved by a sum-plus-count aggregate, and partitioned tables
      aggregate all leaf rows into the same accumulator.
    - Add the pg_checksums.strict GUC.  When enabled, database checksum
      functions fail if a relation cannot be checksummed (missing primary key,
      unsupported index access method, or a scan error) instead of silently
      skipping it.  The default remains false.  Strict errors release the
      per-relation internal subtransaction before propagating, so an exception
      handler can catch them safely.
    - Fix parallel scans to destroy the parallel context and leave parallel
      mode when a worker or the leader fails.  Previously an error caught by a
      PL/pgSQL exception block could leave the backend in parallel mode, making
      later RESET or nested parallel operations fail.
    - Existing checksum values are unchanged for non-partitioned relations;
      partitioned indexes change from NULL to an aggregated value, and the new
      content checksum has its own algorithm.

1.1.1   2026-10-18

    - Security: enforce SELECT privilege (and reject relations protected by
      row-level security) in pg_page_checksum(), pg_cell_checksum(),
      pg_tuple_*_checksum(), pg_table_*_checksum() and pg_index_*_checksum().
      Previously any user could compute checksums of any relation, including
      tables they could not read.
    - Security: the database-level functions are no longer SECURITY DEFINER.
      With SECURITY DEFINER, superuser() saw the owner and the superuser check
      could be bypassed by any user.  EXECUTE is now revoked from PUBLIC, and
      the extension can no longer be installed by a non-superuser.
    - Fix a server crash (signal 11) when pg_index_logical_checksum() was
      called on an SP-GiST index.  Logical index checksums are now B-tree
      only; Hash, GiST, GIN, SP-GiST and BRIN return NULL instead of
      returning a meaningless value.  Physical index checksums remain
      available for all supported access methods.
    - pg_page_checksum() now validates the block number.  A negative block
      number used to be interpreted as P_NEW and silently extended the
      relation; an out-of-range block is now an error.  The page is copied
      before pg_checksum_page() is called, so the shared pd_checksum field is
      never transiently zeroed in the buffer pool.
    - Validate relkinds, line pointers, tuple headers and page headers before
      following them.  A corrupted page or a bogus TID now produces a clean
      error instead of reading out of bounds.  pg_cell_checksum() and
      pg_tuple_logical_checksum() no longer read past PageGetMaxOffsetNumber.
    - Fix PG_RETURN_NULL() inside PG_TRY and mark locals modified between
      setjmp and longjmp as volatile in the tuple checksum functions.
    - Database scans now run each relation in an internal subtransaction.
      Errors release locks and buffer pins, are reported as a warning and no
      longer produce a silently partial checksum.  Cancellation and statement
      timeouts are propagated instead of being swallowed.  PostgreSQL 12-16
      prohibit internal subtransactions in parallel mode; there a relation
      error aborts a parallel database scan, while serial scans (workers = 0)
      and PostgreSQL 17+ still skip the relation with a warning.
    - Enter parallel mode before creating a parallel context and leave it
      after destroying it.  This fixes assertion failures in --enable-cassert
      builds and prevents the leader from starting nested parallel workers
      during a database scan.  Workers are also clamped by
      max_worker_processes, and the block-chunk end calculation no longer
      overflows.
    - Physical checksums of TOAST relations now hash their raw pages instead
      of misinterpreting toast tuples as heap tuples.  include_toast works
      independently of include_system, and logical database checksums skip
      TOAST relations (their content is covered by detoasting the parent
      table).  Shared catalogs are excluded from per-database checksums even
      when include_system is true.
    - Physical table checksums no longer include relpages/reltuples.  Those
      are planner statistics, not physical data: ANALYZE could change a
      physical checksum without any data change, and the implicit float4 to
      uint32 conversion was undefined for reltuples = -1.  Physical table and
      database checksums computed with 1.1.0 must be refreshed.
    - Tuple and table physical checksums no longer include the page LSN,
      pd_checksum and pd_flags.  Hint-bit-only changes made by a concurrent
      scan could change those fields, so serial and parallel scans of the same
      table could disagree.  They now include the relation's relfilenode and
      reltablespace, so VACUUM FULL, CLUSTER, REINDEX and SET TABLESPACE still
      change physical checksums.  Page-level checksums still hash the raw
      page bytes.
    - Skip unsupported index access methods in physical database scans
      instead of silently folding a zero checksum into the aggregate.
    - pg_index_physical_checksum() and pg_index_logical_checksum() return NULL
      for partitioned indexes until leaf-index aggregation is implemented.
    - Logical checksums are unchanged for the same data.  Physical checksums
      have intentionally changed: planner statistics and transient page
      metadata were removed, and relfilenode/reltablespace were added.  Any
      physical baseline computed with 1.1.0 must be refreshed.  Database
      checksums can also change when include_system/include_toast is used
      (shared catalogs and unsupported indexes are now handled correctly) or
      when a database contains non-B-tree indexes.
    - TAP tests are opt-in again (enable_tap_tests=yes), matching the README,
      and run_tests.sh no longer stops a server it did not start and no longer
      requires sudo unconditionally.

1.1.0   2026-10-17

    - Speed up the logical checksum paths considerably. The per-cell pg_type
      system cache lookup is gone, the primary key is looked up once per
      relation instead of once per tuple, and short-header varlenas are hashed
      in place instead of being detoasted into a fresh copy for every cell.
      Logical table checksums are up to ~180x faster on large tables; physical
      and utility functions are unchanged.
    - Fix a relcache reference leak in the parallel database scan: parallel
      workers cannot read the session's temporary tables, and the error that
      this raised left the relation open.
    - Database checksums no longer include temporary relations. They are
      session-local, and including them made the parallel result depend on how
      the work happened to be distributed. Checksums of persistent objects are
      unchanged, and the parallel and serial results now agree.
    - Initialise the relation and buffer variables used by the exception
      handler of pg_tuple_physical_checksum.
    - ALTER EXTENSION pg_checksums UPDATE TO '1.1.0' is a no-op: the SQL
      objects are unchanged.

1.0.0   2026-10-12

    - First public release on PGXN.
    - Checksum functions at six levels: page, cell, tuple, table, index and
      database, in physical and logical variants (cell level is logical only).
    - FNV-1a 32-bit implementation, with order-independent aggregation so that
      table, index and database checksums do not depend on scan order.
    - Parallel scans for table, index and database checksums, controlled by the
      pg_checksums.workers GUC.
    - Partitioned tables are aggregated over all leaf partitions.
    - Supports PostgreSQL 12, 13, 14, 15, 16, 17 and 18.
