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.