Commit eca13886 authored by Tom Lane's avatar Tom Lane

Fix corner-case bug introduced with HOT: if REINDEX TABLE pg_class (or a

REINDEX DATABASE including same) is done before a session has done any other
update on pg_class, the pg_class relcache entry was left with an incorrect
setting of rd_indexattr, because the indexed-attributes set would be first
demanded at a time when we'd forced a partial list of indexes into the
pg_class entry, and it would remain cached after that.  This could result
in incorrect decisions about HOT-update safety later in the same session.
In practice, since only pg_class_relname_nsp_index would be missed out,
only ALTER TABLE RENAME and ALTER TABLE SET SCHEMA could trigger a problem.
Per report and test case from Ondrej Jirman.
parent 30fd8ec7
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.300 2008/06/19 00:46:04 alvherre Exp $ * $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.301 2008/08/10 19:02:33 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -2380,9 +2380,13 @@ reindex_relation(Oid relid, bool toast_too) ...@@ -2380,9 +2380,13 @@ reindex_relation(Oid relid, bool toast_too)
* problem. * problem.
*/ */
is_pg_class = (RelationGetRelid(rel) == RelationRelationId); is_pg_class = (RelationGetRelid(rel) == RelationRelationId);
doneIndexes = NIL;
/* Ensure rd_indexattr is valid; see comments for RelationSetIndexList */
if (is_pg_class)
(void) RelationGetIndexAttrBitmap(rel);
/* Reindex all the indexes. */ /* Reindex all the indexes. */
doneIndexes = NIL;
foreach(indexId, indexIds) foreach(indexId, indexIds)
{ {
Oid indexOid = lfirst_oid(indexId); Oid indexOid = lfirst_oid(indexId);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.272 2008/05/12 00:00:52 alvherre Exp $ * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.273 2008/08/10 19:02:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2986,6 +2986,13 @@ insert_ordered_oid(List *list, Oid datum) ...@@ -2986,6 +2986,13 @@ insert_ordered_oid(List *list, Oid datum)
* messages. In practice it is only used on pg_class (see REINDEX). * messages. In practice it is only used on pg_class (see REINDEX).
* *
* It is up to the caller to make sure the given list is correctly ordered. * It is up to the caller to make sure the given list is correctly ordered.
*
* We deliberately do not change rd_indexattr here: even when operating
* with a temporary partial index list, HOT-update decisions must be made
* correctly with respect to the full index set. It is up to the caller
* to ensure that a correct rd_indexattr set has been cached before first
* calling RelationSetIndexList; else a subsequent inquiry might cause a
* wrong rd_indexattr set to get computed and cached.
*/ */
void void
RelationSetIndexList(Relation relation, List *indexIds, Oid oidIndex) RelationSetIndexList(Relation relation, List *indexIds, Oid oidIndex)
...@@ -3004,7 +3011,6 @@ RelationSetIndexList(Relation relation, List *indexIds, Oid oidIndex) ...@@ -3004,7 +3011,6 @@ RelationSetIndexList(Relation relation, List *indexIds, Oid oidIndex)
relation->rd_indexvalid = 2; /* mark list as forced */ relation->rd_indexvalid = 2; /* mark list as forced */
/* must flag that we have a forced index list */ /* must flag that we have a forced index list */
need_eoxact_work = true; need_eoxact_work = true;
/* we deliberately do not change rd_indexattr */
} }
/* /*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment