Gregory Stark <stark@enterprisedb.com> writes:
> Uhm. Is it possible we're mistakenly doing a HOT update because we're lying
> about what indexes exist?
Yup, exactly. Here's my proposed fix...
regards, tom lane
Index: src/backend/catalog/index.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/catalog/index.c,v
retrieving revision 1.300
diff -c -r1.300 index.c
*** src/backend/catalog/index.c 19 Jun 2008 00:46:04 -0000 1.300
--- src/backend/catalog/index.c 10 Aug 2008 18:49:08 -0000
***************
*** 2380,2388 ****
* problem.
*/
is_pg_class = (RelationGetRelid(rel) == RelationRelationId);
! doneIndexes = NIL;
/* Reindex all the indexes. */
foreach(indexId, indexIds)
{
Oid indexOid = lfirst_oid(indexId);
--- 2380,2392 ----
* problem.
*/
is_pg_class = (RelationGetRelid(rel) == RelationRelationId);
!
! /* Ensure rd_indexattr is valid; see comments for RelationSetIndexList */
! if (is_pg_class)
! (void) RelationGetIndexAttrBitmap(rel);
/* Reindex all the indexes. */
+ doneIndexes = NIL;
foreach(indexId, indexIds)
{
Oid indexOid = lfirst_oid(indexId);
Index: src/backend/utils/cache/relcache.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v
retrieving revision 1.272
diff -c -r1.272 relcache.c
*** src/backend/utils/cache/relcache.c 12 May 2008 00:00:52 -0000 1.272
--- src/backend/utils/cache/relcache.c 10 Aug 2008 18:49:08 -0000
***************
*** 2986,2991 ****
--- 2986,2998 ----
* 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.
+ *
+ * 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
RelationSetIndexList(Relation relation, List *indexIds, Oid oidIndex)
***************
*** 3004,3010 ****
relation->rd_indexvalid = 2; /* mark list as forced */
/* must flag that we have a forced index list */
need_eoxact_work = true;
- /* we deliberately do not change rd_indexattr */
}
/*
--- 3011,3016 ----