diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 0e74464c408..d3b1ce5acd3 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -3700,8 +3700,10 @@ RelationGetIndexPredicate(Relation relation) * we can include system attributes (e.g., OID) in the bitmap representation. * * Caller had better hold at least RowExclusiveLock on the target relation - * to ensure that it has a stable set of indexes. This also makes it safe - * (deadlock-free) for us to take locks on the relation's indexes. + * to ensure it is safe (deadlock-free) for us to take locks on the relation's + * indexes. Note that since the introduction of CREATE INDEX CONCURRENTLY, + * that lock level doesn't guarantee a stable set of indexes, so we have to + * be prepared to retry here in case of a change in the set of indexes. * * The returned result is palloc'd in the caller's memory context and should * be bms_free'd when not needed anymore. @@ -3711,6 +3713,7 @@ RelationGetIndexAttrBitmap(Relation relation) { Bitmapset *indexattrs; List *indexoidlist; + List *newindexoidlist; ListCell *l; MemoryContext oldcxt; @@ -3723,8 +3726,9 @@ RelationGetIndexAttrBitmap(Relation relation) return NULL; /* - * Get cached list of index OIDs + * Get cached list of index OIDs. If we have to start over, we do so here. */ +restart: indexoidlist = RelationGetIndexList(relation); /* Fall out if no indexes (but relhasindex was set) */ @@ -3773,7 +3777,28 @@ RelationGetIndexAttrBitmap(Relation relation) index_close(indexDesc, AccessShareLock); } - list_free(indexoidlist); + /* + * During one of the index_opens in the above loop, we might have received + * a relcache flush event on this relcache entry, which might have been + * signaling a change in the rel's index list. If so, we'd better start + * over to ensure we deliver up-to-date attribute bitmaps. + */ + newindexoidlist = RelationGetIndexList(relation); + if (equal(indexoidlist, newindexoidlist)) + { + /* Still the same index set, so proceed */ + list_free(newindexoidlist); + list_free(indexoidlist); + } + else + { + /* Gotta do it over ... might as well not leak memory */ + list_free(newindexoidlist); + list_free(indexoidlist); + bms_free(indexattrs); + + goto restart; + } /* Now save a copy of the bitmap in the relcache entry. */ oldcxt = MemoryContextSwitchTo(CacheMemoryContext);