I wrote:
> Noah Misch <n...@leadboat.com> writes:
>> Sounds reasonable.  Need to remove the index from pendingReindexedIndexes, 
>> not
>> just call ResetReindexProcessing().

> [ looks again... ]  Uh, right.  I was thinking that the pending list was
> just "pending" and not "in progress" indexes.  I wonder if we should
> rejigger things so that that's actually true, ie, remove an index's OID
> from the pending list when we mark it as the current one?

Attached are two versions of a patch to fix this.  The second one
modifies the code that tracks what's "pending" as per the above thought.
I'm not entirely sure which one I like better ... any comments?

                        regards, tom lane

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 (
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 53b4c3c59bf78cacf8def18ac4d46940a3a29b71..1b39e1683c709ab866de16ccd199ef92ed2db8ec 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,2287 ----
  	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();
+ 
+ 	/*
  	 * 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)
*** 2989,2996 ****
  
  			CommandCounterIncrement();
  
! 			if (flags & REINDEX_REL_SUPPRESS_INDEX_USE)
! 				RemoveReindexPending(indexOid);
  
  			if (is_pg_class)
  				doneIndexes = lappend_oid(doneIndexes, indexOid);
--- 3001,3008 ----
  
  			CommandCounterIncrement();
  
! 			/* Index should no longer be in the pending list */
! 			Assert(!ReindexIsProcessingIndex(indexOid));
  
  			if (is_pg_class)
  				doneIndexes = lappend_oid(doneIndexes, indexOid);
*************** 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.
   * ----------------------------------------------------------------
   */
  
--- 3042,3050 ----
   *		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 ****
--- 3063,3078 ----
  }
  
  /*
+  * 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.
*************** SetReindexProcessing(Oid heapOid, Oid in
*** 3075,3080 ****
--- 3099,3106 ----
  		elog(ERROR, "cannot reindex while reindexing");
  	currentlyReindexedHeap = heapOid;
  	currentlyReindexedIndex = indexOid;
+ 	/* Index is no longer "pending" reindex. */
+ 	RemoveReindexPending(indexOid);
  }
  
  /*
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 (
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to