btree_gin: Fix calculation of leftmost interval value.
authorDean Rasheed <dean.a.rasheed@gmail.com>
Sun, 29 Oct 2023 11:14:34 +0000 (11:14 +0000)
committerDean Rasheed <dean.a.rasheed@gmail.com>
Sun, 29 Oct 2023 11:14:34 +0000 (11:14 +0000)
Formerly, the value computed by leftmostvalue_interval() was a long
way short of the minimum possible interval value.  As a result, an
index scan on a GIN index on an interval column with < or <= operators
would miss large negative interval values.

Fix by setting all fields of the leftmost interval to their minimum
values, ensuring that the result is less than any other possible
interval.  Since this only affects index searches, no index rebuild is
necessary.

Back-patch to all supported branches.

Dean Rasheed, reviewed by Heikki Linnakangas.

Discussion: https://postgr.es/m/CAEZATCV80%2BgOfF8ehNUUfaKBZgZMDfCfL-g1HhWGb6kC3rpDfw%40mail.gmail.com

contrib/btree_gin/btree_gin.c
contrib/btree_gin/expected/interval.out
contrib/btree_gin/sql/interval.sql

index c50d68ce186057f313d879dcab99dd12532bd78f..b09bb8df964c295e7e932a75289b9cf6bafc0fcd 100644 (file)
@@ -306,9 +306,9 @@ leftmostvalue_interval(void)
 {
    Interval   *v = palloc(sizeof(Interval));
 
-   v->time = DT_NOBEGIN;
-   v->day = 0;
-   v->month = 0;
+   v->time = PG_INT64_MIN;
+   v->day = PG_INT32_MIN;
+   v->month = PG_INT32_MIN;
    return IntervalPGetDatum(v);
 }
 
index 1f6ef54070eedd4c2a6515538534a1eaf314b88a..8bb9806650d9f5f12c21a9ddb91ee247db560fbf 100644 (file)
@@ -3,30 +3,34 @@ CREATE TABLE test_interval (
    i interval
 );
 INSERT INTO test_interval VALUES
+   ( '-178000000 years' ),
    ( '03:55:08' ),
    ( '04:55:08' ),
    ( '05:55:08' ),
    ( '08:55:08' ),
    ( '09:55:08' ),
-   ( '10:55:08' )
+   ( '10:55:08' ),
+   ( '178000000 years' )
 ;
 CREATE INDEX idx_interval ON test_interval USING gin (i);
 SELECT * FROM test_interval WHERE i<'08:55:08'::interval ORDER BY i;
             i             
 --------------------------
+ @ 178000000 years ago
  @ 3 hours 55 mins 8 secs
  @ 4 hours 55 mins 8 secs
  @ 5 hours 55 mins 8 secs
-(3 rows)
+(4 rows)
 
 SELECT * FROM test_interval WHERE i<='08:55:08'::interval ORDER BY i;
             i             
 --------------------------
+ @ 178000000 years ago
  @ 3 hours 55 mins 8 secs
  @ 4 hours 55 mins 8 secs
  @ 5 hours 55 mins 8 secs
  @ 8 hours 55 mins 8 secs
-(4 rows)
+(5 rows)
 
 SELECT * FROM test_interval WHERE i='08:55:08'::interval ORDER BY i;
             i             
@@ -40,12 +44,14 @@ SELECT * FROM test_interval WHERE i>='08:55:08'::interval ORDER BY i;
  @ 8 hours 55 mins 8 secs
  @ 9 hours 55 mins 8 secs
  @ 10 hours 55 mins 8 secs
-(3 rows)
+ @ 178000000 years
+(4 rows)
 
 SELECT * FROM test_interval WHERE i>'08:55:08'::interval ORDER BY i;
              i             
 ---------------------------
  @ 9 hours 55 mins 8 secs
  @ 10 hours 55 mins 8 secs
-(2 rows)
+ @ 178000000 years
+(3 rows)
 
index e385158783370660ee958acb55cfddbc9b61c7cf..7a2f3ac0d85f6433a273711180beb8902a2c4094 100644 (file)
@@ -5,12 +5,14 @@ CREATE TABLE test_interval (
 );
 
 INSERT INTO test_interval VALUES
+   ( '-178000000 years' ),
    ( '03:55:08' ),
    ( '04:55:08' ),
    ( '05:55:08' ),
    ( '08:55:08' ),
    ( '09:55:08' ),
-   ( '10:55:08' )
+   ( '10:55:08' ),
+   ( '178000000 years' )
 ;
 
 CREATE INDEX idx_interval ON test_interval USING gin (i);