diff options
Diffstat (limited to 'src/backend/utils')
-rw-r--r-- | src/backend/utils/adt/dbsize.c | 5 | ||||
-rw-r--r-- | src/backend/utils/cache/relcache.c | 25 |
2 files changed, 25 insertions, 5 deletions
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index 2ccdc0cee6e..03975fcea44 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -259,6 +259,9 @@ pg_tablespace_size_name(PG_FUNCTION_ARGS) /* * calculate size of (one fork of) a relation + * + * Note: we can safely apply this to temp tables of other sessions, so there + * is no check here or at the call sites for that. */ static int64 calculate_relation_size(RelFileNode *rfn, BackendId backend, ForkNumber forknum) @@ -313,7 +316,7 @@ pg_relation_size(PG_FUNCTION_ARGS) * that makes queries like "SELECT pg_relation_size(oid) FROM pg_class" * less robust, because while we scan pg_class with an MVCC snapshot, * someone else might drop the table. It's better to return NULL for - * alread-dropped tables than throw an error and abort the whole query. + * already-dropped tables than throw an error and abort the whole query. */ if (rel == NULL) PG_RETURN_NULL(); diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index a64d739cebc..bd7f567f1e9 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -852,20 +852,33 @@ RelationBuildDesc(Oid targetRelId, bool insertIt) case RELPERSISTENCE_UNLOGGED: case RELPERSISTENCE_PERMANENT: relation->rd_backend = InvalidBackendId; + relation->rd_islocaltemp = false; break; case RELPERSISTENCE_TEMP: if (isTempOrToastNamespace(relation->rd_rel->relnamespace)) + { relation->rd_backend = MyBackendId; + relation->rd_islocaltemp = true; + } else { /* - * If it's a local temp table, but not one of ours, we have to - * use the slow, grotty method to figure out the owning - * backend. + * If it's a temp table, but not one of ours, we have to use + * the slow, grotty method to figure out the owning backend. + * + * Note: it's possible that rd_backend gets set to MyBackendId + * here, in case we are looking at a pg_class entry left over + * from a crashed backend that coincidentally had the same + * BackendId we're using. We should *not* consider such a + * table to be "ours"; this is why we need the separate + * rd_islocaltemp flag. The pg_class entry will get flushed + * if/when we clean out the corresponding temp table namespace + * in preparation for using it. */ relation->rd_backend = GetTempNamespaceBackendId(relation->rd_rel->relnamespace); Assert(relation->rd_backend != InvalidBackendId); + relation->rd_islocaltemp = false; } break; default: @@ -1386,6 +1399,7 @@ formrdesc(const char *relationName, Oid relationReltype, relation->rd_createSubid = InvalidSubTransactionId; relation->rd_newRelfilenodeSubid = InvalidSubTransactionId; relation->rd_backend = InvalidBackendId; + relation->rd_islocaltemp = false; /* * initialize relation tuple form @@ -2535,16 +2549,19 @@ RelationBuildLocalRelation(const char *relname, /* needed when bootstrapping: */ rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID; - /* set up persistence; rd_backend is a function of persistence type */ + /* set up persistence and relcache fields dependent on it */ rel->rd_rel->relpersistence = relpersistence; switch (relpersistence) { case RELPERSISTENCE_UNLOGGED: case RELPERSISTENCE_PERMANENT: rel->rd_backend = InvalidBackendId; + rel->rd_islocaltemp = false; break; case RELPERSISTENCE_TEMP: + Assert(isTempOrToastNamespace(relnamespace)); rel->rd_backend = MyBackendId; + rel->rd_islocaltemp = true; break; default: elog(ERROR, "invalid relpersistence: %c", relpersistence); |