This is an automated email from the ASF dual-hosted git repository.

tuhaihe pushed a commit to branch REL_2_STABLE
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit dfcdea90a4ec3a62dcaa04247f3a90b435c0a2e1
Author: Tomas Vondra <[email protected]>
AuthorDate: Fri Oct 27 17:57:11 2023 +0200

    Fix calculation in brin_minmax_multi_distance_date
    
    When calculating the distance between date values, make sure to subtract
    them in the right order, i.e. (larger - smaller).
    
    The distance is used to determine which values to merge, and is expected
    to be a positive value. The code unfortunately did the subtraction in
    the opposite order, i.e. (smaller - larger), thus producing negative
    values and merging values the most distant values first.
    
    The resulting index is correct (i.e. produces correct results), but may
    be significantly less efficient. This affects all minmax-multi indexes
    on date columns.
    
    Backpatch to 14, where minmax-multi indexes were introduced.
    
    Reported-by: Ashutosh Bapat
    Reviewed-by: Ashutosh Bapat, Dean Rasheed
    Backpatch-through: 14
    Discussion: 
https://postgr.es/m/[email protected]
    (cherry picked from commit a6b1b84d3a1909d7268a25c44e57fa2af7b603dc)
---
 src/backend/access/brin/brin_minmax_multi.c |  7 ++++++-
 src/test/regress/expected/brin_multi.out    | 20 ++++++++++++++++++++
 src/test/regress/sql/brin_multi.sql         | 18 ++++++++++++++++++
 3 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/src/backend/access/brin/brin_minmax_multi.c 
b/src/backend/access/brin/brin_minmax_multi.c
index 270fe7a4baf..407b7d8992a 100644
--- a/src/backend/access/brin/brin_minmax_multi.c
+++ b/src/backend/access/brin/brin_minmax_multi.c
@@ -2075,13 +2075,18 @@ brin_minmax_multi_distance_uuid(PG_FUNCTION_ARGS)
 Datum
 brin_minmax_multi_distance_date(PG_FUNCTION_ARGS)
 {
+       float8          delta = 0;
        DateADT         dateVal1 = PG_GETARG_DATEADT(0);
        DateADT         dateVal2 = PG_GETARG_DATEADT(1);
 
        if (DATE_NOT_FINITE(dateVal1) || DATE_NOT_FINITE(dateVal2))
                PG_RETURN_FLOAT8(0);
 
-       PG_RETURN_FLOAT8(dateVal1 - dateVal2);
+       delta = (float8) dateVal2 - (float8) dateVal1;
+
+       Assert(delta >= 0);
+
+       PG_RETURN_FLOAT8(delta);
 }
 
 /*
diff --git a/src/test/regress/expected/brin_multi.out 
b/src/test/regress/expected/brin_multi.out
index e24935298bc..6f305c651a5 100644
--- a/src/test/regress/expected/brin_multi.out
+++ b/src/test/regress/expected/brin_multi.out
@@ -490,5 +490,25 @@ SELECT '294276-12-01 00:00:01'::timestamptz + (i || ' 
seconds')::interval
   FROM generate_series(1,30) s(i);
 CREATE INDEX ON brin_timestamp_test USING brin (a 
timestamptz_minmax_multi_ops) WITH (pages_per_range=1);
 DROP TABLE brin_timestamp_test;
+-- test overflows during CREATE INDEX with extreme date values
+CREATE TABLE brin_date_test(a DATE);
+-- insert values close to date minimum
+INSERT INTO brin_date_test SELECT '4713-01-01 BC'::date + i FROM 
generate_series(1, 30) s(i);
+-- insert values close to date minimum
+INSERT INTO brin_date_test SELECT '5874897-12-01'::date + i FROM 
generate_series(1, 30) s(i);
+CREATE INDEX ON brin_date_test USING brin (a date_minmax_multi_ops) WITH 
(pages_per_range=1);
+SET enable_seqscan = off;
+-- make sure the ranges were built correctly and 2023-01-01 eliminates all
+EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF)
+SELECT * FROM brin_date_test WHERE a = '2023-01-01'::date;
+                               QUERY PLAN                                
+-------------------------------------------------------------------------
+ Bitmap Heap Scan on brin_date_test (actual rows=0 loops=1)
+   Recheck Cond: (a = '2023-01-01'::date)
+   ->  Bitmap Index Scan on brin_date_test_a_idx (actual rows=0 loops=1)
+         Index Cond: (a = '2023-01-01'::date)
+(4 rows)
+
+DROP TABLE brin_date_test;
 RESET enable_seqscan;
 RESET datestyle;
diff --git a/src/test/regress/sql/brin_multi.sql 
b/src/test/regress/sql/brin_multi.sql
index 06ed60b3dd0..f764ac931a7 100644
--- a/src/test/regress/sql/brin_multi.sql
+++ b/src/test/regress/sql/brin_multi.sql
@@ -443,5 +443,23 @@ SELECT '294276-12-01 00:00:01'::timestamptz + (i || ' 
seconds')::interval
 CREATE INDEX ON brin_timestamp_test USING brin (a 
timestamptz_minmax_multi_ops) WITH (pages_per_range=1);
 DROP TABLE brin_timestamp_test;
 
+-- test overflows during CREATE INDEX with extreme date values
+CREATE TABLE brin_date_test(a DATE);
+
+-- insert values close to date minimum
+INSERT INTO brin_date_test SELECT '4713-01-01 BC'::date + i FROM 
generate_series(1, 30) s(i);
+
+-- insert values close to date minimum
+INSERT INTO brin_date_test SELECT '5874897-12-01'::date + i FROM 
generate_series(1, 30) s(i);
+
+CREATE INDEX ON brin_date_test USING brin (a date_minmax_multi_ops) WITH 
(pages_per_range=1);
+
+SET enable_seqscan = off;
+
+-- make sure the ranges were built correctly and 2023-01-01 eliminates all
+EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF)
+SELECT * FROM brin_date_test WHERE a = '2023-01-01'::date;
+
+DROP TABLE brin_date_test;
 RESET enable_seqscan;
 RESET datestyle;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to