| From: | PG Bug reporting form <noreply(at)postgresql(dot)org> |
|---|---|
| To: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Cc: | 303677365(at)qq(dot)com |
| Subject: | BUG #19820: ANALYZE can store empty (0-dimensional) stavalues that the statistics import functions refuse to res |
| Date: | 2026-10-30 06:58:56 |
| Message-ID: | 19820-5ee0f95d22b7366a@postgresql.org |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
The following bug has been logged on the website:
Bug reference: 19820
Logged by: chunling qin
Email address: 303677365(at)qq(dot)com
PostgreSQL version: Unsupported/Unknown
Operating system: Linux (TencentOS 4.4, x86_64)
Description:
Hello,
On current 20devel, ANALYZE deliberately stores an empty (zero-dimensional)
array -- not NULL -- in stavalues whenever a statistics slot has no content
to record (get_attstatsslot() raises an internal error on NULL stavalues,
so NULL was never an option). Three producers do this:
- compute_range_stats(): range_length_histogram, when fewer than two
sampled ranges are non-empty (one-row table, mostly-empty ranges,
or a mostly-NULL range column);
- compute_tsvector_stats(): most_common_elems, when every sampled
tsvector has no lexemes (all ''::tsvector);
- compute_array_stats(): most_common_elems, when every sampled array
is the empty array '{}' .
The import side, however, requires a one-dimensional array:
statatt_build_stavalues() (src/backend/statistics/stat_utils.c:620-630)
rejects ARR_NDIM != 1. So the statistics that ANALYZE just wrote cannot be
restored by the import functions, and the roundtrip silently drops them.
Reproducer (self-contained; attribute path):
CREATE TABLE e1 (tv tsvector, ia int[]) WITH (autovacuum_enabled =
false);
INSERT INTO e1 SELECT ''::tsvector, '{}'::int[] FROM generate_series(1,
50) g;
ANALYZE e1;
-- what ANALYZE stored (pg_stats exposes it just fine):
-- most_common_elems = {} (zero-dimensional)
-- most_common_elem_freqs = {0.02,0.02,0}
-- feeding those exact values back is rejected:
SELECT pg_restore_attribute_stats('schemaname', 'public', 'relname',
'e1',
'attname', 'tv', 'inherited', false,
'most_common_elems', '{}',
'most_common_elem_freqs', '{0.02,0.02,0}');
-- WARNING: "most_common_elems" must be a one-dimensional array
-- (returns false; the slot is dropped, together with range_empty_frac
-- when the range producer is involved)
The extended-statistics path fails the same way and even less gracefully:
pg_restore_extended_stats() reports
WARNING: could not parse "exprs": invalid element in expression -N
HINT: range_length_histogram/range_empty_frac/range_bounds_histogram
must be all either strings or all nulls
and drops the whole expression's statistics (including null_frac and
avg_width), not just the offending slot.
Expected: what ANALYZE writes, the import functions should accept back --
a zero-dimensional array is representable in the function's input syntax,
and it is what ANALYZE itself produces. Alternatively, if 0-dim input is
to stay unsupported, ANALYZE should not write it in the first place; the
current combination means every statistics roundtrip (any consumer that
encodes statistics as pg_restore_*() calls, e.g. pg_dump's statistics
export or pg_upgrade) silently loses these slots.
For reference, on 18.6 the same ANALYZE does not produce these slots at
all for the tsvector/array producers (older behavior), so the asymmetry
between producer and consumer is new with the 20devel behavior.
Reproduced on:
- PostgreSQL 20devel (snapshot of 2026-10-27, x86_64-pc-linux-gnu);
attribute and extended paths, re-runs after DROP and from fresh
sessions give identical results.
A draft fix location would be statatt_build_stavalues()
(src/backend/statistics/stat_utils.c): accept ARR_NDIM == 0 for the
element-array slots, mirroring what the producers write.
Regards,
Chunling Qin
| From | Date | Subject | |
|---|---|---|---|
| Next Message | PG Bug reporting form | 2026-10-30 07:01:30 | BUG #19821: pg_restore_attribute_stats() accepts an unsorted scalar histogram_bounds, producing badly wrong row |
| Previous Message | PG Bug reporting form | 2026-10-30 06:55:38 | BUG #19819: Foreign key DDL can fail with internal errors (XX000) from elog(): "key columns are not both collata |