From c9801a03074d61ff0a03bfd07b55e0c16fc6a9ba Mon Sep 17 00:00:00 2001 From: Ayush Tiwari Date: Tue, 29 Sep 2026 20:08:30 +0530 Subject: [PATCH v3] Fix reachable getQuadrant() "impossible case" The fuzzy comparisons in getQuadrant() can leave a finite point neither above, below, nor horizontal to the centroid. In that case, building an SP-GiST quad tree index can raise the supposedly impossible error. Keep the existing fuzzy quadrant decisions, but fall back to four y-first exact comparisons when none match. These preserve the existing axis tie-breaking. Add an index-build reproducer using nearby large coordinates. It shows that no later INSERT is needed to reach the error. Author: Ayush Tiwari Reviewed-by: Andrey Rachitskiy Reviewed-by: Pierre Forstmann Reported-by: Michael Malis Discussion: https://postgr.es/m/19597-39c532e61d78dff6@postgresql.org Backpatch-through: 14 --- src/backend/access/spgist/spgquadtreeproc.c | 13 +++++++++++++ src/test/regress/expected/spgist.out | 6 ++++++ src/test/regress/sql/spgist.sql | 6 ++++++ 3 files changed, 25 insertions(+) diff --git a/src/backend/access/spgist/spgquadtreeproc.c b/src/backend/access/spgist/spgquadtreeproc.c index 946dabc4527..18204245a88 100644 --- a/src/backend/access/spgist/spgquadtreeproc.c +++ b/src/backend/access/spgist/spgquadtreeproc.c @@ -76,6 +76,19 @@ getQuadrant(Point *centroid, Point *tst) SPTEST(point_left, tst, centroid)) return 4; + /* + * Fuzzy comparisons can leave gaps for finite values. Fall back to + * exact comparisons with the same axis tie-breaking as above. + */ + if (tst->y >= centroid->y && tst->x >= centroid->x) + return 1; + if (tst->y < centroid->y && tst->x >= centroid->x) + return 2; + if (tst->y <= centroid->y && tst->x < centroid->x) + return 3; + if (tst->y > centroid->y && tst->x < centroid->x) + return 4; + elog(ERROR, "getQuadrant: impossible case"); return 0; } diff --git a/src/test/regress/expected/spgist.out b/src/test/regress/expected/spgist.out index 2e911285600..037e23fab2c 100644 --- a/src/test/regress/expected/spgist.out +++ b/src/test/regress/expected/spgist.out @@ -94,3 +94,9 @@ select box(point(i,j)) from generate_series(1,100,5) i, generate_series(1,10,5) j; -- leave this table around, to help in testing dump/restore +-- Check getQuadrant during index build with nearby large coords (bug #19597) +create table spgist_quad_fp_tbl(p point); +insert into spgist_quad_fp_tbl + select point(10000000000 + i * 0.001, 5) + from generate_series(1, 3000) i; +create index spgist_quad_fp_idx on spgist_quad_fp_tbl using spgist(p); diff --git a/src/test/regress/sql/spgist.sql b/src/test/regress/sql/spgist.sql index 4828ede68c3..cf76b2d61b2 100644 --- a/src/test/regress/sql/spgist.sql +++ b/src/test/regress/sql/spgist.sql @@ -89,3 +89,9 @@ select box(point(i,j)) from generate_series(1,100,5) i, generate_series(1,10,5) j; -- leave this table around, to help in testing dump/restore +-- Check getQuadrant during index build with nearby large coords (bug #19597) +create table spgist_quad_fp_tbl(p point); +insert into spgist_quad_fp_tbl + select point(10000000000 + i * 0.001, 5) + from generate_series(1, 3000) i; +create index spgist_quad_fp_idx on spgist_quad_fp_tbl using spgist(p); -- 2.34.1