Author: Noah Misch Commit: Noah Misch diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 13d9994..da6d8d6 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -997,9 +997,16 @@ equalRSDesc(RowSecurityDesc *rsdesc1, RowSecurityDesc *rsdesc2) * (suggesting we are trying to access a just-deleted relation). * Any other error is reported via elog. */ +typedef struct InProgressRels { + Oid relid; + bool invalidated; +} InProgressRels; +static InProgressRels inProgress[100]; + static Relation RelationBuildDesc(Oid targetRelId, bool insertIt) { + int in_progress_offset; Relation relation; Oid relid; HeapTuple pg_class_tuple; @@ -1033,6 +1040,14 @@ RelationBuildDesc(Oid targetRelId, bool insertIt) } #endif + for (in_progress_offset = 0; + OidIsValid(inProgress[in_progress_offset].relid); + in_progress_offset++) + ; + inProgress[in_progress_offset].relid = targetRelId; +retry: + inProgress[in_progress_offset].invalidated = false; + /* * find the tuple in pg_class corresponding to the given relation id */ @@ -1213,6 +1228,10 @@ RelationBuildDesc(Oid targetRelId, bool insertIt) */ heap_freetuple(pg_class_tuple); + if (inProgress[in_progress_offset].invalidated) + goto retry; /* TODO free old one */ + inProgress[in_progress_offset].relid = InvalidOid; + /* * Insert newly created relation into relcache hash table, if requested. * @@ -2805,6 +2824,13 @@ RelationCacheInvalidateEntry(Oid relationId) relcacheInvalsReceived++; RelationFlushRelation(relation); } + else + { + int i; + for (i = 0; OidIsValid(inProgress[i].relid); i++) + if (inProgress[i].relid == relationId) + inProgress[i].invalidated = true; + } } /* @@ -2845,6 +2871,7 @@ RelationCacheInvalidate(void) List *rebuildFirstList = NIL; List *rebuildList = NIL; ListCell *l; + int i; /* * Reload relation mapping data before starting to reconstruct cache. @@ -2931,6 +2958,10 @@ RelationCacheInvalidate(void) RelationClearRelation(relation, true); } list_free(rebuildList); + + /* Any RelationBuildDesc() on the stack must start over. */ + for (i = 0; OidIsValid(inProgress[i].relid); i++) + inProgress[i].invalidated = true; } /*