Hello Tomas,
> On 27. Jul 2026, at 14:06, Jan Nidzwetzki <[email protected]> wrote: > >> On 24. Jul 2026, at 15:55, Tomas Vondra <[email protected]> wrote: [...] >>>> 4. Statistics import accepts Infinity and NaN >>>> --------------------------------------------- >>>> >>>> Finally, the reltuples argument of pg_restore_relation_stats() (and the >>>> shared relation_statistics_update_internal() path) is only validated >>>> with: >>>> >>>> if (reltuples < -1.0) /* relation_stats.c:126 */ >>>> { >>>> ereport(WARNING, ...); >>>> result = false; /* update skipped */ >>>> } > > [...] > >>>> We have not addressed this one in the attached patches, because >>>> rejecting non-finite values here is a slightly larger policy question >>>> (error vs. clamp-to -1). If there is agreement on the desired >>>> behavior, we are glad to propose a patch for this as well. >>>> >>> >>> OTOH this seems like something we might want to do, to validate and >>> reject clearly bogus values. >>> >> >> No opinion on this. But I was checking how we validate the values when >> importing stats, and I noticed relation_statistics_update_internal does >> this: >> >> if (reltuples < -1.0) >> { >> ereport(WARNING, >> (errcode(ERRCODE_INVALID_PARAMETER_VALUE), >> errmsg("argument \"%s\" must not be less than -1.0", >> "reltuples"))); >> result = false; >> } >> >> Isn't that a bit strange it's not (reltuplees < 0.0)? > > This caught my attention as well. From my understanding, -1.0 should be > allowed, since in 3d351d916b2 the value -1 was introduced as a sentinel > meaning "unknown / never analyzed". But we also allow values between > -1.0 and 0 here. I think the looseness below zero is harmless because > every reader treats negative as "unknown". As discussed upthread, here's the follow-up patch to validate and reject clearly bogus reltuples at import. Currently, the function relation_statistics_update_internal() validates the incoming reltuples only with if (reltuples < -1.0) { ereport(WARNING, ...); result = false; } This means that both Infinity and NaN values pass this test since neither is less than -1.0. As a result, non-finite values are accepted and stored in pg_class.reltuples. The patch rejects non-finite reltuples the same non-fatal way the existing out-of-range check does: ereport(WARNING), set result = false, and skip that field, so an otherwise-valid stats import (or pg_upgrade) still proceeds and only the bad value is dropped. It also adds a regression test to stats_import covering the rejected values (Infinity, -Infinity, NaN) and confirming that a legitimate -1 is still accepted. The statistics import functions are new in v18, so this applies to v18+. Best regards Jan
0001-Reject-non-finite-reltuples-in-the-statistics-import.patch
Description: Binary data
--- Jan Nidzwetzki PlanetScale Postgres Core Team
