Dump statistic issue with index on expressions

First seen: 2026-02-25 16:37:24+00:00 · Messages: 4 · Participants: 2

Latest Update

2026-06-01 · claude-opus-4-6

Dump Statistic Issue with Index on Expressions — May 2026 Summary

Overview

A reported bug in pg_dump --statistics-only (new in PostgreSQL 18) involving cross-index attribute name leakage was investigated and ultimately determined to be not reproducible on vanilla PostgreSQL. The issue is specific to forks that generate pg_statistic records for non-expression indexes.

The Bug

When a table has both an expression index and a subsequent plain index, pg_dump --statistics-only could fail with:

pg_dump: error: could not find index attname "source_system"

The root cause: indAttNames/nindAttNames fields are only populated for expression indexes during the index iteration in the stats-dumping path. If a plain index is processed afterward, it inherits stale pointers from the prior expression index, causing attribute name lookup failures.

Key Finding

Alexander Korotkov could not reproduce the error and identified why: in vanilla PostgreSQL, dumpRelationStats_dumper() only iterates indexes that have pg_statistic entries, which are exclusively expression indexes (controlled by the if (indexInfo->ii_Expressions != NIL && va_cols == NIL) check in do_analyze_rel()). Plain indexes never reach the code that reads the stale fields.

Maksim Melnikov confirmed this after investigation — the bug manifests only in Postgres Pro's fork, which generates statistics for additional index types beyond expression indexes.

Current Status

The thread concluded in a "nice-to-have defensive fix" state. The code pattern (conditionally populating per-iteration fields without clearing them) is acknowledged as latent-buggy and "prone to bugs," but since it cannot be triggered in vanilla PostgreSQL, there is no regression urgency. Whether to commit the defensive cleanup remains a code-quality judgment call.

Gap Identified

The statistics-dump feature lacks regression test coverage for the combination of expression indexes and plain indexes on the same table — a gap that could mask future issues if the iteration logic changes.

History (1 prior analysis)
2026-06-01 · claude-opus-4-6

Committer Decision: Defensive Fix Will Be Committed and Backpatched

Alexander Korotkov has made the final decision on this thread: he will push the defensive fix and backpatch it, pending the release freeze being lifted.

This is a brief but definitive resolution message. The key takeaway is that despite the bug not being reproducible on vanilla PostgreSQL, Korotkov has decided the code-quality argument is sufficient to warrant committing the fix — and importantly, backpatching it (presumably to PG18 where the statistics dump feature was introduced). This is slightly more than a "nice-to-have" since backpatching signals he considers the latent inconsistency worth fixing in stable branches, likely because downstream forks or future changes to index statistics could expose the bug.