]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix restore of partitions with exclusion constraints
authorÁlvaro Herrera <alvherre@kurilemu.de>
Mon, 20 Jul 2026 15:21:20 +0000 (17:21 +0200)
committerÁlvaro Herrera <alvherre@kurilemu.de>
Mon, 20 Jul 2026 15:21:20 +0000 (17:21 +0200)
Commit 8c852ba9a4 allowed exclusion constraints to be added to
partitioned tables, but wasn't careful to verify that pg_restore worked
correctly for them.  Fix that by making CompareIndexInfo() more
selective about what needs to be rejected.

Author: Japin Li <japinli@hotmail.com>
Reported-by: Keith Paskett <keith.paskett@logansw.com>
Discussion: https://postgr.es/m/2A40921D-83AB-411E-ADA6-7E509A46F1E4@logansw.com

src/backend/catalog/index.c
src/test/regress/expected/indexing.out
src/test/regress/sql/indexing.sql

index 81bba4beac7cb5bd67357c8bec2323ce9de0e5ec..31ef84d0a1663254cfc199222927fa67d82fc410 100644 (file)
@@ -2663,9 +2663,21 @@ CompareIndexInfo(const IndexInfo *info1, const IndexInfo *info2,
                        return false;
        }
 
-       /* No support currently for comparing exclusion indexes. */
-       if (info1->ii_ExclusionOps != NULL || info2->ii_ExclusionOps != NULL)
+       /* If they're exclusion indexes, their properties must be identical */
+       if ((info1->ii_ExclusionOps == NULL) != (info2->ii_ExclusionOps == NULL))
                return false;
+       if (info1->ii_ExclusionOps != NULL)
+       {
+               for (i = 0; i < info1->ii_NumIndexKeyAttrs; i++)
+               {
+                       if (info1->ii_ExclusionOps[i] != info2->ii_ExclusionOps[i])
+                               return false;
+                       if (info1->ii_ExclusionProcs[i] != info2->ii_ExclusionProcs[i])
+                               return false;
+                       if (info1->ii_ExclusionStrats[i] != info2->ii_ExclusionStrats[i])
+                               return false;
+               }
+       }
 
        return true;
 }
index 4d350fbc658a943d909227d7f34a87b22163b6ed..4a0a652e9f697bd816d0b748c7def26fc5013597 100644 (file)
@@ -1785,3 +1785,18 @@ insert into test_pg_wholerow_index values (2, 'addition', 0);
 drop index row_image_index;
 drop function row_image(test_pg_wholerow_index);
 drop table test_pg_wholerow_index;
+-- Test of a partitioned index attach, when there are exclusion constraints.
+create table idx_excl_part (a int4range, b int4range) partition by list (a);
+create table idx_excl_part_1 (a int4range, b int4range);
+alter table only idx_excl_part attach partition idx_excl_part_1 for values in ('[0,1)'::int4range);
+alter table only idx_excl_part add constraint idxpart_id_data_excl exclude using gist (a with =, b with &&);
+alter table idx_excl_part_1 add constraint idxpart_1_id_data_excl exclude using gist (a with &&, b with &&);
+-- This should be disallowed, because the constraints don't match.
+alter index idxpart_id_data_excl attach partition idxpart_1_id_data_excl;
+ERROR:  cannot attach index "idxpart_1_id_data_excl" as a partition of index "idxpart_id_data_excl"
+DETAIL:  The index definitions do not match.
+-- but if we recreate the constraint differently, it's allowed:
+alter table idx_excl_part_1 drop constraint idxpart_1_id_data_excl;
+alter table idx_excl_part_1 add constraint idxpart_1_id_data_excl exclude using gist (a with =, b with &&);
+alter index idxpart_id_data_excl attach partition idxpart_1_id_data_excl;
+-- leave these tables around, for pg_upgrade testing
index 561403cc7f77029869fbf3574deafe6321d7fe5d..bbcfb36528173a23521107972ed212fcc65d5059 100644 (file)
@@ -1005,3 +1005,17 @@ insert into test_pg_wholerow_index values (2, 'addition', 0);
 drop index row_image_index;
 drop function row_image(test_pg_wholerow_index);
 drop table test_pg_wholerow_index;
+
+-- Test of a partitioned index attach, when there are exclusion constraints.
+create table idx_excl_part (a int4range, b int4range) partition by list (a);
+create table idx_excl_part_1 (a int4range, b int4range);
+alter table only idx_excl_part attach partition idx_excl_part_1 for values in ('[0,1)'::int4range);
+alter table only idx_excl_part add constraint idxpart_id_data_excl exclude using gist (a with =, b with &&);
+alter table idx_excl_part_1 add constraint idxpart_1_id_data_excl exclude using gist (a with &&, b with &&);
+-- This should be disallowed, because the constraints don't match.
+alter index idxpart_id_data_excl attach partition idxpart_1_id_data_excl;
+-- but if we recreate the constraint differently, it's allowed:
+alter table idx_excl_part_1 drop constraint idxpart_1_id_data_excl;
+alter table idx_excl_part_1 add constraint idxpart_1_id_data_excl exclude using gist (a with =, b with &&);
+alter index idxpart_id_data_excl attach partition idxpart_1_id_data_excl;
+-- leave these tables around, for pg_upgrade testing