PostgreSQL 18.4: pg_restore_relation_stats() accepts reltuples = Infinity and writes non-finite catalog stats
- PostgreSQL 18.4 (Docker image
postgres:18.4)
Docker on Linux/macOS (tested via a single container repro script)
pg_restore_relation_stats() accepts Infinity::real for the reltuples argument and writes that value into pg_class.reltuples.
After that, planner estimates become pathological (very large row estimates), until a later ANALYZE rewrites reltuples to a finite value.
The function currently guards reltuples < -1.0, but does not reject non-finite float values (Infinity, -Infinity, NaN).
This reproducer is about the validation gap itself (non-finite catalog statistics are accepted).
It intentionally injects non-finite input through pg_restore_relation_stats() to prove acceptance/persistence of invalid stats values. It does not prove that this is the only ingress path by which production environments may reach the same state.
- Start PostgreSQL 18.4 in Docker.
- Create a regular table and run
ANALYZEto establish finite baseline stats. - Execute:
SELECT pg_restore_relation_stats('schemaname','public','relname','t','reltuples','Infinity'::real);
- Confirm:
SELECT reltuples::text FROM pg_class WHERE oid = 'public.t'::regclass;
- Inspect planner output (
EXPLAIN SELECT * FROM t;). - Run
ANALYZE t;and confirmreltuplesreturns to finite.
From the attached repro.sh:
pg_restore_relation_stats(...)returnstpg_class.reltuplesbecomesInfinity- Planner row estimate for a plain table scan becomes extremely large (clamped high estimate)
- Running
ANALYZErestores finitereltuples
pg_restore_relation_stats() should reject non-finite values for reltuples (at least Infinity, -Infinity, NaN) with a warning/error similar to existing range validation.
No non-default server configuration required for this reproducer.
repro.sh- one-command Docker reproducerscript.log- generated byrepro.sh(psqloutput)postgres.log- generated byrepro.sh(container logs)