* RelationIdGetRelation * * Lookup a reldesc by OID; make one if not already in cache. * * Returns NULL if no pg_class row could be found for the given relid * (suggesting we are trying to access a just-deleted relation). * Any other error is reported via elog. * * NB: caller should already have at least AccessShareLock on the * relation ID, else there are nasty race conditions. *
| 2152 | * that happens by calling RelationClose().) |
| 2153 | */ |
| 2154 | Relation |
| 2155 | RelationIdGetRelation(Oid relationId) |
| 2156 | { |
| 2157 | Relation rd; |
| 2158 | |
| 2159 | /* Make sure we're in an xact, even if this ends up being a cache hit */ |
| 2160 | Assert(IsTransactionState()); |
| 2161 | |
| 2162 | /* |
| 2163 | * first try to find reldesc in the cache |
| 2164 | */ |
| 2165 | RelationIdCacheLookup(relationId, rd); |
| 2166 | |
| 2167 | if (RelationIsValid(rd)) |
| 2168 | { |
| 2169 | /* return NULL for dropped relations */ |
| 2170 | if (rd->rd_droppedSubid != InvalidSubTransactionId) |
| 2171 | { |
| 2172 | Assert(!rd->rd_isvalid); |
| 2173 | return NULL; |
| 2174 | } |
| 2175 | |
| 2176 | RelationIncrementReferenceCount(rd); |
| 2177 | /* revalidate cache entry if necessary */ |
| 2178 | if (!rd->rd_isvalid) |
| 2179 | { |
| 2180 | /* |
| 2181 | * Indexes only have a limited number of possible schema changes, |
| 2182 | * and we don't want to use the full-blown procedure because it's |
| 2183 | * a headache for indexes that reload itself depends on. |
| 2184 | */ |
| 2185 | if (rd->rd_rel->relkind == RELKIND_INDEX || |
| 2186 | rd->rd_rel->relkind == RELKIND_PARTITIONED_INDEX) |
| 2187 | RelationReloadIndexInfo(rd); |
| 2188 | else |
| 2189 | RelationClearRelation(rd, true); |
| 2190 | |
| 2191 | /* |
| 2192 | * Normally entries need to be valid here, but before the relcache |
| 2193 | * has been initialized, not enough infrastructure exists to |
| 2194 | * perform pg_class lookups. The structure of such entries doesn't |
| 2195 | * change, but we still want to update the rd_rel entry. So |
| 2196 | * rd_isvalid = false is left in place for a later lookup. |
| 2197 | */ |
| 2198 | Assert(rd->rd_isvalid || |
| 2199 | (rd->rd_isnailed && !criticalRelcachesBuilt)); |
| 2200 | } |
| 2201 | return rd; |
| 2202 | } |
| 2203 | |
| 2204 | /* |
| 2205 | * no reldesc in the cache, so have RelationBuildDesc() build one and add |
| 2206 | * it. |
| 2207 | */ |
| 2208 | rd = RelationBuildDesc(relationId, true); |
| 2209 | if (RelationIsValid(rd)) |
| 2210 | RelationIncrementReferenceCount(rd); |
| 2211 | return rd; |
no test coverage detected