Hi Tender,
> On Jul 27, 2026, at 19:34, Tender Wang <[email protected]> wrote:
>
> I tried the following:
>
> diff --git a/src/backend/partitioning/partprune.c
> b/src/backend/partitioning/partprune.c
> index e7c318bbcac..96649580e6f 100644
> --- a/src/backend/partitioning/partprune.c
> +++ b/src/backend/partitioning/partprune.c
> @@ -3170,6 +3170,8 @@ get_matching_range_bounds(PartitionPruneContext
> *context,
> * end up adding the first bound's
> offset, that is, 0.
> */
> result->bound_offsets =
> bms_make_singleton(off + 1);
> + if (off == boundinfo->default_index)
> + result->scan_default = true;
> }
>
> return result;
>
> This time all cases in regression passed.
> Any thoughts?
>
> --
> Thanks,
> Tender Wang
Thanks for working on this. I may be missing something, but `off`
indexes range-bound datums while `default_index` is a partition index,
so I am not sure the two can be compared. With that patch I still get a
wrong result:
```sql
CREATE TABLE r (a int) PARTITION BY RANGE (a);
CREATE TABLE r1 PARTITION OF r FOR VALUES FROM (0) TO (10);
CREATE TABLE r2 PARTITION OF r FOR VALUES FROM (20) TO (30);
CREATE TABLE rd PARTITION OF r DEFAULT;
INSERT INTO r VALUES (5), (35);
SELECT count(*) FROM r WHERE a IS NOT NULL AND a IN (5, 35);
```
Here `default_index` is 2 but `off` is 3 for 35, so `scan_default` stays
false, `rd` is pruned and the query returns 1 instead of 2.
I agree with Jacob that the problem is in the `nvalues == 0` path. For
35, the `IN` step keeps a `-1` offset, but the `IS NOT NULL` step
removes that same offset. Their intersection therefore loses 35 and
prunes the default partition. If the `IS NOT NULL` step keeps all
offsets, `get_matching_partitions()` can later turn the surviving `-1`
offset into a default-partition scan:
```diff
diff --git a/src/backend/partitioning/partprune.c
b/src/backend/partitioning/partprune.c
index e7c318bbcac..48d16ebb4fb 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -3031,15 +3031,7 @@ get_matching_range_bounds(PartitionPruneContext *context,
*/
if (nvalues == 0)
{
- /* ignore key space not covered by any partitions */
- if (partindices[minoff] < 0)
- minoff++;
- if (partindices[maxoff] < 0)
- maxoff--;
-
result->scan_default = partition_bound_has_default(boundinfo);
- Assert(partindices[minoff] >= 0 &&
- partindices[maxoff] >= 0);
result->bound_offsets = bms_add_range(NULL, minoff, maxoff);
return result;
```
The reported cases and the example above behave as expected with this,
and `make check` passes.
--
Best regards,
Chengpeng Yan