Hi Ewan, Ewan Young <[email protected]> 于2026年8月6日周四 18:47写道: > > Hi, > > Issue still happens on master as of 9b917a93116, i.e. with 709dfd27f14 > already applied. It is a different instance of the same defect, in another > branch of the same function, and it silently returns wrong results. > > CREATE TABLE t (a int, b int) PARTITION BY RANGE (a, b); > CREATE TABLE t1 PARTITION OF t FOR VALUES FROM (13, 0) TO (19, MAXVALUE); > CREATE TABLE td PARTITION OF t DEFAULT; > INSERT INTO t VALUES (32, 5); > > SELECT count(*) FROM t WHERE a = 32; -- 1, correct > SELECT count(*) FROM t WHERE a = 32 AND b >= -7; -- 0, should be 1
Nice catch. > > Adding a qual that is true for every matching row makes the row disappear; > the plan is a One-Time Filter: false. It takes a multi-column range key, a > bound unbounded in a trailing key but finite in the first key, and a query > constraining all key columns - with nvalues < partnatts, > get_matching_range_bounds() sets scan_default up front, which masks it. > DELETE and UPDATE silently skip rows as well, run-time pruning is affected, > and FROM (13, MINVALUE) is the mirror image. A layout that hits this in > the wild is RANGE (tenant_id, ts) with FROM (N, MINVALUE) TO (N, MAXVALUE) > per tenant plus a default partition. > > At the end of get_matching_range_bounds() two adjustments drop the extreme > bound offset when no partition covers the key space beyond it: > > int lastkey = nvalues - 1; > > if (boundinfo->kind[maxoff - 1][lastkey] == > PARTITION_RANGE_DATUM_MAXVALUE) > maxoff--; > > Only a bound unbounded in its *first* key has no key space beyond it. > TO (19, MAXVALUE) merely means "unbounded within a = 19"; above it is real > key space owned by the default partition. Dropping the offset also drops > the last signal that the default has to be scanned: since 489247b0e615 > get_matching_partitions() derives that from a returned offset whose > partindices[] entry is -1, and scan_default is not set on this path. Yes, I came to the same conclusion. > 0001 tests the first key of the bound instead of the last key of the lookup > value; the code change is two lines. I did not delete the blocks the way > 709dfd27f14 did, because when the first key really is unbounded there is > nothing beyond it and removing them would scan the default partition for no > reason. Tests cover a trailing MAXVALUE, the MINVALUE mirror, a genuinely > unbounded first key, and the no-default case; the last two are unchanged by > the patch, on purpose. The fix WFM. I tweaked the comments a little, as in the attached v2-0001 patch. Others look good to me. -- Thanks, Tender Wang
v2-0001-Don-t-prune-the-default-partition-for-bounds-unbo.patch
Description: Binary data
