summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-06-05 22:30:04 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2011-06-05 22:31:05 -0400
commitdccfb72892acabd25568539ec882cc44c57c25bd (patch)
treeddc8950231ad7b41a9b6f2c1b87cc886b844dd64
parentccd69b888641441b2332dc928ada1390dd0c318a (diff)
downloadpostgresql-dccfb72892acabd25568539ec882cc44c57c25bd.tar.gz
Reset reindex-in-progress state before reverifying an exclusion constraint.
This avoids an Assert failure when we try to use ordinary index fetches while checking for exclusion conflicts. Per report from Noah Misch. No need for back-patch because the Assert wasn't there before 9.1.
-rw-r--r--src/backend/catalog/index.c64
-rw-r--r--src/test/regress/input/constraints.source3
-rw-r--r--src/test/regress/output/constraints.source2
3 files changed, 50 insertions, 19 deletions
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 53b4c3c59b..1b39e1683c 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -115,6 +115,7 @@ static void validate_index_heapscan(Relation heapRelation,
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);
@@ -1747,8 +1748,8 @@ index_build(Relation heapRelation,
* created it, or truncated twice in a subsequent transaction, the
* relfilenode won't change, and nothing needs to be done here.
*/
- if (heapRelation->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED
- && !smgrexists(indexRelation->rd_smgr, INIT_FORKNUM))
+ if (heapRelation->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED &&
+ !smgrexists(indexRelation->rd_smgr, INIT_FORKNUM))
{
RegProcedure ambuildempty = indexRelation->rd_am->ambuildempty;
@@ -1758,19 +1759,6 @@ index_build(Relation heapRelation,
}
/*
- * 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.
@@ -1824,8 +1812,23 @@ index_build(Relation heapRelation,
InvalidOid,
stats->index_tuples);
- /* Make the updated versions visible */
+ /* 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);
}
@@ -2270,6 +2273,15 @@ IndexCheckExclusion(Relation heapRelation,
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.
*/
@@ -2989,8 +3001,8 @@ reindex_relation(Oid relid, int flags)
CommandCounterIncrement();
- if (flags & REINDEX_REL_SUPPRESS_INDEX_USE)
- RemoveReindexPending(indexOid);
+ /* Index should no longer be in the pending list */
+ Assert(!ReindexIsProcessingIndex(indexOid));
if (is_pg_class)
doneIndexes = lappend_oid(doneIndexes, indexOid);
@@ -3030,7 +3042,9 @@ reindex_relation(Oid relid, int flags)
* System index reindexing support
*
* When we are busy reindexing a system index, this code provides support
- * for preventing catalog lookups from using that index.
+ * 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.
* ----------------------------------------------------------------
*/
@@ -3049,6 +3063,16 @@ ReindexIsProcessingHeap(Oid heapOid)
}
/*
+ * 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.
@@ -3075,6 +3099,8 @@ SetReindexProcessing(Oid heapOid, Oid indexOid)
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 0d278212c0..b84d51e9e5 100644
--- a/src/test/regress/input/constraints.source
+++ b/src/test/regress/input/constraints.source
@@ -397,6 +397,9 @@ INSERT INTO circles VALUES('<(20,20), 10>', '<(10,10), 5>');
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 d164b90af7..e2f2939931 100644
--- a/src/test/regress/output/constraints.source
+++ b/src/test/regress/output/constraints.source
@@ -543,6 +543,8 @@ ALTER TABLE circles ADD EXCLUDE USING gist
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 (