reindex-assert-fix-1.patch

text/x-patch

Filename: reindex-assert-fix-1.patch
Type: text/x-patch
Part: 0
Message: Re: Assert failure when rechecking an exclusion constraint

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
File+
src/backend/catalog/index.c 0 0
src/test/regress/input/constraints.source 0 0
src/test/regress/output/constraints.source 0 0
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 53b4c3c59bf78cacf8def18ac4d46940a3a29b71..b046f38ecb8a47538cb12e036a6fca6c3509aec1 100644
*** a/src/backend/catalog/index.c
--- b/src/backend/catalog/index.c
*************** static void validate_index_heapscan(Rela
*** 115,120 ****
--- 115,121 ----
  						Snapshot snapshot,
  						v_i_state *state);
  static Oid	IndexGetRelation(Oid indexId);
+ static bool ReindexIsCurrentlyProcessingIndex(Oid indexOid);
  static void SetReindexProcessing(Oid heapOid, Oid indexOid);
  static void ResetReindexProcessing(void);
  static void SetReindexPending(List *indexes);
*************** index_build(Relation heapRelation,
*** 1758,1776 ****
  	}
  
  	/*
- 	 * If it's for an exclusion constraint, make a second pass over the heap
- 	 * to verify that the constraint is satisfied.
- 	 */
- 	if (indexInfo->ii_ExclusionOps != NULL)
- 		IndexCheckExclusion(heapRelation, indexRelation, indexInfo);
- 
- 	/* Roll back any GUC changes executed by index functions */
- 	AtEOXact_GUC(false, save_nestlevel);
- 
- 	/* Restore userid and security context */
- 	SetUserIdAndSecContext(save_userid, save_sec_context);
- 
- 	/*
  	 * If we found any potentially broken HOT chains, mark the index as not
  	 * being usable until the current transaction is below the event horizon.
  	 * See src/backend/access/heap/README.HOT for discussion.
--- 1759,1764 ----
*************** index_build(Relation heapRelation,
*** 1824,1831 ****
  					   InvalidOid,
  					   stats->index_tuples);
  
! 	/* Make the updated versions visible */
  	CommandCounterIncrement();
  }
  
  
--- 1812,1834 ----
  					   InvalidOid,
  					   stats->index_tuples);
  
! 	/* Make the updated catalog row versions visible */
  	CommandCounterIncrement();
+ 
+ 	/*
+ 	 * If it's for an exclusion constraint, make a second pass over the heap
+ 	 * to verify that the constraint is satisfied.  We must not do this until
+ 	 * the index is fully valid.  (Broken HOT chains shouldn't matter, though;
+ 	 * see comments for IndexCheckExclusion.)
+ 	 */
+ 	if (indexInfo->ii_ExclusionOps != NULL)
+ 		IndexCheckExclusion(heapRelation, indexRelation, indexInfo);
+ 
+ 	/* Roll back any GUC changes executed by index functions */
+ 	AtEOXact_GUC(false, save_nestlevel);
+ 
+ 	/* Restore userid and security context */
+ 	SetUserIdAndSecContext(save_userid, save_sec_context);
  }
  
  
*************** IndexCheckExclusion(Relation heapRelatio
*** 2270,2275 ****
--- 2273,2290 ----
  	ExprContext *econtext;
  
  	/*
+ 	 * If we are reindexing the target index, mark it as no longer being
+ 	 * reindexed, to forestall an Assert in index_beginscan when we try to
+ 	 * use the index for probes.  This is OK because the index is now
+ 	 * fully valid.
+ 	 */
+ 	if (ReindexIsCurrentlyProcessingIndex(RelationGetRelid(indexRelation)))
+ 	{
+ 		ResetReindexProcessing();
+ 		RemoveReindexPending(RelationGetRelid(indexRelation));
+ 	}
+ 
+ 	/*
  	 * Need an EState for evaluation of index expressions and partial-index
  	 * predicates.	Also a slot to hold the current tuple.
  	 */
*************** reindex_relation(Oid relid, int flags)
*** 3030,3036 ****
   *		System index reindexing support
   *
   * When we are busy reindexing a system index, this code provides support
!  * for preventing catalog lookups from using that index.
   * ----------------------------------------------------------------
   */
  
--- 3045,3053 ----
   *		System index reindexing support
   *
   * When we are busy reindexing a system index, this code provides support
!  * for preventing catalog lookups from using that index.  We also make use
!  * of this to catch attempted uses of user indexes during reindexing of
!  * those indexes.
   * ----------------------------------------------------------------
   */
  
*************** ReindexIsProcessingHeap(Oid heapOid)
*** 3049,3054 ****
--- 3066,3081 ----
  }
  
  /*
+  * ReindexIsCurrentlyProcessingIndex
+  *		True if index specified by OID is currently being reindexed.
+  */
+ static bool
+ ReindexIsCurrentlyProcessingIndex(Oid indexOid)
+ {
+ 	return indexOid == currentlyReindexedIndex;
+ }
+ 
+ /*
   * ReindexIsProcessingIndex
   *		True if index specified by OID is currently being reindexed,
   *		or should be treated as invalid because it is awaiting reindex.
diff --git a/src/test/regress/input/constraints.source b/src/test/regress/input/constraints.source
index 0d278212c02a4801cd0919b4c2a134b448a2ac42..b84d51e9e5216f8e5899f6bb10d87e12a78e4dc1 100644
*** a/src/test/regress/input/constraints.source
--- b/src/test/regress/input/constraints.source
*************** INSERT INTO circles VALUES('<(20,20), 10
*** 397,402 ****
--- 397,405 ----
  ALTER TABLE circles ADD EXCLUDE USING gist
    (c1 WITH &&, (c2::circle) WITH &&);
  
+ -- try reindexing an existing constraint
+ REINDEX INDEX circles_c1_c2_excl;
+ 
  DROP TABLE circles;
  
  -- Check deferred exclusion constraint
diff --git a/src/test/regress/output/constraints.source b/src/test/regress/output/constraints.source
index d164b90af78e5cb818803e1f1bbadb90fe87c05a..e2f2939931580e1796fc3fde7f4cebf25553d02e 100644
*** a/src/test/regress/output/constraints.source
--- b/src/test/regress/output/constraints.source
*************** ALTER TABLE circles ADD EXCLUDE USING gi
*** 543,548 ****
--- 543,550 ----
  NOTICE:  ALTER TABLE / ADD EXCLUDE will create implicit index "circles_c1_c2_excl1" for table "circles"
  ERROR:  could not create exclusion constraint "circles_c1_c2_excl1"
  DETAIL:  Key (c1, (c2::circle))=(<(0,0),5>, <(0,0),5>) conflicts with key (c1, (c2::circle))=(<(0,0),5>, <(0,0),4>).
+ -- try reindexing an existing constraint
+ REINDEX INDEX circles_c1_c2_excl;
  DROP TABLE circles;
  -- Check deferred exclusion constraint
  CREATE TABLE deferred_excl (