Re: BUG #19597: getQuadrant: impossible case is reachable - Mailing list pgsql-bugs

From Ayush Tiwari
Subject Re: BUG #19597: getQuadrant: impossible case is reachable
Date
Msg-id CAJTYsWX4xaFpk+nC_o8JCSOT9Rk_3VBr3Tyec+F4UDMQEnQo1w@mail.gmail.com
Whole thread
In response to Re: BUG #19597: getQuadrant: impossible case is reachable  (John Naylor <johncnaylorls@gmail.com>)
List pgsql-bugs
Hi,

On Tue, 29 Sept 2026 at 19:09, John Naylor <johncnaylorls@gmail.com> wrote:
>
> On Mon, Aug 3, 2026 at 4:22 AM Andrey Rachitskiy <pl0h0yp1@gmail.com> wrote:
> > The approach looks right to me: keep the fuzzy arms, fall back to exact comparisons for the finite gap, and leave
the
> > elog for NaN.
> >
> > Here is a suggested v2 on top of your patch.
>
> Note: "on top of" implies applying both -- v1 and then v2. v2 is
> independent, and CI applies only the latest.
>
> "not mutually exhaustive near some power-of-two boundaries"
>
> The reporter stumbled across something interesting, but you actually
> don't need to be near a boundary:
>
> drop table if exists g2;
> create table g2(p point);
> insert into g2 select point(10000000000 + i* 0.001, 5)
> from generate_series(1,3000) i;
> create index on g2 using spgist(p);
> ERROR:  getQuadrant: impossible case
>
> Note also that this doesn't need a separate insert. I found on master
> and REL_18_STABLE that the reporter's case didn't need one either --
> the error happened for me already when building the index.
>
> What I think is happening (from rubber-ducking with Claude):
> picksplit() calculates the centroid as the mean of a page of points.
> For this binade [2^33, 2^34), where both 17179869183.999998 and
> 10000000000 are found, the error happens if any point on that page is
> exactly 1 ulp (unit in the last place) from the centroid, or 1.9e-6.
> This is because this ulp is between EPSILON and 2*EPSILON.  A point
> exactly 1 ulp from the centroid is then more than EPSILON away, so
> FPeq is false. But centroid +/- EPSILON rounds onto that point, so
> FPgt and FPlt are false too. Other binades have similar gaps, but it's
> probably harder to use them to reach this elog from SQL.
>
> > 1. Write the exact fallback as y-then-x checks, which I find a bit easier to match to the quadrant diagram and the
axistie-breaking  rule. 
>
> + if (tst->y > centroid->y)
> + return (tst->x >= centroid->x) ? 1 : 4;
> + if (tst->y < centroid->y)
> + return (tst->x >= centroid->x) ? 2 : 3;
> + if (tst->y == centroid->y)
> + return (tst->x >= centroid->x) ? 1 : 3;
>
> I preferred the style of Ayush's patch. -- this looks really different
> from the coding for the fuzzy case. Let's make the exact stanza
> similar to the fuzzy stanza, including testing y before x.

Thanks a lot for the review, John!

Attaching v3 with updated test case and earlier fuzzy comparisons.

Regards,
Ayush

Attachment

pgsql-bugs by date:

Previous
From: Ross Burton
Date:
Subject: Re: BUG #19727: pg-combinebackup fails to link
Next
From: Tom Lane
Date:
Subject: Re: BUG #19727: pg-combinebackup fails to link