diff options
author | Robert Haas <rhaas@postgresql.org> | 2010-12-13 12:34:26 -0500 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2010-12-13 12:34:26 -0500 |
commit | 5f7b58fad8f45c69bb67944779dce67e2f481995 (patch) | |
tree | fae9ba84d982d83e9505546facfe17369909994a /src | |
parent | 0c90442355fbbe785740669f63141f24674c8958 (diff) | |
download | postgresql-5f7b58fad8f45c69bb67944779dce67e2f481995.tar.gz postgresql-5f7b58fad8f45c69bb67944779dce67e2f481995.zip |
Generalize concept of temporary relations to "relation persistence".
This commit replaces pg_class.relistemp with pg_class.relpersistence;
and also modifies the RangeVar node type to carry relpersistence rather
than istemp. It also removes removes rd_istemp from RelationData and
instead performs the correct computation based on relpersistence.
For clarity, we add three new macros: RelationNeedsWAL(),
RelationUsesLocalBuffers(), and RelationUsesTempNamespace(), so that we
can clarify the purpose of each check that previous depended on
rd_istemp.
This is intended as infrastructure for the upcoming unlogged tables
patch, as well as for future possible work on global temporary tables.
Diffstat (limited to 'src')
48 files changed, 334 insertions, 230 deletions
diff --git a/src/backend/access/gin/ginbtree.c b/src/backend/access/gin/ginbtree.c index 070cd9209e1..9d857a03102 100644 --- a/src/backend/access/gin/ginbtree.c +++ b/src/backend/access/gin/ginbtree.c @@ -304,7 +304,7 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats) MarkBufferDirty(stack->buffer); - if (!btree->index->rd_istemp) + if (RelationNeedsWAL(btree->index)) { XLogRecPtr recptr; @@ -373,7 +373,7 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats) MarkBufferDirty(lbuffer); MarkBufferDirty(stack->buffer); - if (!btree->index->rd_istemp) + if (RelationNeedsWAL(btree->index)) { XLogRecPtr recptr; @@ -422,7 +422,7 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats) MarkBufferDirty(rbuffer); MarkBufferDirty(stack->buffer); - if (!btree->index->rd_istemp) + if (RelationNeedsWAL(btree->index)) { XLogRecPtr recptr; diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c index 525f79cea7a..74339c9eeaf 100644 --- a/src/backend/access/gin/ginfast.c +++ b/src/backend/access/gin/ginfast.c @@ -103,7 +103,7 @@ writeListPage(Relation index, Buffer buffer, MarkBufferDirty(buffer); - if (!index->rd_istemp) + if (RelationNeedsWAL(index)) { XLogRecData rdata[2]; ginxlogInsertListPage data; @@ -384,7 +384,7 @@ ginHeapTupleFastInsert(Relation index, GinState *ginstate, */ MarkBufferDirty(metabuffer); - if (!index->rd_istemp) + if (RelationNeedsWAL(index)) { XLogRecPtr recptr; @@ -564,7 +564,7 @@ shiftList(Relation index, Buffer metabuffer, BlockNumber newHead, MarkBufferDirty(buffers[i]); } - if (!index->rd_istemp) + if (RelationNeedsWAL(index)) { XLogRecPtr recptr; diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c index fa70e4fa55d..8681edefe67 100644 --- a/src/backend/access/gin/gininsert.c +++ b/src/backend/access/gin/gininsert.c @@ -55,7 +55,7 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems) MarkBufferDirty(buffer); - if (!index->rd_istemp) + if (RelationNeedsWAL(index)) { XLogRecPtr recptr; XLogRecData rdata[2]; @@ -325,7 +325,7 @@ ginbuild(PG_FUNCTION_ARGS) GinInitBuffer(RootBuffer, GIN_LEAF); MarkBufferDirty(RootBuffer); - if (!index->rd_istemp) + if (RelationNeedsWAL(index)) { XLogRecPtr recptr; XLogRecData rdata; diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c index 27326acec9a..5f20ac9349f 100644 --- a/src/backend/access/gin/ginutil.c +++ b/src/backend/access/gin/ginutil.c @@ -410,7 +410,7 @@ ginUpdateStats(Relation index, const GinStatsData *stats) MarkBufferDirty(metabuffer); - if (!index->rd_istemp) + if (RelationNeedsWAL(index)) { XLogRecPtr recptr; ginxlogUpdateMeta data; diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c index 7dfecffc877..4b35acb983a 100644 --- a/src/backend/access/gin/ginvacuum.c +++ b/src/backend/access/gin/ginvacuum.c @@ -93,7 +93,7 @@ xlogVacuumPage(Relation index, Buffer buffer) Assert(GinPageIsLeaf(page)); - if (index->rd_istemp) + if (!RelationNeedsWAL(index)) return; data.node = index->rd_node; @@ -308,7 +308,7 @@ ginDeletePage(GinVacuumState *gvs, BlockNumber deleteBlkno, BlockNumber leftBlkn MarkBufferDirty(lBuffer); MarkBufferDirty(dBuffer); - if (!gvs->index->rd_istemp) + if (RelationNeedsWAL(gvs->index)) { XLogRecPtr recptr; XLogRecData rdata[4]; diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index d6aaea2162d..b34830bb424 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -115,7 +115,7 @@ gistbuild(PG_FUNCTION_ARGS) MarkBufferDirty(buffer); - if (!index->rd_istemp) + if (RelationNeedsWAL(index)) { XLogRecPtr recptr; XLogRecData rdata; @@ -401,7 +401,7 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate) dist->page = BufferGetPage(dist->buffer); } - if (!state->r->rd_istemp) + if (RelationNeedsWAL(state->r)) { XLogRecPtr recptr; XLogRecData *rdata; @@ -465,7 +465,7 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate) MarkBufferDirty(state->stack->buffer); - if (!state->r->rd_istemp) + if (RelationNeedsWAL(state->r)) { OffsetNumber noffs = 0, offs[1]; @@ -550,7 +550,7 @@ gistfindleaf(GISTInsertState *state, GISTSTATE *giststate) opaque = GistPageGetOpaque(state->stack->page); state->stack->lsn = PageGetLSN(state->stack->page); - Assert(state->r->rd_istemp || !XLogRecPtrIsInvalid(state->stack->lsn)); + Assert(!RelationNeedsWAL(state->r) || !XLogRecPtrIsInvalid(state->stack->lsn)); if (state->stack->blkno != GIST_ROOT_BLKNO && XLByteLT(state->stack->parent->lsn, opaque->nsn)) @@ -911,7 +911,7 @@ gistmakedeal(GISTInsertState *state, GISTSTATE *giststate) } /* say to xlog that insert is completed */ - if (state->needInsertComplete && !state->r->rd_istemp) + if (state->needInsertComplete && RelationNeedsWAL(state->r)) gistxlogInsertCompletion(state->r->rd_node, &(state->key), 1); } @@ -1011,7 +1011,7 @@ gistnewroot(Relation r, Buffer buffer, IndexTuple *itup, int len, ItemPointer ke MarkBufferDirty(buffer); - if (!r->rd_istemp) + if (RelationNeedsWAL(r)) { XLogRecPtr recptr; XLogRecData *rdata; diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c index dbe9406ceb8..e02e72d4313 100644 --- a/src/backend/access/gist/gistvacuum.c +++ b/src/backend/access/gist/gistvacuum.c @@ -248,7 +248,7 @@ gistbulkdelete(PG_FUNCTION_ARGS) PageIndexTupleDelete(page, todelete[i]); GistMarkTuplesDeleted(page); - if (!rel->rd_istemp) + if (RelationNeedsWAL(rel)) { XLogRecData *rdata; XLogRecPtr recptr; diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 4fe3a739109..4020906b347 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -124,7 +124,7 @@ initscan(HeapScanDesc scan, ScanKey key, bool is_rescan) * * During a rescan, don't make a new strategy object if we don't have to. */ - if (!scan->rs_rd->rd_istemp && + if (!RelationUsesLocalBuffers(scan->rs_rd) && scan->rs_nblocks > NBuffers / 4) { allow_strat = scan->rs_allow_strat; @@ -905,7 +905,7 @@ relation_open(Oid relationId, LOCKMODE lockmode) elog(ERROR, "could not open relation with OID %u", relationId); /* Make note that we've accessed a temporary relation */ - if (r->rd_istemp) + if (RelationUsesLocalBuffers(r)) MyXactAccessedTempRel = true; pgstat_initstats(r); @@ -951,7 +951,7 @@ try_relation_open(Oid relationId, LOCKMODE lockmode) elog(ERROR, "could not open relation with OID %u", relationId); /* Make note that we've accessed a temporary relation */ - if (r->rd_istemp) + if (RelationUsesLocalBuffers(r)) MyXactAccessedTempRel = true; pgstat_initstats(r); @@ -1917,7 +1917,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid, MarkBufferDirty(buffer); /* XLOG stuff */ - if (!(options & HEAP_INSERT_SKIP_WAL) && !relation->rd_istemp) + if (!(options & HEAP_INSERT_SKIP_WAL) && RelationNeedsWAL(relation)) { xl_heap_insert xlrec; xl_heap_header xlhdr; @@ -2227,7 +2227,7 @@ l1: MarkBufferDirty(buffer); /* XLOG stuff */ - if (!relation->rd_istemp) + if (RelationNeedsWAL(relation)) { xl_heap_delete xlrec; XLogRecPtr recptr; @@ -2780,7 +2780,7 @@ l2: MarkBufferDirty(buffer); /* XLOG stuff */ - if (!relation->rd_istemp) + if (RelationNeedsWAL(relation)) { XLogRecPtr recptr = log_heap_update(relation, buffer, oldtup.t_self, newbuf, heaptup, @@ -3403,7 +3403,7 @@ l3: * (Also, in a PITR log-shipping or 2PC environment, we have to have XLOG * entries for everything anyway.) */ - if (!relation->rd_istemp) + if (RelationNeedsWAL(relation)) { xl_heap_lock xlrec; XLogRecPtr recptr; @@ -3505,7 +3505,7 @@ heap_inplace_update(Relation relation, HeapTuple tuple) MarkBufferDirty(buffer); /* XLOG stuff */ - if (!relation->rd_istemp) + if (RelationNeedsWAL(relation)) { xl_heap_inplace xlrec; XLogRecPtr recptr; @@ -3867,8 +3867,8 @@ log_heap_clean(Relation reln, Buffer buffer, XLogRecPtr recptr; XLogRecData rdata[4]; - /* Caller should not call me on a temp relation */ - Assert(!reln->rd_istemp); + /* Caller should not call me on a non-WAL-logged relation */ + Assert(RelationNeedsWAL(reln)); xlrec.node = reln->rd_node; xlrec.block = BufferGetBlockNumber(buffer); @@ -3950,8 +3950,8 @@ log_heap_freeze(Relation reln, Buffer buffer, XLogRecPtr recptr; XLogRecData rdata[2]; - /* Caller should not call me on a temp relation */ - Assert(!reln->rd_istemp); + /* Caller should not call me on a non-WAL-logged relation */ + Assert(RelationNeedsWAL(reln)); /* nor when there are no tuples to freeze */ Assert(offcnt > 0); @@ -3996,8 +3996,8 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from, XLogRecData rdata[4]; Page page = BufferGetPage(newbuf); - /* Caller should not call me on a temp relation */ - Assert(!reln->rd_istemp); + /* Caller should not call me on a non-WAL-logged relation */ + Assert(RelationNeedsWAL(reln)); if (HeapTupleIsHeapOnly(newtup)) info = XLOG_HEAP_HOT_UPDATE; @@ -4997,7 +4997,7 @@ heap2_desc(StringInfo buf, uint8 xl_info, char *rec) * heap_sync - sync a heap, for use when no WAL has been written * * This forces the heap contents (including TOAST heap if any) down to disk. - * If we skipped using WAL, and it's not a temp relation, we must force the + * If we skipped using WAL, and WAL is otherwise needed, we must force the * relation down to disk before it's safe to commit the transaction. This * requires writing out any dirty buffers and then doing a forced fsync. * @@ -5010,8 +5010,8 @@ heap2_desc(StringInfo buf, uint8 xl_info, char *rec) void heap_sync(Relation rel) { - /* temp tables never need fsync */ - if (rel->rd_istemp) + /* non-WAL-logged tables never need fsync */ + if (!RelationNeedsWAL(rel)) return; /* main heap */ diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c index ee5f38fccd6..d1b08b3a8bc 100644 --- a/src/backend/access/heap/pruneheap.c +++ b/src/backend/access/heap/pruneheap.c @@ -233,7 +233,7 @@ heap_page_prune(Relation relation, Buffer buffer, TransactionId OldestXmin, /* * Emit a WAL HEAP_CLEAN record showing what we did */ - if (!relation->rd_istemp) + if (RelationNeedsWAL(relation)) { XLogRecPtr recptr; diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c index 19ca302ebb9..eb2dbffb9dd 100644 --- a/src/backend/access/heap/rewriteheap.c +++ b/src/backend/access/heap/rewriteheap.c @@ -277,8 +277,8 @@ end_heap_rewrite(RewriteState state) } /* - * If the rel isn't temp, must fsync before commit. We use heap_sync to - * ensure that the toast table gets fsync'd too. + * If the rel is WAL-logged, must fsync before commit. We use heap_sync + * to ensure that the toast table gets fsync'd too. * * It's obvious that we must do this when not WAL-logging. It's less * obvious that we have to do it even if we did WAL-log the pages. The @@ -287,7 +287,7 @@ end_heap_rewrite(RewriteState state) * occurring during the rewriteheap operation won't have fsync'd data we * wrote before the checkpoint. */ - if (!state->rs_new_rel->rd_istemp) + if (RelationNeedsWAL(state->rs_new_rel)) heap_sync(state->rs_new_rel); /* Deleting the context frees everything */ diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index eaad8122b11..ee0f04cdb5b 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -766,7 +766,7 @@ _bt_insertonpg(Relation rel, } /* XLOG stuff */ - if (!rel->rd_istemp) + if (RelationNeedsWAL(rel)) { xl_btree_insert xlrec; BlockNumber xldownlink; @@ -1165,7 +1165,7 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright, } /* XLOG stuff */ - if (!rel->rd_istemp) + if (RelationNeedsWAL(rel)) { xl_btree_split xlrec; uint8 xlinfo; @@ -1914,7 +1914,7 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf) MarkBufferDirty(metabuf); /* XLOG stuff */ - if (!rel->rd_istemp) + if (RelationNeedsWAL(rel)) { xl_btree_newroot xlrec; XLogRecPtr recptr; diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c index e0c0f21f4ef..2b4478089d8 100644 --- a/src/backend/access/nbtree/nbtpage.c +++ b/src/backend/access/nbtree/nbtpage.c @@ -224,7 +224,7 @@ _bt_getroot(Relation rel, int access) MarkBufferDirty(metabuf); /* XLOG stuff */ - if (!rel->rd_istemp) + if (RelationNeedsWAL(rel)) { xl_btree_newroot xlrec; XLogRecPtr recptr; @@ -452,7 +452,7 @@ _bt_checkpage(Relation rel, Buffer buf) static void _bt_log_reuse_page(Relation rel, BlockNumber blkno, TransactionId latestRemovedXid) { - if (rel->rd_istemp) + if (!RelationNeedsWAL(rel)) return; /* No ereport(ERROR) until changes are logged */ @@ -751,7 +751,7 @@ _bt_delitems_vacuum(Relation rel, Buffer buf, MarkBufferDirty(buf); /* XLOG stuff */ - if (!rel->rd_istemp) + if (RelationNeedsWAL(rel)) { XLogRecPtr recptr; XLogRecData rdata[2]; @@ -829,7 +829,7 @@ _bt_delitems_delete(Relation rel, Buffer buf, MarkBufferDirty(buf); /* XLOG stuff */ - if (!rel->rd_istemp) + if (RelationNeedsWAL(rel)) { XLogRecPtr recptr; XLogRecData rdata[3]; @@ -1365,7 +1365,7 @@ _bt_pagedel(Relation rel, Buffer buf, BTStack stack) MarkBufferDirty(lbuf); /* XLOG stuff */ - if (!rel->rd_istemp) + if (RelationNeedsWAL(rel)) { xl_btree_delete_page xlrec; xl_btree_metadata xlmeta; diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c index a1d3aef353e..3fb43a2e588 100644 --- a/src/backend/access/nbtree/nbtsort.c +++ b/src/backend/access/nbtree/nbtsort.c @@ -211,9 +211,9 @@ _bt_leafbuild(BTSpool *btspool, BTSpool *btspool2) /* * We need to log index creation in WAL iff WAL archiving/streaming is - * enabled AND it's not a temp index. + * enabled UNLESS the index isn't WAL-logged anyway. */ - wstate.btws_use_wal = XLogIsNeeded() && !wstate.index->rd_istemp; + wstate.btws_use_wal = XLogIsNeeded() && RelationNeedsWAL(wstate.index); /* reserve the metapage */ wstate.btws_pages_alloced = BTREE_METAPAGE + 1; @@ -797,9 +797,9 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2) _bt_uppershutdown(wstate, state); /* - * If the index isn't temp, we must fsync it down to disk before it's safe - * to commit the transaction. (For a temp index we don't care since the - * index will be uninteresting after a crash anyway.) + * If the index is WAL-logged, we must fsync it down to disk before it's + * safe to commit the transaction. (For a non-WAL-logged index we don't + * care since the index will be uninteresting after a crash anyway.) * * It's obvious that we must do this when not WAL-logging the build. It's * less obvious that we have to do it even if we did WAL-log the index @@ -811,7 +811,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2) * fsync those pages here, they might still not be on disk when the crash * occurs. */ - if (!wstate->index->rd_istemp) + if (RelationNeedsWAL(wstate->index)) { RelationOpenSmgr(wstate->index); smgrimmedsync(wstate->index->rd_smgr, MAIN_FORKNUM); diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y index e475403b9e5..73ef114d9cc 100644 --- a/src/backend/bootstrap/bootparse.y +++ b/src/backend/bootstrap/bootparse.y @@ -219,6 +219,7 @@ Boot_CreateStmt: $3, tupdesc, RELKIND_RELATION, + RELPERSISTENCE_PERMANENT, shared_relation, mapped_relation, true); @@ -238,6 +239,7 @@ Boot_CreateStmt: tupdesc, NIL, RELKIND_RELATION, + RELPERSISTENCE_PERMANENT, shared_relation, mapped_relation, true, diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c index 63225127f7a..88b5c2a215d 100644 --- a/src/backend/catalog/catalog.c +++ b/src/backend/catalog/catalog.c @@ -524,12 +524,26 @@ GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn) * created by bootstrap have preassigned OIDs, so there's no need. */ Oid -GetNewRelFileNode(Oid reltablespace, Relation pg_class, BackendId backend) +GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence) { RelFileNodeBackend rnode; char *rpath; int fd; bool collides; + BackendId backend; + + switch (relpersistence) + { + case RELPERSISTENCE_TEMP: + backend = MyBackendId; + break; + case RELPERSISTENCE_PERMANENT: + backend = InvalidBackendId; + break; + default: + elog(ERROR, "invalid relpersistence: %c", relpersistence); + return InvalidOid; /* placate compiler */ + } /* This logic should match RelationInitPhysicalAddr */ rnode.node.spcNode = reltablespace ? reltablespace : MyDatabaseTableSpace; diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 9b7668c133e..bcf6caa2eef 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -238,6 +238,7 @@ heap_create(const char *relname, Oid relid, TupleDesc tupDesc, char relkind, + char relpersistence, bool shared_relation, bool mapped_relation, bool allow_system_table_mods) @@ -311,7 +312,8 @@ heap_create(const char *relname, relid, reltablespace, shared_relation, - mapped_relation); + mapped_relation, + relpersistence); /* * Have the storage manager create the relation's disk file, if needed. @@ -322,7 +324,7 @@ heap_create(const char *relname, if (create_storage) { RelationOpenSmgr(rel); - RelationCreateStorage(rel->rd_node, rel->rd_istemp); + RelationCreateStorage(rel->rd_node, relpersistence); } return rel; @@ -693,7 +695,7 @@ InsertPgClassTuple(Relation pg_class_desc, values[Anum_pg_class_reltoastidxid - 1] = ObjectIdGetDatum(rd_rel->reltoastidxid); values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex); values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared); - values[Anum_pg_class_relistemp - 1] = BoolGetDatum(rd_rel->relistemp); + values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence); values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind); values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts); values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks); @@ -898,6 +900,7 @@ heap_create_with_catalog(const char *relname, TupleDesc tupdesc, List *cooked_constraints, char relkind, + char relpersistence, bool shared_relation, bool mapped_relation, bool oidislocal, @@ -997,8 +1000,7 @@ heap_create_with_catalog(const char *relname, } else relid = GetNewRelFileNode(reltablespace, pg_class_desc, - isTempOrToastNamespace(relnamespace) ? - MyBackendId : InvalidBackendId); + relpersistence); } /* @@ -1036,6 +1038,7 @@ heap_create_with_catalog(const char *relname, relid, tupdesc, relkind, + relpersistence, shared_relation, mapped_relation, allow_system_table_mods); diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index b437c9976a1..8fbe8ebc91d 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -545,6 +545,7 @@ index_create(Oid heapRelationId, bool is_exclusion; Oid namespaceId; int i; + char relpersistence; is_exclusion = (indexInfo->ii_ExclusionOps != NULL); @@ -561,11 +562,13 @@ index_create(Oid heapRelationId, /* * The index will be in the same namespace as its parent table, and is * shared across databases if and only if the parent is. Likewise, it - * will use the relfilenode map if and only if the parent does. + * will use the relfilenode map if and only if the parent does; and it + * inherits the parent's relpersistence. */ namespaceId = RelationGetNamespace(heapRelation); shared_relation = heapRelation->rd_rel->relisshared; mapped_relation = RelationIsMapped(heapRelation); + relpersistence = heapRelation->rd_rel->relpersistence; /* * check parameters @@ -646,9 +649,7 @@ index_create(Oid heapRelationId, else { indexRelationId = - GetNewRelFileNode(tableSpaceId, pg_class, - heapRelation->rd_istemp ? - MyBackendId : InvalidBackendId); + GetNewRelFileNode(tableSpaceId, pg_class, relpersistence); } } @@ -663,6 +664,7 @@ index_create(Oid heapRelationId, indexRelationId, indexTupDesc, RELKIND_INDEX, + relpersistence, shared_relation, mapped_relation, allow_system_table_mods); diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 653c9ada118..84cbfeb0a7d 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -235,14 +235,14 @@ RangeVarGetRelid(const RangeVar *relation, bool failOK) } /* - * If istemp is set, this is a reference to a temp relation. The parser - * never generates such a RangeVar in simple DML, but it can happen in - * contexts such as "CREATE TEMP TABLE foo (f1 int PRIMARY KEY)". Such a - * command will generate an added CREATE INDEX operation, which must be + * Some non-default relpersistence value may have been specified. The + * parser never generates such a RangeVar in simple DML, but it can happen + * in contexts such as "CREATE TEMP TABLE foo (f1 int PRIMARY KEY)". Such + * a command will generate an added CREATE INDEX operation, which must be * careful to find the temp table, even when pg_temp is not first in the * search path. */ - if (relation->istemp) + if (relation->relpersistence == RELPERSISTENCE_TEMP) { if (relation->schemaname) ereport(ERROR, @@ -308,7 +308,7 @@ RangeVarGetCreationNamespace(const RangeVar *newRelation) newRelation->relname))); } - if (newRelation->istemp) + if (newRelation->relpersistence == RELPERSISTENCE_TEMP) { /* TEMP tables are created in our backend-local temp namespace */ if (newRelation->schemaname) diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c index 0ce2051b6b1..671aaff133a 100644 --- a/src/backend/catalog/storage.c +++ b/src/backend/catalog/storage.c @@ -95,19 +95,35 @@ typedef struct xl_smgr_truncate * transaction aborts later on, the storage will be destroyed. */ void -RelationCreateStorage(RelFileNode rnode, bool istemp) +RelationCreateStorage(RelFileNode rnode, char relpersistence) { PendingRelDelete *pending; XLogRecPtr lsn; XLogRecData rdata; xl_smgr_create xlrec; SMgrRelation srel; - BackendId backend = istemp ? MyBackendId : InvalidBackendId; + BackendId backend; + bool needs_wal; + + switch (relpersistence) + { + case RELPERSISTENCE_TEMP: + backend = MyBackendId; + needs_wal = false; + break; + case RELPERSISTENCE_PERMANENT: + backend = InvalidBackendId; + needs_wal = true; + break; + default: + elog(ERROR, "invalid relpersistence: %c", relpersistence); + return; /* placate compiler */ + } srel = smgropen(rnode, backend); smgrcreate(srel, MAIN_FORKNUM, false); - if (!istemp) + if (needs_wal) { /* * Make an XLOG entry reporting the file creation. @@ -253,7 +269,7 @@ RelationTruncate(Relation rel, BlockNumber nblocks) * failure to truncate, that might spell trouble at WAL replay, into a * certain PANIC. */ - if (!rel->rd_istemp) + if (RelationNeedsWAL(rel)) { /* * Make an XLOG entry reporting the file truncation. diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c index 7bf64e22ee8..d1f6c9f3683 100644 --- a/src/backend/catalog/toasting.c +++ b/src/backend/catalog/toasting.c @@ -195,7 +195,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, Datum reloptio * Toast tables for regular relations go in pg_toast; those for temp * relations go into the per-backend temp-toast-table namespace. */ - if (rel->rd_backend == MyBackendId) + if (RelationUsesTempNamespace(rel)) namespaceid = GetTempToastNamespace(); else namespaceid = PG_TOAST_NAMESPACE; @@ -216,6 +216,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, Datum reloptio tupdesc, NIL, RELKIND_TOASTVALUE, + rel->rd_rel->relpersistence, shared_relation, mapped_relation, true, diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index e1dbd6d985b..249067f1e2d 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -675,6 +675,7 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace) tupdesc, NIL, OldHeap->rd_rel->relkind, + OldHeap->rd_rel->relpersistence, false, RelationIsMapped(OldHeap), true, @@ -789,9 +790,9 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, /* * We need to log the copied data in WAL iff WAL archiving/streaming is - * enabled AND it's not a temp rel. + * enabled AND it's not a WAL-logged rel. */ - use_wal = XLogIsNeeded() && !NewHeap->rd_istemp; + use_wal = XLogIsNeeded() && RelationNeedsWAL(NewHeap); /* use_wal off requires smgr_targblock be initially invalid */ Assert(RelationGetTargetBlock(NewHeap) == InvalidBlockNumber); diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 9407d0f02d7..09408931353 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -222,7 +222,7 @@ DefineIndex(RangeVar *heapRelation, } else { - tablespaceId = GetDefaultTablespace(rel->rd_istemp); + tablespaceId = GetDefaultTablespace(rel->rd_rel->relpersistence); /* note InvalidOid is OK in this case */ } @@ -1706,7 +1706,7 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user) continue; /* Skip temp tables of other backends; we can't reindex them at all */ - if (classtuple->relistemp && + if (classtuple->relpersistence == RELPERSISTENCE_TEMP && !isTempNamespace(classtuple->relnamespace)) continue; diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index bb8ebce25a0..e1df5fb13c7 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -366,7 +366,7 @@ fill_seq_with_data(Relation rel, HeapTuple tuple) MarkBufferDirty(buf); /* XLOG stuff */ - if (!rel->rd_istemp) + if (RelationNeedsWAL(rel)) { xl_seq_rec xlrec; XLogRecPtr recptr; @@ -448,7 +448,7 @@ AlterSequence(AlterSeqStmt *stmt) MarkBufferDirty(buf); /* XLOG stuff */ - if (!seqrel->rd_istemp) + if (RelationNeedsWAL(seqrel)) { xl_seq_rec xlrec; XLogRecPtr recptr; @@ -678,7 +678,7 @@ nextval_internal(Oid relid) MarkBufferDirty(buf); /* XLOG stuff */ - if (logit && !seqrel->rd_istemp) + if (logit && RelationNeedsWAL(seqrel)) { xl_seq_rec xlrec; XLogRecPtr recptr; @@ -855,7 +855,7 @@ do_setval(Oid relid, int64 next, bool iscalled) MarkBufferDirty(buf); /* XLOG stuff */ - if (!seqrel->rd_istemp) + if (RelationNeedsWAL(seqrel)) { xl_seq_rec xlrec; XLogRecPtr recptr; diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 937992ba585..6729d8336f5 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -224,7 +224,7 @@ static const struct dropmsgstrings dropmsgstringarray[] = { static void truncate_check_rel(Relation rel); -static List *MergeAttributes(List *schema, List *supers, bool istemp, +static List *MergeAttributes(List *schema, List *supers, char relpersistence, List **supOids, List **supconstr, int *supOidCount); static bool MergeCheckConstraint(List *constraints, char *name, Node *expr); static bool change_varattnos_walker(Node *node, const AttrNumber *newattno); @@ -339,7 +339,7 @@ static void ATPrepAddInherit(Relation child_rel); static void ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode); static void ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode); static void copy_relation_data(SMgrRelation rel, SMgrRelation dst, - ForkNumber forkNum, bool istemp); + ForkNumber forkNum, char relpersistence); static const char *storage_name(char c); @@ -391,7 +391,8 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId) /* * Check consistency of arguments */ - if (stmt->oncommit != ONCOMMIT_NOOP && !stmt->relation->istemp) + if (stmt->oncommit != ONCOMMIT_NOOP + && stmt->relation->relpersistence != RELPERSISTENCE_TEMP) ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("ON COMMIT can only be used on temporary tables"))); @@ -401,7 +402,8 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId) * code. This is needed because calling code might not expect untrusted * tables to appear in pg_temp at the front of its search path. */ - if (stmt->relation->istemp && InSecurityRestrictedOperation()) + if (stmt->relation->relpersistence == RELPERSISTENCE_TEMP + && InSecurityRestrictedOperation()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("cannot create temporary table within security-restricted operation"))); @@ -434,7 +436,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId) } else { - tablespaceId = GetDefaultTablespace(stmt->relation->istemp); + tablespaceId = GetDefaultTablespace(stmt->relation->relpersistence); /* note InvalidOid is OK in this case */ } @@ -478,7 +480,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId) * inherited attributes. */ schema = MergeAttributes(schema, stmt->inhRelations, - stmt->relation->istemp, + stmt->relation->relpersistence, &inheritOids, &old_constraints, &parentOidCount); /* @@ -557,6 +559,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId) list_concat(cookedDefaults, old_constraints), relkind, + stmt->relation->relpersistence, false, false, localHasOids, @@ -1208,7 +1211,7 @@ storage_name(char c) *---------- */ static List * -MergeAttributes(List *schema, List *supers, bool istemp, +MergeAttributes(List *schema, List *supers, char relpersistence, List **supOids, List **supconstr, int *supOidCount) { ListCell *entry; @@ -1316,7 +1319,8 @@ MergeAttributes(List *schema, List *supers, bool istemp, errmsg("inherited relation \"%s\" is not a table", parent->relname))); /* Permanent rels cannot inherit from temporary ones */ - if (!istemp && relation->rd_istemp) + if (relpersistence != RELPERSISTENCE_TEMP + && RelationUsesTempNamespace(relation)) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot inherit from temporary relation \"%s\"", @@ -5124,26 +5128,27 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, RelationGetRelationName(pkrel)))); /* - * Disallow reference from permanent table to temp table or vice versa. - * (The ban on perm->temp is for fairly obvious reasons. The ban on - * temp->perm is because other backends might need to run the RI triggers - * on the perm table, but they can't reliably see tuples the owning - * backend has created in the temp table, because non-shared buffers are - * used for temp tables.) + * References from permanent tables to temp tables are disallowed because + * the contents of the temp table disappear at the end of each session. + * References from temp tables to permanent tables are also disallowed, + * because other backends might need to run the RI triggers on the perm + * table, but they can't reliably see tuples in the local buffers of other + * backends. */ - if (pkrel->rd_istemp) + switch (rel->rd_rel->relpersistence) { - if (!rel->rd_istemp) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TABLE_DEFINITION), - errmsg("cannot reference temporary table from permanent table constraint"))); - } - else - { - if (rel->rd_istemp) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TABLE_DEFINITION), - errmsg("cannot reference permanent table from temporary table constraint"))); + case RELPERSISTENCE_PERMANENT: + if (pkrel->rd_rel->relpersistence != RELPERSISTENCE_PERMANENT) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("constraints on permanent tables may reference only permanent tables"))); + break; + case RELPERSISTENCE_TEMP: + if (pkrel->rd_rel->relpersistence != RELPERSISTENCE_TEMP) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("constraints on temporary tables may reference only temporary tables"))); + break; } /* @@ -7347,7 +7352,8 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode) * Relfilenodes are not unique across tablespaces, so we need to allocate * a new one in the new tablespace. */ - newrelfilenode = GetNewRelFileNode(newTableSpace, NULL, rel->rd_backend); + newrelfilenode = GetNewRelFileNode(newTableSpace, NULL, + rel->rd_rel->relpersistence); /* Open old and new relation */ newrnode = rel->rd_node; @@ -7364,10 +7370,11 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode) * NOTE: any conflict in relfilenode value will be caught in * RelationCreateStorage(). */ - RelationCreateStorage(newrnode, rel->rd_istemp); + RelationCreateStorage(newrnode, rel->rd_rel->relpersistence); /* copy main fork */ - copy_relation_data(rel->rd_smgr, dstrel, MAIN_FORKNUM, rel->rd_istemp); + copy_relation_data(rel->rd_smgr, dstrel, MAIN_FORKNUM, + rel->rd_rel->relpersistence); /* copy those extra forks that exist */ for (forkNum = MAIN_FORKNUM + 1; forkNum <= MAX_FORKNUM; forkNum++) @@ -7375,7 +7382,8 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode) if (smgrexists(rel->rd_smgr, forkNum)) { smgrcreate(dstrel, forkNum, false); - copy_relation_data(rel->rd_smgr, dstrel, forkNum, rel->rd_istemp); + copy_relation_data(rel->rd_smgr, dstrel, forkNum, + rel->rd_rel->relpersistence); } } @@ -7410,7 +7418,7 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode) */ static void copy_relation_data(SMgrRelation src, SMgrRelation dst, - ForkNumber forkNum, bool istemp) + ForkNumber forkNum, char relpersistence) { char *buf; Page page; @@ -7429,9 +7437,9 @@ copy_relation_data(SMgrRelation src, SMgrRelation dst, /* * We need to log the copied data in WAL iff WAL archiving/streaming is - * enabled AND it's not a temp rel. + * enabled AND it's a permanent relation. */ - use_wal = XLogIsNeeded() && !istemp; + use_wal = XLogIsNeeded() && relpersistence == RELPERSISTENCE_PERMANENT; nblocks = smgrnblocks(src, forkNum); @@ -7470,7 +7478,7 @@ copy_relation_data(SMgrRelation src, SMgrRelation dst, * wouldn't replay our earlier WAL entries. If we do not fsync those pages * here, they might still not be on disk when the crash occurs. */ - if (!istemp) + if (relpersistence == RELPERSISTENCE_PERMANENT) smgrimmedsync(dst, forkNum); } @@ -7538,7 +7546,8 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode) ATSimplePermissions(parent_rel, false, false); /* Permanent rels cannot inherit from temporary ones */ - if (parent_rel->rd_istemp && !child_rel->rd_istemp) + if (RelationUsesTempNamespace(parent_rel) + && !RelationUsesTempNamespace(child_rel)) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot inherit from temporary relation \"%s\"", diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index cd80c811a92..5ad08314049 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -1050,8 +1050,8 @@ assign_default_tablespace(const char *newval, bool doit, GucSource source) /* * GetDefaultTablespace -- get the OID of the current default tablespace * - * Regular objects and temporary objects have different default tablespaces, - * hence the forTemp parameter must be specified. + * Temporary objects have different default tablespaces, hence the + * relpersistence parameter must be specified. * * May return InvalidOid to indicate "use the database's default tablespace". * @@ -1062,12 +1062,12 @@ assign_default_tablespace(const char *newval, bool doit, GucSource source) * default_tablespace GUC variable. */ Oid -GetDefaultTablespace(bool forTemp) +GetDefaultTablespace(char relpersistence) { Oid result; /* The temp-table case is handled elsewhere */ - if (forTemp) + if (relpersistence == RELPERSISTENCE_TEMP) { PrepareTempTablespaces(); return GetNextTempTableSpace(); diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index 0ac993f957d..cbdf97de91b 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -268,10 +268,10 @@ static void vacuum_log_cleanup_info(Relation rel, LVRelStats *vacrelstats) { /* - * No need to log changes for temp tables, they do not contain data - * visible on the standby server. + * Skip this for relations for which no WAL is to be written, or if we're + * not trying to support archive recovery. */ - if (rel->rd_istemp || !XLogIsNeeded()) + if (!RelationNeedsWAL(rel) || !XLogIsNeeded()) return; /* @@ -664,8 +664,7 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, if (nfrozen > 0) { MarkBufferDirty(buf); - /* no XLOG for temp tables, though */ - if (!onerel->rd_istemp) + if (RelationNeedsWAL(onerel)) { XLogRecPtr recptr; @@ -895,7 +894,7 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, MarkBufferDirty(buffer); /* XLOG stuff */ - if (!onerel->rd_istemp) + if (RelationNeedsWAL(onerel)) { XLogRecPtr recptr; diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index 09ab24b0116..2b2b9085005 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -68,10 +68,10 @@ isViewOnTempTable_walker(Node *node, void *context) if (rte->rtekind == RTE_RELATION) { Relation rel = heap_open(rte->relid, AccessShareLock); - bool istemp = rel->rd_istemp; + char relpersistence = rel->rd_rel->relpersistence; heap_close(rel, AccessShareLock); - if (istemp) + if (relpersistence == RELPERSISTENCE_TEMP) return true; } } @@ -173,9 +173,9 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace) /* * Due to the namespace visibility rules for temporary objects, we * should only end up replacing a temporary view with another - * temporary view, and vice versa. + * temporary view, and similarly for permanent views. */ - Assert(relation->istemp == rel->rd_istemp); + Assert(relation->relpersistence == rel->rd_rel->relpersistence); /* * Create a tuple descriptor to compare against the existing view, and @@ -454,10 +454,11 @@ DefineView(ViewStmt *stmt, const char *queryString) * schema name. */ view = stmt->view; - if (!view->istemp && isViewOnTempTable(viewParse)) + if (view->relpersistence == RELPERSISTENCE_PERMANENT + && isViewOnTempTable(viewParse)) { view = copyObject(view); /* don't corrupt original command */ - view->istemp = true; + view->relpersistence = RELPERSISTENCE_TEMP; ereport(NOTICE, (errmsg("view \"%s\" will be a temporary view", view->relname))); diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 69f3a28d415..c4719f33b96 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -2131,7 +2131,8 @@ OpenIntoRel(QueryDesc *queryDesc) /* * Check consistency of arguments */ - if (into->onCommit != ONCOMMIT_NOOP && !into->rel->istemp) + if (into->onCommit != ONCOMMIT_NOOP + && into->rel->relpersistence != RELPERSISTENCE_TEMP) ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("ON COMMIT can only be used on temporary tables"))); @@ -2141,7 +2142,8 @@ OpenIntoRel(QueryDesc *queryDesc) * code. This is needed because calling code might not expect untrusted * tables to appear in pg_temp at the front of its search path. */ - if (into->rel->istemp && InSecurityRestrictedOperation()) + if (into->rel->relpersistence == RELPERSISTENCE_TEMP + && InSecurityRestrictedOperation()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("cannot create temporary table within security-restricted operation"))); @@ -2168,7 +2170,7 @@ OpenIntoRel(QueryDesc *queryDesc) } else { - tablespaceId = GetDefaultTablespace(into->rel->istemp); + tablespaceId = GetDefaultTablespace(into->rel->relpersistence); /* note InvalidOid is OK in this case */ } @@ -2208,6 +2210,7 @@ OpenIntoRel(QueryDesc *queryDesc) tupdesc, NIL, RELKIND_RELATION, + into->rel->relpersistence, false, false, true, diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 735322ee3f5..4e1f221af1b 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -958,7 +958,7 @@ _copyRangeVar(RangeVar *from) COPY_STRING_FIELD(schemaname); COPY_STRING_FIELD(relname); COPY_SCALAR_FIELD(inhOpt); - COPY_SCALAR_FIELD(istemp); + COPY_SCALAR_FIELD(relpersistence); COPY_NODE_FIELD(alias); COPY_LOCATION_FIELD(location); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 2d2b8c77634..85cded0f74d 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -104,7 +104,7 @@ _equalRangeVar(RangeVar *a, RangeVar *b) COMPARE_STRING_FIELD(schemaname); COMPARE_STRING_FIELD(relname); COMPARE_SCALAR_FIELD(inhOpt); - COMPARE_SCALAR_FIELD(istemp); + COMPARE_SCALAR_FIELD(relpersistence); COMPARE_NODE_FIELD(alias); COMPARE_LOCATION_FIELD(location); diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index 4b268f3c6b3..f06f73bd6ac 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -15,6 +15,7 @@ */ #include "postgres.h" +#include "catalog/pg_class.h" #include "catalog/pg_type.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" @@ -378,7 +379,7 @@ makeRangeVar(char *schemaname, char *relname, int location) r->schemaname = schemaname; r->relname = relname; r->inhOpt = INH_DEFAULT; - r->istemp = false; + r->relpersistence = RELPERSISTENCE_PERMANENT; r->alias = NULL; r->location = location; diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 5d09e16477d..7d77d84a370 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -841,7 +841,7 @@ _outRangeVar(StringInfo str, RangeVar *node) WRITE_STRING_FIELD(schemaname); WRITE_STRING_FIELD(relname); WRITE_ENUM_FIELD(inhOpt, InhOption); - WRITE_BOOL_FIELD(istemp); + WRITE_CHAR_FIELD(relpersistence); WRITE_NODE_FIELD(alias); WRITE_LOCATION_FIELD(location); } diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 2166a5d1e0e..933d58ada5f 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -373,7 +373,7 @@ _readRangeVar(void) READ_STRING_FIELD(schemaname); READ_STRING_FIELD(relname); READ_ENUM_FIELD(inhOpt, InhOption); - READ_BOOL_FIELD(istemp); + READ_CHAR_FIELD(relpersistence); READ_NODE_FIELD(alias); READ_LOCATION_FIELD(location); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 9ec75f776cf..8fc79b63377 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -311,7 +311,8 @@ static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_ %type <fun_param_mode> arg_class %type <typnam> func_return func_type -%type <boolean> OptTemp opt_trusted opt_restart_seqs +%type <boolean> opt_trusted opt_restart_seqs +%type <ival> OptTemp %type <oncommit> OnCommitOption %type <node> for_locking_item @@ -2280,7 +2281,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' OptInherit OptWith OnCommitOption OptTableSpace { CreateStmt *n = makeNode(CreateStmt); - $4->istemp = $2; + $4->relpersistence = $2; n->relation = $4; n->tableElts = $6; n->inhRelations = $8; @@ -2296,7 +2297,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' OptTableSpace { CreateStmt *n = makeNode(CreateStmt); - $7->istemp = $2; + $7->relpersistence = $2; n->relation = $7; n->tableElts = $9; n->inhRelations = $11; @@ -2311,7 +2312,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' OptTypedTableElementList OptWith OnCommitOption OptTableSpace { CreateStmt *n = makeNode(CreateStmt); - $4->istemp = $2; + $4->relpersistence = $2; n->relation = $4; n->tableElts = $7; n->ofTypename = makeTypeNameFromNameList($6); @@ -2327,7 +2328,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' OptTypedTableElementList OptWith OnCommitOption OptTableSpace { CreateStmt *n = makeNode(CreateStmt); - $7->istemp = $2; + $7->relpersistence = $2; n->relation = $7; n->tableElts = $10; n->ofTypename = makeTypeNameFromNameList($9); @@ -2348,13 +2349,13 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' * NOTE: we accept both GLOBAL and LOCAL options; since we have no modules * the LOCAL keyword is really meaningless. */ -OptTemp: TEMPORARY { $$ = TRUE; } - | TEMP { $$ = TRUE; } - | LOCAL TEMPORARY { $$ = TRUE; } - | LOCAL TEMP { $$ = TRUE; } - | GLOBAL TEMPORARY { $$ = TRUE; } - | GLOBAL TEMP { $$ = TRUE; } - | /*EMPTY*/ { $$ = FALSE; } +OptTemp: TEMPORARY { $$ = RELPERSISTENCE_TEMP; } + | TEMP { $$ = RELPERSISTENCE_TEMP; } + | LOCAL TEMPORARY { $$ = RELPERSISTENCE_TEMP; } + | LOCAL TEMP { $$ = RELPERSISTENCE_TEMP; } + | GLOBAL TEMPORARY { $$ = RELPERSISTENCE_TEMP; } + | GLOBAL TEMP { $$ = RELPERSISTENCE_TEMP; } + | /*EMPTY*/ { $$ = RELPERSISTENCE_PERMANENT; } ; OptTableElementList: @@ -2834,7 +2835,7 @@ CreateAsStmt: (errcode(ERRCODE_SYNTAX_ERROR), errmsg("CREATE TABLE AS cannot specify INTO"), parser_errposition(exprLocation((Node *) n->intoClause)))); - $4->rel->istemp = $2; + $4->rel->relpersistence = $2; n->intoClause = $4; /* Implement WITH NO DATA by forcing top-level LIMIT 0 */ if (!$7) @@ -2900,7 +2901,7 @@ CreateSeqStmt: CREATE OptTemp SEQUENCE qualified_name OptSeqOptList { CreateSeqStmt *n = makeNode(CreateSeqStmt); - $4->istemp = $2; + $4->relpersistence = $2; n->sequence = $4; n->options = $5; n->ownerId = InvalidOid; @@ -6621,7 +6622,7 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list { ViewStmt *n = makeNode(ViewStmt); n->view = $4; - n->view->istemp = $2; + n->view->relpersistence = $2; n->aliases = $5; n->query = $7; n->replace = false; @@ -6632,7 +6633,7 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list { ViewStmt *n = makeNode(ViewStmt); n->view = $6; - n->view->istemp = $4; + n->view->relpersistence = $4; n->aliases = $7; n->query = $9; n->replace = true; @@ -7328,7 +7329,7 @@ ExecuteStmt: EXECUTE name execute_param_clause ExecuteStmt *n = makeNode(ExecuteStmt); n->name = $7; n->params = $8; - $4->rel->istemp = $2; + $4->rel->relpersistence = $2; n->into = $4; if ($4->colNames) ereport(ERROR, @@ -7889,42 +7890,42 @@ OptTempTableName: TEMPORARY opt_table qualified_name { $$ = $3; - $$->istemp = true; + $$->relpersistence = RELPERSISTENCE_TEMP; } | TEMP opt_table qualified_name { $$ = $3; - $$->istemp = true; + $$->relpersistence = RELPERSISTENCE_TEMP; } | LOCAL TEMPORARY opt_table qualified_name { $$ = $4; - $$->istemp = true; + $$->relpersistence = RELPERSISTENCE_TEMP; } | LOCAL TEMP opt_table qualified_name { $$ = $4; - $$->istemp = true; + $$->relpersistence = RELPERSISTENCE_TEMP; } | GLOBAL TEMPORARY opt_table qualified_name { $$ = $4; - $$->istemp = true; + $$->relpersistence = RELPERSISTENCE_TEMP; } | GLOBAL TEMP opt_table qualified_name { $$ = $4; - $$->istemp = true; + $$->relpersistence = RELPERSISTENCE_TEMP; } | TABLE qualified_name { $$ = $2; - $$->istemp = false; + $$->relpersistence = RELPERSISTENCE_PERMANENT; } | qualified_name { $$ = $1; - $$->istemp = false; + $$->relpersistence = RELPERSISTENCE_PERMANENT; } ; @@ -10916,16 +10917,12 @@ qualified_name_list: qualified_name: ColId { - $$ = makeNode(RangeVar); - $$->catalogname = NULL; - $$->schemaname = NULL; - $$->relname = $1; - $$->location = @1; + $$ = makeRangeVar(NULL, $1, @1); } | ColId indirection { check_qualified_name($2, yyscanner); - $$ = makeNode(RangeVar); + $$ = makeRangeVar(NULL, NULL, @1); switch (list_length($2)) { case 1: @@ -10946,7 +10943,6 @@ qualified_name: parser_errposition(@1))); break; } - $$->location = @1; } ; @@ -12163,6 +12159,7 @@ makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner) break; } + r->relpersistence = RELPERSISTENCE_PERMANENT; r->location = position; return r; diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index a8aee204c74..aa7c144c941 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -158,10 +158,11 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) * If the target relation name isn't schema-qualified, make it so. This * prevents some corner cases in which added-on rewritten commands might * think they should apply to other relations that have the same name and - * are earlier in the search path. "istemp" is equivalent to a - * specification of pg_temp, so no need for anything extra in that case. + * are earlier in the search path. But a local temp table is effectively + * specified to be in pg_temp, so no need for anything extra in that case. */ - if (stmt->relation->schemaname == NULL && !stmt->relation->istemp) + if (stmt->relation->schemaname == NULL + && stmt->relation->relpersistence != RELPERSISTENCE_TEMP) { Oid namespaceid = RangeVarGetCreationNamespace(stmt->relation); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c7d704dc8c8..89b2540871c 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -1975,7 +1975,7 @@ do_autovacuum(void) * Check if it is a temp table (presumably, of some other backend's). * We cannot safely process other backends' temp tables. */ - if (classForm->relistemp) + if (classForm->relpersistence == RELPERSISTENCE_TEMP) { int backendID; @@ -2072,7 +2072,7 @@ do_autovacuum(void) /* * We cannot safely process other backends' temp tables, so skip 'em. */ - if (classForm->relistemp) + if (classForm->relpersistence == RELPERSISTENCE_TEMP) continue; relid = HeapTupleGetOid(tuple); diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index edc497788df..860e736ff05 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -123,7 +123,7 @@ PrefetchBuffer(Relation reln, ForkNumber forkNum, BlockNumber blockNum) /* Open it at the smgr level if not already done */ RelationOpenSmgr(reln); - if (reln->rd_istemp) + if (RelationUsesLocalBuffers(reln)) { /* see comments in ReadBufferExtended */ if (RELATION_IS_OTHER_TEMP(reln)) @@ -2071,7 +2071,7 @@ FlushRelationBuffers(Relation rel) /* Open rel at the smgr level if not already done */ RelationOpenSmgr(rel); - if (rel->rd_istemp) + if (RelationUsesLocalBuffers(rel)) { for (i = 0; i < NLocBuffer; i++) { diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index f5250a263cd..e352cdafb3b 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -612,16 +612,26 @@ pg_relation_filepath(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } - /* If temporary, determine owning backend. */ - if (!relform->relistemp) - backend = InvalidBackendId; - else if (isTempOrToastNamespace(relform->relnamespace)) - backend = MyBackendId; - else + /* Determine owning backend. */ + switch (relform->relpersistence) { - /* Do it the hard way. */ - backend = GetTempNamespaceBackendId(relform->relnamespace); - Assert(backend != InvalidBackendId); + case RELPERSISTENCE_PERMANENT: + backend = InvalidBackendId; + break; + case RELPERSISTENCE_TEMP: + if (isTempOrToastNamespace(relform->relnamespace)) + backend = MyBackendId; + else + { + /* Do it the hard way. */ + backend = GetTempNamespaceBackendId(relform->relnamespace); + Assert(backend != InvalidBackendId); + } + break; + default: + elog(ERROR, "invalid relpersistence: %c", relform->relpersistence); + backend = InvalidBackendId; /* placate compiler */ + break; } ReleaseSysCache(tuple); diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 8df12a14243..1509686079b 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -849,20 +849,30 @@ RelationBuildDesc(Oid targetRelId, bool insertIt) relation->rd_isnailed = false; relation->rd_createSubid = InvalidSubTransactionId; relation->rd_newRelfilenodeSubid = InvalidSubTransactionId; - relation->rd_istemp = relation->rd_rel->relistemp; - if (!relation->rd_istemp) - relation->rd_backend = InvalidBackendId; - else if (isTempOrToastNamespace(relation->rd_rel->relnamespace)) - relation->rd_backend = MyBackendId; - else + switch (relation->rd_rel->relpersistence) { - /* - * If it's a temporary table, but not one of ours, we have to use - * the slow, grotty method to figure out the owning backend. - */ - relation->rd_backend = - GetTempNamespaceBackendId(relation->rd_rel->relnamespace); - Assert(relation->rd_backend != InvalidBackendId); + case RELPERSISTENCE_PERMANENT: + relation->rd_backend = InvalidBackendId; + break; + case RELPERSISTENCE_TEMP: + if (isTempOrToastNamespace(relation->rd_rel->relnamespace)) + relation->rd_backend = MyBackendId; + 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. + */ + relation->rd_backend = + GetTempNamespaceBackendId(relation->rd_rel->relnamespace); + Assert(relation->rd_backend != InvalidBackendId); + } + break; + default: + elog(ERROR, "invalid relpersistence: %c", + relation->rd_rel->relpersistence); + break; } /* @@ -1358,7 +1368,6 @@ formrdesc(const char *relationName, Oid relationReltype, relation->rd_isnailed = true; relation->rd_createSubid = InvalidSubTransactionId; relation->rd_newRelfilenodeSubid = InvalidSubTransactionId; - relation->rd_istemp = false; relation->rd_backend = InvalidBackendId; /* @@ -1384,11 +1393,8 @@ formrdesc(const char *relationName, Oid relationReltype, if (isshared) relation->rd_rel->reltablespace = GLOBALTABLESPACE_OID; - /* - * Likewise, we must know if a relation is temp ... but formrdesc is not - * used for any temp relations. - */ - relation->rd_rel->relistemp = false; + /* formrdesc is used only for permanent relations */ + relation->rd_rel->relpersistence = RELPERSISTENCE_PERMANENT; relation->rd_rel->relpages = 1; relation->rd_rel->reltuples = 1; @@ -2366,7 +2372,8 @@ RelationBuildLocalRelation(const char *relname, Oid relid, Oid reltablespace, bool shared_relation, - bool mapped_relation) + bool mapped_relation, + char relpersistence) { Relation rel; MemoryContext oldcxt; @@ -2440,10 +2447,6 @@ RelationBuildLocalRelation(const char *relname, /* must flag that we have rels created in this transaction */ need_eoxact_work = true; - /* it is temporary if and only if it is in my temp-table namespace */ - rel->rd_istemp = isTempOrToastNamespace(relnamespace); - rel->rd_backend = rel->rd_istemp ? MyBackendId : InvalidBackendId; - /* * create a new tuple descriptor from the one passed in. We do this * partly to copy it into the cache context, and partly because the new @@ -2483,6 +2486,21 @@ RelationBuildLocalRelation(const char *relname, /* needed when bootstrapping: */ rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID; + /* set up persistence; rd_backend is a function of persistence type */ + rel->rd_rel->relpersistence = relpersistence; + switch (relpersistence) + { + case RELPERSISTENCE_PERMANENT: + rel->rd_backend = InvalidBackendId; + break; + case RELPERSISTENCE_TEMP: + rel->rd_backend = MyBackendId; + break; + default: + elog(ERROR, "invalid relpersistence: %c", relpersistence); + break; + } + /* * Insert relation physical and logical identifiers (OIDs) into the right * places. Note that the physical ID (relfilenode) is initially the same @@ -2491,7 +2509,6 @@ RelationBuildLocalRelation(const char *relname, * map. */ rel->rd_rel->relisshared = shared_relation; - rel->rd_rel->relistemp = rel->rd_istemp; RelationGetRelid(rel) = relid; @@ -2569,7 +2586,7 @@ RelationSetNewRelfilenode(Relation relation, TransactionId freezeXid) /* Allocate a new relfilenode */ newrelfilenode = GetNewRelFileNode(relation->rd_rel->reltablespace, NULL, - relation->rd_backend); + relation->rd_rel->relpersistence); /* * Get a writable copy of the pg_class tuple for the given relation. @@ -2592,7 +2609,7 @@ RelationSetNewRelfilenode(Relation relation, TransactionId freezeXid) newrnode.node = relation->rd_node; newrnode.node.relNode = newrelfilenode; newrnode.backend = relation->rd_backend; - RelationCreateStorage(newrnode.node, relation->rd_istemp); + RelationCreateStorage(newrnode.node, relation->rd_rel->relpersistence); smgrclosenode(newrnode); /* diff --git a/src/include/catalog/catalog.h b/src/include/catalog/catalog.h index 97c808bc509..56dcdd53fe2 100644 --- a/src/include/catalog/catalog.h +++ b/src/include/catalog/catalog.h @@ -56,6 +56,6 @@ extern Oid GetNewOid(Relation relation); extern Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn); extern Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class, - BackendId backend); + char relpersistence); #endif /* CATALOG_H */ diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 6c12f7cbf82..1c3d14951c0 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201012031 +#define CATALOG_VERSION_NO 201012131 #endif diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index 7795bda323b..646ab9c8f19 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -40,6 +40,7 @@ extern Relation heap_create(const char *relname, Oid relid, TupleDesc tupDesc, char relkind, + char relpersistence, bool shared_relation, bool mapped_relation, bool allow_system_table_mods); @@ -54,6 +55,7 @@ extern Oid heap_create_with_catalog(const char *relname, TupleDesc tupdesc, List *cooked_constraints, char relkind, + char relpersistence, bool shared_relation, bool mapped_relation, bool oidislocal, diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h index f50cf9d55bb..1edbfe378b1 100644 --- a/src/include/catalog/pg_class.h +++ b/src/include/catalog/pg_class.h @@ -49,7 +49,7 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83) BKI_SCHEMA_MACRO Oid reltoastidxid; /* if toast table, OID of chunk_id index */ bool relhasindex; /* T if has (or has had) any indexes */ bool relisshared; /* T if shared across databases */ - bool relistemp; /* T if temporary relation */ + char relpersistence; /* see RELPERSISTENCE_xxx constants */ char relkind; /* see RELKIND_xxx constants below */ int2 relnatts; /* number of user attributes */ @@ -108,7 +108,7 @@ typedef FormData_pg_class *Form_pg_class; #define Anum_pg_class_reltoastidxid 12 #define Anum_pg_class_relhasindex 13 #define Anum_pg_class_relisshared 14 -#define Anum_pg_class_relistemp 15 +#define Anum_pg_class_relpersistence 15 #define Anum_pg_class_relkind 16 #define Anum_pg_class_relnatts 17 #define Anum_pg_class_relchecks 18 @@ -132,13 +132,13 @@ typedef FormData_pg_class *Form_pg_class; */ /* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId */ -DATA(insert OID = 1247 ( pg_type PGNSP 71 0 PGUID 0 0 0 0 0 0 0 f f f r 28 0 t f f f f f 3 _null_ _null_ )); +DATA(insert OID = 1247 ( pg_type PGNSP 71 0 PGUID 0 0 0 0 0 0 0 f f p r 28 0 t f f f f f 3 _null_ _null_ )); DESCR(""); -DATA(insert OID = 1249 ( pg_attribute PGNSP 75 0 PGUID 0 0 0 0 0 0 0 f f f r 19 0 f f f f f f 3 _null_ _null_ )); +DATA(insert OID = 1249 ( pg_attribute PGNSP 75 0 PGUID 0 0 0 0 0 0 0 f f p r 19 0 f f f f f f 3 _null_ _null_ )); DESCR(""); -DATA(insert OID = 1255 ( pg_proc PGNSP 81 0 PGUID 0 0 0 0 0 0 0 f f f r 25 0 t f f f f f 3 _null_ _null_ )); +DATA(insert OID = 1255 ( pg_proc PGNSP 81 0 PGUID 0 0 0 0 0 0 0 f f p r 25 0 t f f f f f 3 _null_ _null_ )); DESCR(""); -DATA(insert OID = 1259 ( pg_class PGNSP 83 0 PGUID 0 0 0 0 0 0 0 f f f r 27 0 t f f f f f 3 _null_ _null_ )); +DATA(insert OID = 1259 ( pg_class PGNSP 83 0 PGUID 0 0 0 0 0 0 0 f f p r 27 0 t f f f f f 3 _null_ _null_ )); DESCR(""); #define RELKIND_INDEX 'i' /* secondary index */ @@ -149,4 +149,7 @@ DESCR(""); #define RELKIND_VIEW 'v' /* view */ #define RELKIND_COMPOSITE_TYPE 'c' /* composite type */ +#define RELPERSISTENCE_PERMANENT 'p' +#define RELPERSISTENCE_TEMP 't' + #endif /* PG_CLASS_H */ diff --git a/src/include/catalog/storage.h b/src/include/catalog/storage.h index d7b8731838c..f086b1c33f6 100644 --- a/src/include/catalog/storage.h +++ b/src/include/catalog/storage.h @@ -20,7 +20,7 @@ #include "storage/relfilenode.h" #include "utils/relcache.h" -extern void RelationCreateStorage(RelFileNode rnode, bool istemp); +extern void RelationCreateStorage(RelFileNode rnode, char relpersistence); extern void RelationDropStorage(Relation rel); extern void RelationPreserveStorage(RelFileNode rnode); extern void RelationTruncate(Relation rel, BlockNumber nblocks); diff --git a/src/include/commands/tablespace.h b/src/include/commands/tablespace.h index 327fbc6c4f9..1e3f6ca0c62 100644 --- a/src/include/commands/tablespace.h +++ b/src/include/commands/tablespace.h @@ -47,7 +47,7 @@ extern void AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt); extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo); -extern Oid GetDefaultTablespace(bool forTemp); +extern Oid GetDefaultTablespace(char relpersistence); extern void PrepareTempTablespaces(void); diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index b17adf2aa3f..ba5ae371c01 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -74,7 +74,7 @@ typedef struct RangeVar char *relname; /* the relation/sequence name */ InhOption inhOpt; /* expand rel by inheritance? recursively act * on children? */ - bool istemp; /* is this a temp relation/sequence? */ + char relpersistence; /* see RELPERSISTENCE_* in pg_class.h */ Alias *alias; /* table alias & optional column aliases */ int location; /* token location, or -1 if unknown */ } RangeVar; diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index 39e0365c0b1..88a3168d133 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -132,7 +132,6 @@ typedef struct RelationData struct SMgrRelationData *rd_smgr; /* cached file handle, or NULL */ int rd_refcnt; /* reference count */ BackendId rd_backend; /* owning backend id, if temporary relation */ - bool rd_istemp; /* rel is a temporary relation */ bool rd_isnailed; /* rel is nailed in cache */ bool rd_isvalid; /* relcache entry is valid */ char rd_indexvalid; /* state of rd_indexlist: 0 = not valid, 1 = @@ -390,6 +389,27 @@ typedef struct StdRdOptions } while (0) /* + * RelationNeedsWAL + * True if relation needs WAL. + */ +#define RelationNeedsWAL(relation) \ + ((relation)->rd_rel->relpersistence == RELPERSISTENCE_PERMANENT) + +/* + * RelationUsesLocalBuffers + * True if relation's pages are stored in local buffers. + */ +#define RelationUsesLocalBuffers(relation) \ + ((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP) + +/* + * RelationUsesTempNamespace + * True if relation's catalog entries live in a private namespace. + */ +#define RelationUsesTempNamespace(relation) \ + ((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP) + +/* * RELATION_IS_LOCAL * If a rel is either temp or newly created in the current transaction, * it can be assumed to be visible only to the current backend. @@ -407,7 +427,8 @@ typedef struct StdRdOptions * Beware of multiple eval of argument */ #define RELATION_IS_OTHER_TEMP(relation) \ - ((relation)->rd_istemp && (relation)->rd_backend != MyBackendId) + ((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP \ + && (relation)->rd_backend != MyBackendId) /* routines in utils/cache/relcache.c */ extern void RelationIncrementReferenceCount(Relation rel); diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h index 10d82d4b412..35000500c11 100644 --- a/src/include/utils/relcache.h +++ b/src/include/utils/relcache.h @@ -69,7 +69,8 @@ extern Relation RelationBuildLocalRelation(const char *relname, Oid relid, Oid reltablespace, bool shared_relation, - bool mapped_relation); + bool mapped_relation, + char relpersistence); /* * Routine to manage assignment of new relfilenode to a relation |