BUG #19761: btree_gist: "cannot subtract infinite dates" when inserting 'infinity' into a GiST index on date

Started by PG Bug reporting form10 days ago4 messagesbugs
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

appliessuccessCI history

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t254211
psql -h localhost -U postgres

Built from patchset v2 (message #2), October 24, 2026 at 10:02 AM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t254211_2 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t254211_2 && git checkout t254211_2

Patchset v2 (message #2) is on t254211_2

Jump to latest
#1PG Bug reporting form
noreply@postgresql.org

The following bug has been logged on the website:

Bug reference: 19761
Logged by: Alperen Keles
Email address: alpkeles99@gmail.com
PostgreSQL version: 18.6
Operating system: macOS 26 arm64 (also Ubuntu 24.04 x86_64)
Description:

With contrib/btree_gist, a GiST index on a date column rejects the values
'infinity' and '-infinity' once the index has more than one page:

ERROR: 22008: cannot subtract infinite dates
LOCATION: date_mi, date.c:556

Inserting finite dates also fails once the index holds an infinity, and so
does a KNN search (ORDER BY d <-> ...) over such an index. The timestamp and
timestamptz opclasses handle all of these cases.

Versions tested (both behave the same):
- master at 158b6d5109f (PostgreSQL 20devel), --enable-cassert
--enable-debug
- REL_18_STABLE at a85b5523e67 (reports 18.6)
Platform: macOS 26 (Darwin 25.6.0), Apple M-series arm64, Apple clang
21.0.0.
Rechecked on 2026-10-15 (Ubuntu 24.04, x86_64, gcc 13.3, --enable-cassert
--enable-debug, server under ulimit -v 6 GB): the same five errors on
master aa7b9cf132b, 19rc1 (REL_19_STABLE 0fb192f1b02) and REL_18_STABLE
4d62ef92fda.
Fresh initdb, default configuration except fsync=off; empty ~/.psqlrc.

Script:

\set VERBOSITY verbose
CREATE EXTENSION btree_gist;
CREATE TABLE t (d date);
CREATE INDEX t_d_idx ON t USING gist (d);
-- about 410+ rows are enough for the index to grow past one page
INSERT INTO t SELECT date '2000-01-01' + i FROM generate_series(1, 500) i;
INSERT INTO t VALUES ('infinity');
INSERT INTO t VALUES ('-infinity');
-- an index built over rows that already hold infinities (sorted build)
-- succeeds, but later inserts and KNN searches fail
CREATE TABLE u (d date);
INSERT INTO u SELECT date '2000-01-01' + i FROM generate_series(1, 500) i;
INSERT INTO u VALUES ('infinity'), ('-infinity');
CREATE INDEX u_d_idx ON u USING gist (d);
INSERT INTO u VALUES ('2000-06-01');
SET enable_seqscan = off;
SELECT d FROM u ORDER BY d <-> date '2000-06-01' LIMIT 1;
-- the scalar operator rejects infinity as well
SELECT date 'infinity' <-> date '2000-01-01';
-- for comparison, timestamp handles all of this
CREATE TABLE ts (x timestamp);
CREATE INDEX ts_x_idx ON ts USING gist (x);
INSERT INTO ts SELECT timestamp '2000-01-01' + i * interval '1 day' FROM
generate_series(1, 500) i;
INSERT INTO ts VALUES ('infinity'), ('-infinity');
SELECT timestamp 'infinity' <-> timestamp '2000-01-01';

Actual output (master; 18 is identical except date.c:560):

INSERT 0 500
ERROR: 22008: cannot subtract infinite dates <- INSERT 'infinity'
ERROR: 22008: cannot subtract infinite dates <- INSERT '-infinity'
CREATE INDEX <- u_d_idx builds fine
ERROR: 22008: cannot subtract infinite dates <- INSERT '2000-06-01'
into u
ERROR: 22008: cannot subtract infinite dates <- ORDER BY d <-> ...
LIMIT 1
ERROR: 22008: cannot subtract infinite dates <- date 'infinity' <->
date
INSERT 0 2 <- timestamp infinities
OK
infinity <- timestamp <-> result

Expected output: the inserts succeed, the KNN query returns 2000-06-01, and
date <-> returns a saturated value instead of an error, as it does for
timestamp. The table accepts these values without the index, and so does a
btree index.

UPDATE ... SET d = 'infinity' and COPY fail the same way. So does
CREATE INDEX ... WITH (buffering = on) over a table that holds infinities,
since that path does not use the sorted build. Before the sorted build for
btree_gist (e4309f73f69, v18), I believe a plain CREATE INDEX over such a
table would fail as well, but I did not test older branches.

Cause: contrib/btree_gist/btree_date.c computes key differences with
DirectFunctionCall2(date_mi, ...). Since date got infinities in 8.4
(a303e4dc431), date_mi raises an error for infinite input
(src/backend/utils/adt/date.c:553-556). The calls are:
- gbt_date_penalty, lines 212, 218, 228. gistchoose calls it on every
insert once the root is an internal page, which is why a single-page
index does not show the problem. Backtrace (backtrace_functions =
'date_mi'): date_mi <- gbt_date_penalty <- gistchoose <- gistdoinsert.
- gdb_date_dist, line 95 (KNN distance, via gbt_date_distance and
gistScanPage).
- date_dist, line 123 (the date <-> date operator).
btree_ts.c avoids this. gbt_ts_penalty does its own double arithmetic on the
raw int64 values, gbt_ts_dist returns get_float8_infinity() for non-finite
input, and ts_dist/tstz_dist return a saturated interval.

#2Nitin Motiani
nitinmotiani@google.com
In reply to: PG Bug reporting form (#1)
Re: BUG #19761: btree_gist: "cannot subtract infinite dates" when inserting 'infinity' into a GiST index on date

Hi,

Thanks for the analysis. I was able to reproduce the issue.

On Thu, Oct 15, 2026 at 9:03 PM PG Bug reporting form
<noreply@postgresql.org> wrote:

btree_ts.c avoids this. gbt_ts_penalty does its own double arithmetic on the
raw int64 values, gbt_ts_dist returns get_float8_infinity() for non-finite
input, and ts_dist/tstz_dist return a saturated interval.

I'm attaching a patch which uses the same logic as btree_ts.c and
btree_int.c in btree_date.co to handle these issues. Please take a
look.

Thanks & Regards

Nitin Motiani,
Google

Attachments:

t254211_2
v1-0001-btree_gist-Fix-cannot-subtract-infinite-dates-err.patchapplication/x-patch; name=v1-0001-btree_gist-Fix-cannot-subtract-infinite-dates-err.patchDownload+35-31
#3Dilip Kumar
dilipbalaut@gmail.com
In reply to: Nitin Motiani (#2)
Re: BUG #19761: btree_gist: "cannot subtract infinite dates" when inserting 'infinity' into a GiST index on date

On Fri, Oct 16, 2026 at 2:45 PM Nitin Motiani <nitinmotiani@google.com> wrote:

Hi,

Thanks for the analysis. I was able to reproduce the issue.

On Thu, Oct 15, 2026 at 9:03 PM PG Bug reporting form
<noreply@postgresql.org> wrote:

btree_ts.c avoids this. gbt_ts_penalty does its own double arithmetic on the
raw int64 values, gbt_ts_dist returns get_float8_infinity() for non-finite
input, and ts_dist/tstz_dist return a saturated interval.

I'm attaching a patch which uses the same logic as btree_ts.c and
btree_int.c in btree_date.co to handle these issues. Please take a
look.

So IIUC the issue relates to the btree date handling function and not
to gist? If so we can use a normal btree index in the new test cases
we have added instead of gist. I haven't yet reviewed the code
completely but I will do it soon.

--
Regards,
Dilip Kumar
Google

#4Nitin Motiani
nitinmotiani@google.com
In reply to: Dilip Kumar (#3)
Re: BUG #19761: btree_gist: "cannot subtract infinite dates" when inserting 'infinity' into a GiST index on date

On Fri, Oct 23, 2026 at 12:34 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:

So IIUC the issue relates to the btree date handling function and not
to gist? If so we can use a normal btree index in the new test cases
we have added instead of gist. I haven't yet reviewed the code
completely but I will do it soon.

Thanks for taking a look, Dilip. The issue is specific to GiST.
contrib/btree_gist/btree_date.c is the GiST operator class for date in
the btree_gist extension, not btree code[1]https://www.postgresql.org/docs/current/btree-gist.html. The failing functions are
its GiST penalty and distance support functions (gbt_date_penalty and
gdb_date_dist). GiST calls them when routing inserts through internal
pages and for KNN searches. A regular btree index on date never calls
these functions. I tested the standard btree date functions with
infinity, -infinity and they pass without the fix.

That's why the test uses a GiST index with enough rows to have
internal pages. On unpatched code, the INSERT of infinite dates fails
in the penalty function, and the KNN query fails in the distance
function. With the patch, both pass.

One question which I'm unclear on : the bug report also noted that the
SQL operator date <-> date (date_dist in btree_date.c) fails on
+/-infinity. In v1, I left date_dist unchanged because its return type
is int4, which has no infinity representation (similar to int4_dist
raising an error when the distance cannot fit in int4). The
alternative is to make date_dist return PG_INT32_MAX for infinite
inputs, similar to how ts_dist saturates for timestamp. Do you think
we should saturate date_dist to PG_INT32_MAX as well, or keep the
error for the SQL operator?

Regards,
Nitin Motiani
Google

[1]: https://www.postgresql.org/docs/current/btree-gist.html