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.
This commit is contained in:
parent
0c90442355
commit
5f7b58fad8
@ -304,7 +304,7 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
|
|||||||
|
|
||||||
MarkBufferDirty(stack->buffer);
|
MarkBufferDirty(stack->buffer);
|
||||||
|
|
||||||
if (!btree->index->rd_istemp)
|
if (RelationNeedsWAL(btree->index))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
|
|
||||||
@ -373,7 +373,7 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
|
|||||||
MarkBufferDirty(lbuffer);
|
MarkBufferDirty(lbuffer);
|
||||||
MarkBufferDirty(stack->buffer);
|
MarkBufferDirty(stack->buffer);
|
||||||
|
|
||||||
if (!btree->index->rd_istemp)
|
if (RelationNeedsWAL(btree->index))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
|
|
||||||
@ -422,7 +422,7 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
|
|||||||
MarkBufferDirty(rbuffer);
|
MarkBufferDirty(rbuffer);
|
||||||
MarkBufferDirty(stack->buffer);
|
MarkBufferDirty(stack->buffer);
|
||||||
|
|
||||||
if (!btree->index->rd_istemp)
|
if (RelationNeedsWAL(btree->index))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ writeListPage(Relation index, Buffer buffer,
|
|||||||
|
|
||||||
MarkBufferDirty(buffer);
|
MarkBufferDirty(buffer);
|
||||||
|
|
||||||
if (!index->rd_istemp)
|
if (RelationNeedsWAL(index))
|
||||||
{
|
{
|
||||||
XLogRecData rdata[2];
|
XLogRecData rdata[2];
|
||||||
ginxlogInsertListPage data;
|
ginxlogInsertListPage data;
|
||||||
@ -384,7 +384,7 @@ ginHeapTupleFastInsert(Relation index, GinState *ginstate,
|
|||||||
*/
|
*/
|
||||||
MarkBufferDirty(metabuffer);
|
MarkBufferDirty(metabuffer);
|
||||||
|
|
||||||
if (!index->rd_istemp)
|
if (RelationNeedsWAL(index))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
|
|
||||||
@ -564,7 +564,7 @@ shiftList(Relation index, Buffer metabuffer, BlockNumber newHead,
|
|||||||
MarkBufferDirty(buffers[i]);
|
MarkBufferDirty(buffers[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!index->rd_istemp)
|
if (RelationNeedsWAL(index))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems)
|
|||||||
|
|
||||||
MarkBufferDirty(buffer);
|
MarkBufferDirty(buffer);
|
||||||
|
|
||||||
if (!index->rd_istemp)
|
if (RelationNeedsWAL(index))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
XLogRecData rdata[2];
|
XLogRecData rdata[2];
|
||||||
@ -325,7 +325,7 @@ ginbuild(PG_FUNCTION_ARGS)
|
|||||||
GinInitBuffer(RootBuffer, GIN_LEAF);
|
GinInitBuffer(RootBuffer, GIN_LEAF);
|
||||||
MarkBufferDirty(RootBuffer);
|
MarkBufferDirty(RootBuffer);
|
||||||
|
|
||||||
if (!index->rd_istemp)
|
if (RelationNeedsWAL(index))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
XLogRecData rdata;
|
XLogRecData rdata;
|
||||||
|
@ -410,7 +410,7 @@ ginUpdateStats(Relation index, const GinStatsData *stats)
|
|||||||
|
|
||||||
MarkBufferDirty(metabuffer);
|
MarkBufferDirty(metabuffer);
|
||||||
|
|
||||||
if (!index->rd_istemp)
|
if (RelationNeedsWAL(index))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
ginxlogUpdateMeta data;
|
ginxlogUpdateMeta data;
|
||||||
|
@ -93,7 +93,7 @@ xlogVacuumPage(Relation index, Buffer buffer)
|
|||||||
|
|
||||||
Assert(GinPageIsLeaf(page));
|
Assert(GinPageIsLeaf(page));
|
||||||
|
|
||||||
if (index->rd_istemp)
|
if (!RelationNeedsWAL(index))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
data.node = index->rd_node;
|
data.node = index->rd_node;
|
||||||
@ -308,7 +308,7 @@ ginDeletePage(GinVacuumState *gvs, BlockNumber deleteBlkno, BlockNumber leftBlkn
|
|||||||
MarkBufferDirty(lBuffer);
|
MarkBufferDirty(lBuffer);
|
||||||
MarkBufferDirty(dBuffer);
|
MarkBufferDirty(dBuffer);
|
||||||
|
|
||||||
if (!gvs->index->rd_istemp)
|
if (RelationNeedsWAL(gvs->index))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
XLogRecData rdata[4];
|
XLogRecData rdata[4];
|
||||||
|
@ -115,7 +115,7 @@ gistbuild(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
MarkBufferDirty(buffer);
|
MarkBufferDirty(buffer);
|
||||||
|
|
||||||
if (!index->rd_istemp)
|
if (RelationNeedsWAL(index))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
XLogRecData rdata;
|
XLogRecData rdata;
|
||||||
@ -401,7 +401,7 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate)
|
|||||||
dist->page = BufferGetPage(dist->buffer);
|
dist->page = BufferGetPage(dist->buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state->r->rd_istemp)
|
if (RelationNeedsWAL(state->r))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
XLogRecData *rdata;
|
XLogRecData *rdata;
|
||||||
@ -465,7 +465,7 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate)
|
|||||||
|
|
||||||
MarkBufferDirty(state->stack->buffer);
|
MarkBufferDirty(state->stack->buffer);
|
||||||
|
|
||||||
if (!state->r->rd_istemp)
|
if (RelationNeedsWAL(state->r))
|
||||||
{
|
{
|
||||||
OffsetNumber noffs = 0,
|
OffsetNumber noffs = 0,
|
||||||
offs[1];
|
offs[1];
|
||||||
@ -550,7 +550,7 @@ gistfindleaf(GISTInsertState *state, GISTSTATE *giststate)
|
|||||||
opaque = GistPageGetOpaque(state->stack->page);
|
opaque = GistPageGetOpaque(state->stack->page);
|
||||||
|
|
||||||
state->stack->lsn = PageGetLSN(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 &&
|
if (state->stack->blkno != GIST_ROOT_BLKNO &&
|
||||||
XLByteLT(state->stack->parent->lsn, opaque->nsn))
|
XLByteLT(state->stack->parent->lsn, opaque->nsn))
|
||||||
@ -911,7 +911,7 @@ gistmakedeal(GISTInsertState *state, GISTSTATE *giststate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* say to xlog that insert is completed */
|
/* 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);
|
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);
|
MarkBufferDirty(buffer);
|
||||||
|
|
||||||
if (!r->rd_istemp)
|
if (RelationNeedsWAL(r))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
XLogRecData *rdata;
|
XLogRecData *rdata;
|
||||||
|
@ -248,7 +248,7 @@ gistbulkdelete(PG_FUNCTION_ARGS)
|
|||||||
PageIndexTupleDelete(page, todelete[i]);
|
PageIndexTupleDelete(page, todelete[i]);
|
||||||
GistMarkTuplesDeleted(page);
|
GistMarkTuplesDeleted(page);
|
||||||
|
|
||||||
if (!rel->rd_istemp)
|
if (RelationNeedsWAL(rel))
|
||||||
{
|
{
|
||||||
XLogRecData *rdata;
|
XLogRecData *rdata;
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
|
@ -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.
|
* 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)
|
scan->rs_nblocks > NBuffers / 4)
|
||||||
{
|
{
|
||||||
allow_strat = scan->rs_allow_strat;
|
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);
|
elog(ERROR, "could not open relation with OID %u", relationId);
|
||||||
|
|
||||||
/* Make note that we've accessed a temporary relation */
|
/* Make note that we've accessed a temporary relation */
|
||||||
if (r->rd_istemp)
|
if (RelationUsesLocalBuffers(r))
|
||||||
MyXactAccessedTempRel = true;
|
MyXactAccessedTempRel = true;
|
||||||
|
|
||||||
pgstat_initstats(r);
|
pgstat_initstats(r);
|
||||||
@ -951,7 +951,7 @@ try_relation_open(Oid relationId, LOCKMODE lockmode)
|
|||||||
elog(ERROR, "could not open relation with OID %u", relationId);
|
elog(ERROR, "could not open relation with OID %u", relationId);
|
||||||
|
|
||||||
/* Make note that we've accessed a temporary relation */
|
/* Make note that we've accessed a temporary relation */
|
||||||
if (r->rd_istemp)
|
if (RelationUsesLocalBuffers(r))
|
||||||
MyXactAccessedTempRel = true;
|
MyXactAccessedTempRel = true;
|
||||||
|
|
||||||
pgstat_initstats(r);
|
pgstat_initstats(r);
|
||||||
@ -1917,7 +1917,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
|
|||||||
MarkBufferDirty(buffer);
|
MarkBufferDirty(buffer);
|
||||||
|
|
||||||
/* XLOG stuff */
|
/* 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_insert xlrec;
|
||||||
xl_heap_header xlhdr;
|
xl_heap_header xlhdr;
|
||||||
@ -2227,7 +2227,7 @@ l1:
|
|||||||
MarkBufferDirty(buffer);
|
MarkBufferDirty(buffer);
|
||||||
|
|
||||||
/* XLOG stuff */
|
/* XLOG stuff */
|
||||||
if (!relation->rd_istemp)
|
if (RelationNeedsWAL(relation))
|
||||||
{
|
{
|
||||||
xl_heap_delete xlrec;
|
xl_heap_delete xlrec;
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
@ -2780,7 +2780,7 @@ l2:
|
|||||||
MarkBufferDirty(buffer);
|
MarkBufferDirty(buffer);
|
||||||
|
|
||||||
/* XLOG stuff */
|
/* XLOG stuff */
|
||||||
if (!relation->rd_istemp)
|
if (RelationNeedsWAL(relation))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr = log_heap_update(relation, buffer, oldtup.t_self,
|
XLogRecPtr recptr = log_heap_update(relation, buffer, oldtup.t_self,
|
||||||
newbuf, heaptup,
|
newbuf, heaptup,
|
||||||
@ -3403,7 +3403,7 @@ l3:
|
|||||||
* (Also, in a PITR log-shipping or 2PC environment, we have to have XLOG
|
* (Also, in a PITR log-shipping or 2PC environment, we have to have XLOG
|
||||||
* entries for everything anyway.)
|
* entries for everything anyway.)
|
||||||
*/
|
*/
|
||||||
if (!relation->rd_istemp)
|
if (RelationNeedsWAL(relation))
|
||||||
{
|
{
|
||||||
xl_heap_lock xlrec;
|
xl_heap_lock xlrec;
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
@ -3505,7 +3505,7 @@ heap_inplace_update(Relation relation, HeapTuple tuple)
|
|||||||
MarkBufferDirty(buffer);
|
MarkBufferDirty(buffer);
|
||||||
|
|
||||||
/* XLOG stuff */
|
/* XLOG stuff */
|
||||||
if (!relation->rd_istemp)
|
if (RelationNeedsWAL(relation))
|
||||||
{
|
{
|
||||||
xl_heap_inplace xlrec;
|
xl_heap_inplace xlrec;
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
@ -3867,8 +3867,8 @@ log_heap_clean(Relation reln, Buffer buffer,
|
|||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
XLogRecData rdata[4];
|
XLogRecData rdata[4];
|
||||||
|
|
||||||
/* Caller should not call me on a temp relation */
|
/* Caller should not call me on a non-WAL-logged relation */
|
||||||
Assert(!reln->rd_istemp);
|
Assert(RelationNeedsWAL(reln));
|
||||||
|
|
||||||
xlrec.node = reln->rd_node;
|
xlrec.node = reln->rd_node;
|
||||||
xlrec.block = BufferGetBlockNumber(buffer);
|
xlrec.block = BufferGetBlockNumber(buffer);
|
||||||
@ -3950,8 +3950,8 @@ log_heap_freeze(Relation reln, Buffer buffer,
|
|||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
XLogRecData rdata[2];
|
XLogRecData rdata[2];
|
||||||
|
|
||||||
/* Caller should not call me on a temp relation */
|
/* Caller should not call me on a non-WAL-logged relation */
|
||||||
Assert(!reln->rd_istemp);
|
Assert(RelationNeedsWAL(reln));
|
||||||
/* nor when there are no tuples to freeze */
|
/* nor when there are no tuples to freeze */
|
||||||
Assert(offcnt > 0);
|
Assert(offcnt > 0);
|
||||||
|
|
||||||
@ -3996,8 +3996,8 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,
|
|||||||
XLogRecData rdata[4];
|
XLogRecData rdata[4];
|
||||||
Page page = BufferGetPage(newbuf);
|
Page page = BufferGetPage(newbuf);
|
||||||
|
|
||||||
/* Caller should not call me on a temp relation */
|
/* Caller should not call me on a non-WAL-logged relation */
|
||||||
Assert(!reln->rd_istemp);
|
Assert(RelationNeedsWAL(reln));
|
||||||
|
|
||||||
if (HeapTupleIsHeapOnly(newtup))
|
if (HeapTupleIsHeapOnly(newtup))
|
||||||
info = XLOG_HEAP_HOT_UPDATE;
|
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
|
* 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.
|
* 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
|
* 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.
|
* 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
|
void
|
||||||
heap_sync(Relation rel)
|
heap_sync(Relation rel)
|
||||||
{
|
{
|
||||||
/* temp tables never need fsync */
|
/* non-WAL-logged tables never need fsync */
|
||||||
if (rel->rd_istemp)
|
if (!RelationNeedsWAL(rel))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* main heap */
|
/* main heap */
|
||||||
|
@ -233,7 +233,7 @@ heap_page_prune(Relation relation, Buffer buffer, TransactionId OldestXmin,
|
|||||||
/*
|
/*
|
||||||
* Emit a WAL HEAP_CLEAN record showing what we did
|
* Emit a WAL HEAP_CLEAN record showing what we did
|
||||||
*/
|
*/
|
||||||
if (!relation->rd_istemp)
|
if (RelationNeedsWAL(relation))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
|
|
||||||
|
@ -277,8 +277,8 @@ end_heap_rewrite(RewriteState state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the rel isn't temp, must fsync before commit. We use heap_sync to
|
* If the rel is WAL-logged, must fsync before commit. We use heap_sync
|
||||||
* ensure that the toast table gets fsync'd too.
|
* 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
|
* 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
|
* 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
|
* occurring during the rewriteheap operation won't have fsync'd data we
|
||||||
* wrote before the checkpoint.
|
* wrote before the checkpoint.
|
||||||
*/
|
*/
|
||||||
if (!state->rs_new_rel->rd_istemp)
|
if (RelationNeedsWAL(state->rs_new_rel))
|
||||||
heap_sync(state->rs_new_rel);
|
heap_sync(state->rs_new_rel);
|
||||||
|
|
||||||
/* Deleting the context frees everything */
|
/* Deleting the context frees everything */
|
||||||
|
@ -766,7 +766,7 @@ _bt_insertonpg(Relation rel,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* XLOG stuff */
|
/* XLOG stuff */
|
||||||
if (!rel->rd_istemp)
|
if (RelationNeedsWAL(rel))
|
||||||
{
|
{
|
||||||
xl_btree_insert xlrec;
|
xl_btree_insert xlrec;
|
||||||
BlockNumber xldownlink;
|
BlockNumber xldownlink;
|
||||||
@ -1165,7 +1165,7 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* XLOG stuff */
|
/* XLOG stuff */
|
||||||
if (!rel->rd_istemp)
|
if (RelationNeedsWAL(rel))
|
||||||
{
|
{
|
||||||
xl_btree_split xlrec;
|
xl_btree_split xlrec;
|
||||||
uint8 xlinfo;
|
uint8 xlinfo;
|
||||||
@ -1914,7 +1914,7 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
|
|||||||
MarkBufferDirty(metabuf);
|
MarkBufferDirty(metabuf);
|
||||||
|
|
||||||
/* XLOG stuff */
|
/* XLOG stuff */
|
||||||
if (!rel->rd_istemp)
|
if (RelationNeedsWAL(rel))
|
||||||
{
|
{
|
||||||
xl_btree_newroot xlrec;
|
xl_btree_newroot xlrec;
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
|
@ -224,7 +224,7 @@ _bt_getroot(Relation rel, int access)
|
|||||||
MarkBufferDirty(metabuf);
|
MarkBufferDirty(metabuf);
|
||||||
|
|
||||||
/* XLOG stuff */
|
/* XLOG stuff */
|
||||||
if (!rel->rd_istemp)
|
if (RelationNeedsWAL(rel))
|
||||||
{
|
{
|
||||||
xl_btree_newroot xlrec;
|
xl_btree_newroot xlrec;
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
@ -452,7 +452,7 @@ _bt_checkpage(Relation rel, Buffer buf)
|
|||||||
static void
|
static void
|
||||||
_bt_log_reuse_page(Relation rel, BlockNumber blkno, TransactionId latestRemovedXid)
|
_bt_log_reuse_page(Relation rel, BlockNumber blkno, TransactionId latestRemovedXid)
|
||||||
{
|
{
|
||||||
if (rel->rd_istemp)
|
if (!RelationNeedsWAL(rel))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* No ereport(ERROR) until changes are logged */
|
/* No ereport(ERROR) until changes are logged */
|
||||||
@ -751,7 +751,7 @@ _bt_delitems_vacuum(Relation rel, Buffer buf,
|
|||||||
MarkBufferDirty(buf);
|
MarkBufferDirty(buf);
|
||||||
|
|
||||||
/* XLOG stuff */
|
/* XLOG stuff */
|
||||||
if (!rel->rd_istemp)
|
if (RelationNeedsWAL(rel))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
XLogRecData rdata[2];
|
XLogRecData rdata[2];
|
||||||
@ -829,7 +829,7 @@ _bt_delitems_delete(Relation rel, Buffer buf,
|
|||||||
MarkBufferDirty(buf);
|
MarkBufferDirty(buf);
|
||||||
|
|
||||||
/* XLOG stuff */
|
/* XLOG stuff */
|
||||||
if (!rel->rd_istemp)
|
if (RelationNeedsWAL(rel))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
XLogRecData rdata[3];
|
XLogRecData rdata[3];
|
||||||
@ -1365,7 +1365,7 @@ _bt_pagedel(Relation rel, Buffer buf, BTStack stack)
|
|||||||
MarkBufferDirty(lbuf);
|
MarkBufferDirty(lbuf);
|
||||||
|
|
||||||
/* XLOG stuff */
|
/* XLOG stuff */
|
||||||
if (!rel->rd_istemp)
|
if (RelationNeedsWAL(rel))
|
||||||
{
|
{
|
||||||
xl_btree_delete_page xlrec;
|
xl_btree_delete_page xlrec;
|
||||||
xl_btree_metadata xlmeta;
|
xl_btree_metadata xlmeta;
|
||||||
|
@ -211,9 +211,9 @@ _bt_leafbuild(BTSpool *btspool, BTSpool *btspool2)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to log index creation in WAL iff WAL archiving/streaming is
|
* 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 */
|
/* reserve the metapage */
|
||||||
wstate.btws_pages_alloced = BTREE_METAPAGE + 1;
|
wstate.btws_pages_alloced = BTREE_METAPAGE + 1;
|
||||||
@ -797,9 +797,9 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
|
|||||||
_bt_uppershutdown(wstate, state);
|
_bt_uppershutdown(wstate, state);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the index isn't temp, we must fsync it down to disk before it's safe
|
* If the index is WAL-logged, we must fsync it down to disk before it's
|
||||||
* to commit the transaction. (For a temp index we don't care since the
|
* safe to commit the transaction. (For a non-WAL-logged index we don't
|
||||||
* index will be uninteresting after a crash anyway.)
|
* 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
|
* 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
|
* 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
|
* fsync those pages here, they might still not be on disk when the crash
|
||||||
* occurs.
|
* occurs.
|
||||||
*/
|
*/
|
||||||
if (!wstate->index->rd_istemp)
|
if (RelationNeedsWAL(wstate->index))
|
||||||
{
|
{
|
||||||
RelationOpenSmgr(wstate->index);
|
RelationOpenSmgr(wstate->index);
|
||||||
smgrimmedsync(wstate->index->rd_smgr, MAIN_FORKNUM);
|
smgrimmedsync(wstate->index->rd_smgr, MAIN_FORKNUM);
|
||||||
|
@ -219,6 +219,7 @@ Boot_CreateStmt:
|
|||||||
$3,
|
$3,
|
||||||
tupdesc,
|
tupdesc,
|
||||||
RELKIND_RELATION,
|
RELKIND_RELATION,
|
||||||
|
RELPERSISTENCE_PERMANENT,
|
||||||
shared_relation,
|
shared_relation,
|
||||||
mapped_relation,
|
mapped_relation,
|
||||||
true);
|
true);
|
||||||
@ -238,6 +239,7 @@ Boot_CreateStmt:
|
|||||||
tupdesc,
|
tupdesc,
|
||||||
NIL,
|
NIL,
|
||||||
RELKIND_RELATION,
|
RELKIND_RELATION,
|
||||||
|
RELPERSISTENCE_PERMANENT,
|
||||||
shared_relation,
|
shared_relation,
|
||||||
mapped_relation,
|
mapped_relation,
|
||||||
true,
|
true,
|
||||||
|
@ -524,12 +524,26 @@ GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
|
|||||||
* created by bootstrap have preassigned OIDs, so there's no need.
|
* created by bootstrap have preassigned OIDs, so there's no need.
|
||||||
*/
|
*/
|
||||||
Oid
|
Oid
|
||||||
GetNewRelFileNode(Oid reltablespace, Relation pg_class, BackendId backend)
|
GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
|
||||||
{
|
{
|
||||||
RelFileNodeBackend rnode;
|
RelFileNodeBackend rnode;
|
||||||
char *rpath;
|
char *rpath;
|
||||||
int fd;
|
int fd;
|
||||||
bool collides;
|
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 */
|
/* This logic should match RelationInitPhysicalAddr */
|
||||||
rnode.node.spcNode = reltablespace ? reltablespace : MyDatabaseTableSpace;
|
rnode.node.spcNode = reltablespace ? reltablespace : MyDatabaseTableSpace;
|
||||||
|
@ -238,6 +238,7 @@ heap_create(const char *relname,
|
|||||||
Oid relid,
|
Oid relid,
|
||||||
TupleDesc tupDesc,
|
TupleDesc tupDesc,
|
||||||
char relkind,
|
char relkind,
|
||||||
|
char relpersistence,
|
||||||
bool shared_relation,
|
bool shared_relation,
|
||||||
bool mapped_relation,
|
bool mapped_relation,
|
||||||
bool allow_system_table_mods)
|
bool allow_system_table_mods)
|
||||||
@ -311,7 +312,8 @@ heap_create(const char *relname,
|
|||||||
relid,
|
relid,
|
||||||
reltablespace,
|
reltablespace,
|
||||||
shared_relation,
|
shared_relation,
|
||||||
mapped_relation);
|
mapped_relation,
|
||||||
|
relpersistence);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Have the storage manager create the relation's disk file, if needed.
|
* Have the storage manager create the relation's disk file, if needed.
|
||||||
@ -322,7 +324,7 @@ heap_create(const char *relname,
|
|||||||
if (create_storage)
|
if (create_storage)
|
||||||
{
|
{
|
||||||
RelationOpenSmgr(rel);
|
RelationOpenSmgr(rel);
|
||||||
RelationCreateStorage(rel->rd_node, rel->rd_istemp);
|
RelationCreateStorage(rel->rd_node, relpersistence);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rel;
|
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_reltoastidxid - 1] = ObjectIdGetDatum(rd_rel->reltoastidxid);
|
||||||
values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
|
values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
|
||||||
values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
|
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_relkind - 1] = CharGetDatum(rd_rel->relkind);
|
||||||
values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
|
values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
|
||||||
values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
|
values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
|
||||||
@ -898,6 +900,7 @@ heap_create_with_catalog(const char *relname,
|
|||||||
TupleDesc tupdesc,
|
TupleDesc tupdesc,
|
||||||
List *cooked_constraints,
|
List *cooked_constraints,
|
||||||
char relkind,
|
char relkind,
|
||||||
|
char relpersistence,
|
||||||
bool shared_relation,
|
bool shared_relation,
|
||||||
bool mapped_relation,
|
bool mapped_relation,
|
||||||
bool oidislocal,
|
bool oidislocal,
|
||||||
@ -997,8 +1000,7 @@ heap_create_with_catalog(const char *relname,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
relid = GetNewRelFileNode(reltablespace, pg_class_desc,
|
relid = GetNewRelFileNode(reltablespace, pg_class_desc,
|
||||||
isTempOrToastNamespace(relnamespace) ?
|
relpersistence);
|
||||||
MyBackendId : InvalidBackendId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1036,6 +1038,7 @@ heap_create_with_catalog(const char *relname,
|
|||||||
relid,
|
relid,
|
||||||
tupdesc,
|
tupdesc,
|
||||||
relkind,
|
relkind,
|
||||||
|
relpersistence,
|
||||||
shared_relation,
|
shared_relation,
|
||||||
mapped_relation,
|
mapped_relation,
|
||||||
allow_system_table_mods);
|
allow_system_table_mods);
|
||||||
|
@ -545,6 +545,7 @@ index_create(Oid heapRelationId,
|
|||||||
bool is_exclusion;
|
bool is_exclusion;
|
||||||
Oid namespaceId;
|
Oid namespaceId;
|
||||||
int i;
|
int i;
|
||||||
|
char relpersistence;
|
||||||
|
|
||||||
is_exclusion = (indexInfo->ii_ExclusionOps != NULL);
|
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
|
* 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
|
* 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);
|
namespaceId = RelationGetNamespace(heapRelation);
|
||||||
shared_relation = heapRelation->rd_rel->relisshared;
|
shared_relation = heapRelation->rd_rel->relisshared;
|
||||||
mapped_relation = RelationIsMapped(heapRelation);
|
mapped_relation = RelationIsMapped(heapRelation);
|
||||||
|
relpersistence = heapRelation->rd_rel->relpersistence;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* check parameters
|
* check parameters
|
||||||
@ -646,9 +649,7 @@ index_create(Oid heapRelationId,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
indexRelationId =
|
indexRelationId =
|
||||||
GetNewRelFileNode(tableSpaceId, pg_class,
|
GetNewRelFileNode(tableSpaceId, pg_class, relpersistence);
|
||||||
heapRelation->rd_istemp ?
|
|
||||||
MyBackendId : InvalidBackendId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -663,6 +664,7 @@ index_create(Oid heapRelationId,
|
|||||||
indexRelationId,
|
indexRelationId,
|
||||||
indexTupDesc,
|
indexTupDesc,
|
||||||
RELKIND_INDEX,
|
RELKIND_INDEX,
|
||||||
|
relpersistence,
|
||||||
shared_relation,
|
shared_relation,
|
||||||
mapped_relation,
|
mapped_relation,
|
||||||
allow_system_table_mods);
|
allow_system_table_mods);
|
||||||
|
@ -235,14 +235,14 @@ RangeVarGetRelid(const RangeVar *relation, bool failOK)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If istemp is set, this is a reference to a temp relation. The parser
|
* Some non-default relpersistence value may have been specified. The
|
||||||
* never generates such a RangeVar in simple DML, but it can happen in
|
* parser never generates such a RangeVar in simple DML, but it can happen
|
||||||
* contexts such as "CREATE TEMP TABLE foo (f1 int PRIMARY KEY)". Such a
|
* in contexts such as "CREATE TEMP TABLE foo (f1 int PRIMARY KEY)". Such
|
||||||
* command will generate an added CREATE INDEX operation, which must be
|
* 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
|
* careful to find the temp table, even when pg_temp is not first in the
|
||||||
* search path.
|
* search path.
|
||||||
*/
|
*/
|
||||||
if (relation->istemp)
|
if (relation->relpersistence == RELPERSISTENCE_TEMP)
|
||||||
{
|
{
|
||||||
if (relation->schemaname)
|
if (relation->schemaname)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -308,7 +308,7 @@ RangeVarGetCreationNamespace(const RangeVar *newRelation)
|
|||||||
newRelation->relname)));
|
newRelation->relname)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newRelation->istemp)
|
if (newRelation->relpersistence == RELPERSISTENCE_TEMP)
|
||||||
{
|
{
|
||||||
/* TEMP tables are created in our backend-local temp namespace */
|
/* TEMP tables are created in our backend-local temp namespace */
|
||||||
if (newRelation->schemaname)
|
if (newRelation->schemaname)
|
||||||
|
@ -95,19 +95,35 @@ typedef struct xl_smgr_truncate
|
|||||||
* transaction aborts later on, the storage will be destroyed.
|
* transaction aborts later on, the storage will be destroyed.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
RelationCreateStorage(RelFileNode rnode, bool istemp)
|
RelationCreateStorage(RelFileNode rnode, char relpersistence)
|
||||||
{
|
{
|
||||||
PendingRelDelete *pending;
|
PendingRelDelete *pending;
|
||||||
XLogRecPtr lsn;
|
XLogRecPtr lsn;
|
||||||
XLogRecData rdata;
|
XLogRecData rdata;
|
||||||
xl_smgr_create xlrec;
|
xl_smgr_create xlrec;
|
||||||
SMgrRelation srel;
|
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);
|
srel = smgropen(rnode, backend);
|
||||||
smgrcreate(srel, MAIN_FORKNUM, false);
|
smgrcreate(srel, MAIN_FORKNUM, false);
|
||||||
|
|
||||||
if (!istemp)
|
if (needs_wal)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Make an XLOG entry reporting the file creation.
|
* 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
|
* failure to truncate, that might spell trouble at WAL replay, into a
|
||||||
* certain PANIC.
|
* certain PANIC.
|
||||||
*/
|
*/
|
||||||
if (!rel->rd_istemp)
|
if (RelationNeedsWAL(rel))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Make an XLOG entry reporting the file truncation.
|
* Make an XLOG entry reporting the file truncation.
|
||||||
|
@ -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
|
* Toast tables for regular relations go in pg_toast; those for temp
|
||||||
* relations go into the per-backend temp-toast-table namespace.
|
* relations go into the per-backend temp-toast-table namespace.
|
||||||
*/
|
*/
|
||||||
if (rel->rd_backend == MyBackendId)
|
if (RelationUsesTempNamespace(rel))
|
||||||
namespaceid = GetTempToastNamespace();
|
namespaceid = GetTempToastNamespace();
|
||||||
else
|
else
|
||||||
namespaceid = PG_TOAST_NAMESPACE;
|
namespaceid = PG_TOAST_NAMESPACE;
|
||||||
@ -216,6 +216,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, Datum reloptio
|
|||||||
tupdesc,
|
tupdesc,
|
||||||
NIL,
|
NIL,
|
||||||
RELKIND_TOASTVALUE,
|
RELKIND_TOASTVALUE,
|
||||||
|
rel->rd_rel->relpersistence,
|
||||||
shared_relation,
|
shared_relation,
|
||||||
mapped_relation,
|
mapped_relation,
|
||||||
true,
|
true,
|
||||||
|
@ -675,6 +675,7 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace)
|
|||||||
tupdesc,
|
tupdesc,
|
||||||
NIL,
|
NIL,
|
||||||
OldHeap->rd_rel->relkind,
|
OldHeap->rd_rel->relkind,
|
||||||
|
OldHeap->rd_rel->relpersistence,
|
||||||
false,
|
false,
|
||||||
RelationIsMapped(OldHeap),
|
RelationIsMapped(OldHeap),
|
||||||
true,
|
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
|
* 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 */
|
/* use_wal off requires smgr_targblock be initially invalid */
|
||||||
Assert(RelationGetTargetBlock(NewHeap) == InvalidBlockNumber);
|
Assert(RelationGetTargetBlock(NewHeap) == InvalidBlockNumber);
|
||||||
|
@ -222,7 +222,7 @@ DefineIndex(RangeVar *heapRelation,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tablespaceId = GetDefaultTablespace(rel->rd_istemp);
|
tablespaceId = GetDefaultTablespace(rel->rd_rel->relpersistence);
|
||||||
/* note InvalidOid is OK in this case */
|
/* note InvalidOid is OK in this case */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1706,7 +1706,7 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Skip temp tables of other backends; we can't reindex them at all */
|
/* Skip temp tables of other backends; we can't reindex them at all */
|
||||||
if (classtuple->relistemp &&
|
if (classtuple->relpersistence == RELPERSISTENCE_TEMP &&
|
||||||
!isTempNamespace(classtuple->relnamespace))
|
!isTempNamespace(classtuple->relnamespace))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -366,7 +366,7 @@ fill_seq_with_data(Relation rel, HeapTuple tuple)
|
|||||||
MarkBufferDirty(buf);
|
MarkBufferDirty(buf);
|
||||||
|
|
||||||
/* XLOG stuff */
|
/* XLOG stuff */
|
||||||
if (!rel->rd_istemp)
|
if (RelationNeedsWAL(rel))
|
||||||
{
|
{
|
||||||
xl_seq_rec xlrec;
|
xl_seq_rec xlrec;
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
@ -448,7 +448,7 @@ AlterSequence(AlterSeqStmt *stmt)
|
|||||||
MarkBufferDirty(buf);
|
MarkBufferDirty(buf);
|
||||||
|
|
||||||
/* XLOG stuff */
|
/* XLOG stuff */
|
||||||
if (!seqrel->rd_istemp)
|
if (RelationNeedsWAL(seqrel))
|
||||||
{
|
{
|
||||||
xl_seq_rec xlrec;
|
xl_seq_rec xlrec;
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
@ -678,7 +678,7 @@ nextval_internal(Oid relid)
|
|||||||
MarkBufferDirty(buf);
|
MarkBufferDirty(buf);
|
||||||
|
|
||||||
/* XLOG stuff */
|
/* XLOG stuff */
|
||||||
if (logit && !seqrel->rd_istemp)
|
if (logit && RelationNeedsWAL(seqrel))
|
||||||
{
|
{
|
||||||
xl_seq_rec xlrec;
|
xl_seq_rec xlrec;
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
@ -855,7 +855,7 @@ do_setval(Oid relid, int64 next, bool iscalled)
|
|||||||
MarkBufferDirty(buf);
|
MarkBufferDirty(buf);
|
||||||
|
|
||||||
/* XLOG stuff */
|
/* XLOG stuff */
|
||||||
if (!seqrel->rd_istemp)
|
if (RelationNeedsWAL(seqrel))
|
||||||
{
|
{
|
||||||
xl_seq_rec xlrec;
|
xl_seq_rec xlrec;
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
|
@ -224,7 +224,7 @@ static const struct dropmsgstrings dropmsgstringarray[] = {
|
|||||||
|
|
||||||
|
|
||||||
static void truncate_check_rel(Relation rel);
|
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);
|
List **supOids, List **supconstr, int *supOidCount);
|
||||||
static bool MergeCheckConstraint(List *constraints, char *name, Node *expr);
|
static bool MergeCheckConstraint(List *constraints, char *name, Node *expr);
|
||||||
static bool change_varattnos_walker(Node *node, const AttrNumber *newattno);
|
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 ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode);
|
||||||
static void ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode);
|
static void ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode);
|
||||||
static void copy_relation_data(SMgrRelation rel, SMgrRelation dst,
|
static void copy_relation_data(SMgrRelation rel, SMgrRelation dst,
|
||||||
ForkNumber forkNum, bool istemp);
|
ForkNumber forkNum, char relpersistence);
|
||||||
static const char *storage_name(char c);
|
static const char *storage_name(char c);
|
||||||
|
|
||||||
|
|
||||||
@ -391,7 +391,8 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
|
|||||||
/*
|
/*
|
||||||
* Check consistency of arguments
|
* Check consistency of arguments
|
||||||
*/
|
*/
|
||||||
if (stmt->oncommit != ONCOMMIT_NOOP && !stmt->relation->istemp)
|
if (stmt->oncommit != ONCOMMIT_NOOP
|
||||||
|
&& stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
||||||
errmsg("ON COMMIT can only be used on temporary tables")));
|
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
|
* code. This is needed because calling code might not expect untrusted
|
||||||
* tables to appear in pg_temp at the front of its search path.
|
* 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,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||||
errmsg("cannot create temporary table within security-restricted operation")));
|
errmsg("cannot create temporary table within security-restricted operation")));
|
||||||
@ -434,7 +436,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tablespaceId = GetDefaultTablespace(stmt->relation->istemp);
|
tablespaceId = GetDefaultTablespace(stmt->relation->relpersistence);
|
||||||
/* note InvalidOid is OK in this case */
|
/* note InvalidOid is OK in this case */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,7 +480,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
|
|||||||
* inherited attributes.
|
* inherited attributes.
|
||||||
*/
|
*/
|
||||||
schema = MergeAttributes(schema, stmt->inhRelations,
|
schema = MergeAttributes(schema, stmt->inhRelations,
|
||||||
stmt->relation->istemp,
|
stmt->relation->relpersistence,
|
||||||
&inheritOids, &old_constraints, &parentOidCount);
|
&inheritOids, &old_constraints, &parentOidCount);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -557,6 +559,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
|
|||||||
list_concat(cookedDefaults,
|
list_concat(cookedDefaults,
|
||||||
old_constraints),
|
old_constraints),
|
||||||
relkind,
|
relkind,
|
||||||
|
stmt->relation->relpersistence,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
localHasOids,
|
localHasOids,
|
||||||
@ -1208,7 +1211,7 @@ storage_name(char c)
|
|||||||
*----------
|
*----------
|
||||||
*/
|
*/
|
||||||
static List *
|
static List *
|
||||||
MergeAttributes(List *schema, List *supers, bool istemp,
|
MergeAttributes(List *schema, List *supers, char relpersistence,
|
||||||
List **supOids, List **supconstr, int *supOidCount)
|
List **supOids, List **supconstr, int *supOidCount)
|
||||||
{
|
{
|
||||||
ListCell *entry;
|
ListCell *entry;
|
||||||
@ -1316,7 +1319,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
|||||||
errmsg("inherited relation \"%s\" is not a table",
|
errmsg("inherited relation \"%s\" is not a table",
|
||||||
parent->relname)));
|
parent->relname)));
|
||||||
/* Permanent rels cannot inherit from temporary ones */
|
/* Permanent rels cannot inherit from temporary ones */
|
||||||
if (!istemp && relation->rd_istemp)
|
if (relpersistence != RELPERSISTENCE_TEMP
|
||||||
|
&& RelationUsesTempNamespace(relation))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||||
errmsg("cannot inherit from temporary relation \"%s\"",
|
errmsg("cannot inherit from temporary relation \"%s\"",
|
||||||
@ -5124,26 +5128,27 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
|
|||||||
RelationGetRelationName(pkrel))));
|
RelationGetRelationName(pkrel))));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disallow reference from permanent table to temp table or vice versa.
|
* References from permanent tables to temp tables are disallowed because
|
||||||
* (The ban on perm->temp is for fairly obvious reasons. The ban on
|
* the contents of the temp table disappear at the end of each session.
|
||||||
* temp->perm is because other backends might need to run the RI triggers
|
* References from temp tables to permanent tables are also disallowed,
|
||||||
* on the perm table, but they can't reliably see tuples the owning
|
* because other backends might need to run the RI triggers on the perm
|
||||||
* backend has created in the temp table, because non-shared buffers are
|
* table, but they can't reliably see tuples in the local buffers of other
|
||||||
* used for temp tables.)
|
* backends.
|
||||||
*/
|
*/
|
||||||
if (pkrel->rd_istemp)
|
switch (rel->rd_rel->relpersistence)
|
||||||
{
|
{
|
||||||
if (!rel->rd_istemp)
|
case RELPERSISTENCE_PERMANENT:
|
||||||
ereport(ERROR,
|
if (pkrel->rd_rel->relpersistence != RELPERSISTENCE_PERMANENT)
|
||||||
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
ereport(ERROR,
|
||||||
errmsg("cannot reference temporary table from permanent table constraint")));
|
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
||||||
}
|
errmsg("constraints on permanent tables may reference only permanent tables")));
|
||||||
else
|
break;
|
||||||
{
|
case RELPERSISTENCE_TEMP:
|
||||||
if (rel->rd_istemp)
|
if (pkrel->rd_rel->relpersistence != RELPERSISTENCE_TEMP)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
||||||
errmsg("cannot reference permanent table from temporary table constraint")));
|
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
|
* Relfilenodes are not unique across tablespaces, so we need to allocate
|
||||||
* a new one in the new tablespace.
|
* 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 */
|
/* Open old and new relation */
|
||||||
newrnode = rel->rd_node;
|
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
|
* NOTE: any conflict in relfilenode value will be caught in
|
||||||
* RelationCreateStorage().
|
* RelationCreateStorage().
|
||||||
*/
|
*/
|
||||||
RelationCreateStorage(newrnode, rel->rd_istemp);
|
RelationCreateStorage(newrnode, rel->rd_rel->relpersistence);
|
||||||
|
|
||||||
/* copy main fork */
|
/* 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 */
|
/* copy those extra forks that exist */
|
||||||
for (forkNum = MAIN_FORKNUM + 1; forkNum <= MAX_FORKNUM; forkNum++)
|
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))
|
if (smgrexists(rel->rd_smgr, forkNum))
|
||||||
{
|
{
|
||||||
smgrcreate(dstrel, forkNum, false);
|
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
|
static void
|
||||||
copy_relation_data(SMgrRelation src, SMgrRelation dst,
|
copy_relation_data(SMgrRelation src, SMgrRelation dst,
|
||||||
ForkNumber forkNum, bool istemp)
|
ForkNumber forkNum, char relpersistence)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
Page page;
|
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
|
* 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);
|
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
|
* 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.
|
* here, they might still not be on disk when the crash occurs.
|
||||||
*/
|
*/
|
||||||
if (!istemp)
|
if (relpersistence == RELPERSISTENCE_PERMANENT)
|
||||||
smgrimmedsync(dst, forkNum);
|
smgrimmedsync(dst, forkNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7538,7 +7546,8 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
|
|||||||
ATSimplePermissions(parent_rel, false, false);
|
ATSimplePermissions(parent_rel, false, false);
|
||||||
|
|
||||||
/* Permanent rels cannot inherit from temporary ones */
|
/* 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,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||||
errmsg("cannot inherit from temporary relation \"%s\"",
|
errmsg("cannot inherit from temporary relation \"%s\"",
|
||||||
|
@ -1050,8 +1050,8 @@ assign_default_tablespace(const char *newval, bool doit, GucSource source)
|
|||||||
/*
|
/*
|
||||||
* GetDefaultTablespace -- get the OID of the current default tablespace
|
* GetDefaultTablespace -- get the OID of the current default tablespace
|
||||||
*
|
*
|
||||||
* Regular objects and temporary objects have different default tablespaces,
|
* Temporary objects have different default tablespaces, hence the
|
||||||
* hence the forTemp parameter must be specified.
|
* relpersistence parameter must be specified.
|
||||||
*
|
*
|
||||||
* May return InvalidOid to indicate "use the database's default tablespace".
|
* 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.
|
* default_tablespace GUC variable.
|
||||||
*/
|
*/
|
||||||
Oid
|
Oid
|
||||||
GetDefaultTablespace(bool forTemp)
|
GetDefaultTablespace(char relpersistence)
|
||||||
{
|
{
|
||||||
Oid result;
|
Oid result;
|
||||||
|
|
||||||
/* The temp-table case is handled elsewhere */
|
/* The temp-table case is handled elsewhere */
|
||||||
if (forTemp)
|
if (relpersistence == RELPERSISTENCE_TEMP)
|
||||||
{
|
{
|
||||||
PrepareTempTablespaces();
|
PrepareTempTablespaces();
|
||||||
return GetNextTempTableSpace();
|
return GetNextTempTableSpace();
|
||||||
|
@ -268,10 +268,10 @@ static void
|
|||||||
vacuum_log_cleanup_info(Relation rel, LVRelStats *vacrelstats)
|
vacuum_log_cleanup_info(Relation rel, LVRelStats *vacrelstats)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* No need to log changes for temp tables, they do not contain data
|
* Skip this for relations for which no WAL is to be written, or if we're
|
||||||
* visible on the standby server.
|
* not trying to support archive recovery.
|
||||||
*/
|
*/
|
||||||
if (rel->rd_istemp || !XLogIsNeeded())
|
if (!RelationNeedsWAL(rel) || !XLogIsNeeded())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -664,8 +664,7 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
|||||||
if (nfrozen > 0)
|
if (nfrozen > 0)
|
||||||
{
|
{
|
||||||
MarkBufferDirty(buf);
|
MarkBufferDirty(buf);
|
||||||
/* no XLOG for temp tables, though */
|
if (RelationNeedsWAL(onerel))
|
||||||
if (!onerel->rd_istemp)
|
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
|
|
||||||
@ -895,7 +894,7 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
|
|||||||
MarkBufferDirty(buffer);
|
MarkBufferDirty(buffer);
|
||||||
|
|
||||||
/* XLOG stuff */
|
/* XLOG stuff */
|
||||||
if (!onerel->rd_istemp)
|
if (RelationNeedsWAL(onerel))
|
||||||
{
|
{
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
|
|
||||||
|
@ -68,10 +68,10 @@ isViewOnTempTable_walker(Node *node, void *context)
|
|||||||
if (rte->rtekind == RTE_RELATION)
|
if (rte->rtekind == RTE_RELATION)
|
||||||
{
|
{
|
||||||
Relation rel = heap_open(rte->relid, AccessShareLock);
|
Relation rel = heap_open(rte->relid, AccessShareLock);
|
||||||
bool istemp = rel->rd_istemp;
|
char relpersistence = rel->rd_rel->relpersistence;
|
||||||
|
|
||||||
heap_close(rel, AccessShareLock);
|
heap_close(rel, AccessShareLock);
|
||||||
if (istemp)
|
if (relpersistence == RELPERSISTENCE_TEMP)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,9 +173,9 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace)
|
|||||||
/*
|
/*
|
||||||
* Due to the namespace visibility rules for temporary objects, we
|
* Due to the namespace visibility rules for temporary objects, we
|
||||||
* should only end up replacing a temporary view with another
|
* 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
|
* Create a tuple descriptor to compare against the existing view, and
|
||||||
@ -454,10 +454,11 @@ DefineView(ViewStmt *stmt, const char *queryString)
|
|||||||
* schema name.
|
* schema name.
|
||||||
*/
|
*/
|
||||||
view = stmt->view;
|
view = stmt->view;
|
||||||
if (!view->istemp && isViewOnTempTable(viewParse))
|
if (view->relpersistence == RELPERSISTENCE_PERMANENT
|
||||||
|
&& isViewOnTempTable(viewParse))
|
||||||
{
|
{
|
||||||
view = copyObject(view); /* don't corrupt original command */
|
view = copyObject(view); /* don't corrupt original command */
|
||||||
view->istemp = true;
|
view->relpersistence = RELPERSISTENCE_TEMP;
|
||||||
ereport(NOTICE,
|
ereport(NOTICE,
|
||||||
(errmsg("view \"%s\" will be a temporary view",
|
(errmsg("view \"%s\" will be a temporary view",
|
||||||
view->relname)));
|
view->relname)));
|
||||||
|
@ -2131,7 +2131,8 @@ OpenIntoRel(QueryDesc *queryDesc)
|
|||||||
/*
|
/*
|
||||||
* Check consistency of arguments
|
* Check consistency of arguments
|
||||||
*/
|
*/
|
||||||
if (into->onCommit != ONCOMMIT_NOOP && !into->rel->istemp)
|
if (into->onCommit != ONCOMMIT_NOOP
|
||||||
|
&& into->rel->relpersistence != RELPERSISTENCE_TEMP)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
||||||
errmsg("ON COMMIT can only be used on temporary tables")));
|
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
|
* code. This is needed because calling code might not expect untrusted
|
||||||
* tables to appear in pg_temp at the front of its search path.
|
* 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,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||||
errmsg("cannot create temporary table within security-restricted operation")));
|
errmsg("cannot create temporary table within security-restricted operation")));
|
||||||
@ -2168,7 +2170,7 @@ OpenIntoRel(QueryDesc *queryDesc)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tablespaceId = GetDefaultTablespace(into->rel->istemp);
|
tablespaceId = GetDefaultTablespace(into->rel->relpersistence);
|
||||||
/* note InvalidOid is OK in this case */
|
/* note InvalidOid is OK in this case */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2208,6 +2210,7 @@ OpenIntoRel(QueryDesc *queryDesc)
|
|||||||
tupdesc,
|
tupdesc,
|
||||||
NIL,
|
NIL,
|
||||||
RELKIND_RELATION,
|
RELKIND_RELATION,
|
||||||
|
into->rel->relpersistence,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
|
@ -958,7 +958,7 @@ _copyRangeVar(RangeVar *from)
|
|||||||
COPY_STRING_FIELD(schemaname);
|
COPY_STRING_FIELD(schemaname);
|
||||||
COPY_STRING_FIELD(relname);
|
COPY_STRING_FIELD(relname);
|
||||||
COPY_SCALAR_FIELD(inhOpt);
|
COPY_SCALAR_FIELD(inhOpt);
|
||||||
COPY_SCALAR_FIELD(istemp);
|
COPY_SCALAR_FIELD(relpersistence);
|
||||||
COPY_NODE_FIELD(alias);
|
COPY_NODE_FIELD(alias);
|
||||||
COPY_LOCATION_FIELD(location);
|
COPY_LOCATION_FIELD(location);
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ _equalRangeVar(RangeVar *a, RangeVar *b)
|
|||||||
COMPARE_STRING_FIELD(schemaname);
|
COMPARE_STRING_FIELD(schemaname);
|
||||||
COMPARE_STRING_FIELD(relname);
|
COMPARE_STRING_FIELD(relname);
|
||||||
COMPARE_SCALAR_FIELD(inhOpt);
|
COMPARE_SCALAR_FIELD(inhOpt);
|
||||||
COMPARE_SCALAR_FIELD(istemp);
|
COMPARE_SCALAR_FIELD(relpersistence);
|
||||||
COMPARE_NODE_FIELD(alias);
|
COMPARE_NODE_FIELD(alias);
|
||||||
COMPARE_LOCATION_FIELD(location);
|
COMPARE_LOCATION_FIELD(location);
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
|
#include "catalog/pg_class.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
#include "nodes/makefuncs.h"
|
#include "nodes/makefuncs.h"
|
||||||
#include "nodes/nodeFuncs.h"
|
#include "nodes/nodeFuncs.h"
|
||||||
@ -378,7 +379,7 @@ makeRangeVar(char *schemaname, char *relname, int location)
|
|||||||
r->schemaname = schemaname;
|
r->schemaname = schemaname;
|
||||||
r->relname = relname;
|
r->relname = relname;
|
||||||
r->inhOpt = INH_DEFAULT;
|
r->inhOpt = INH_DEFAULT;
|
||||||
r->istemp = false;
|
r->relpersistence = RELPERSISTENCE_PERMANENT;
|
||||||
r->alias = NULL;
|
r->alias = NULL;
|
||||||
r->location = location;
|
r->location = location;
|
||||||
|
|
||||||
|
@ -841,7 +841,7 @@ _outRangeVar(StringInfo str, RangeVar *node)
|
|||||||
WRITE_STRING_FIELD(schemaname);
|
WRITE_STRING_FIELD(schemaname);
|
||||||
WRITE_STRING_FIELD(relname);
|
WRITE_STRING_FIELD(relname);
|
||||||
WRITE_ENUM_FIELD(inhOpt, InhOption);
|
WRITE_ENUM_FIELD(inhOpt, InhOption);
|
||||||
WRITE_BOOL_FIELD(istemp);
|
WRITE_CHAR_FIELD(relpersistence);
|
||||||
WRITE_NODE_FIELD(alias);
|
WRITE_NODE_FIELD(alias);
|
||||||
WRITE_LOCATION_FIELD(location);
|
WRITE_LOCATION_FIELD(location);
|
||||||
}
|
}
|
||||||
|
@ -373,7 +373,7 @@ _readRangeVar(void)
|
|||||||
READ_STRING_FIELD(schemaname);
|
READ_STRING_FIELD(schemaname);
|
||||||
READ_STRING_FIELD(relname);
|
READ_STRING_FIELD(relname);
|
||||||
READ_ENUM_FIELD(inhOpt, InhOption);
|
READ_ENUM_FIELD(inhOpt, InhOption);
|
||||||
READ_BOOL_FIELD(istemp);
|
READ_CHAR_FIELD(relpersistence);
|
||||||
READ_NODE_FIELD(alias);
|
READ_NODE_FIELD(alias);
|
||||||
READ_LOCATION_FIELD(location);
|
READ_LOCATION_FIELD(location);
|
||||||
|
|
||||||
|
@ -311,7 +311,8 @@ static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_
|
|||||||
%type <fun_param_mode> arg_class
|
%type <fun_param_mode> arg_class
|
||||||
%type <typnam> func_return func_type
|
%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 <oncommit> OnCommitOption
|
||||||
|
|
||||||
%type <node> for_locking_item
|
%type <node> for_locking_item
|
||||||
@ -2280,7 +2281,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
|
|||||||
OptInherit OptWith OnCommitOption OptTableSpace
|
OptInherit OptWith OnCommitOption OptTableSpace
|
||||||
{
|
{
|
||||||
CreateStmt *n = makeNode(CreateStmt);
|
CreateStmt *n = makeNode(CreateStmt);
|
||||||
$4->istemp = $2;
|
$4->relpersistence = $2;
|
||||||
n->relation = $4;
|
n->relation = $4;
|
||||||
n->tableElts = $6;
|
n->tableElts = $6;
|
||||||
n->inhRelations = $8;
|
n->inhRelations = $8;
|
||||||
@ -2296,7 +2297,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
|
|||||||
OptTableSpace
|
OptTableSpace
|
||||||
{
|
{
|
||||||
CreateStmt *n = makeNode(CreateStmt);
|
CreateStmt *n = makeNode(CreateStmt);
|
||||||
$7->istemp = $2;
|
$7->relpersistence = $2;
|
||||||
n->relation = $7;
|
n->relation = $7;
|
||||||
n->tableElts = $9;
|
n->tableElts = $9;
|
||||||
n->inhRelations = $11;
|
n->inhRelations = $11;
|
||||||
@ -2311,7 +2312,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
|
|||||||
OptTypedTableElementList OptWith OnCommitOption OptTableSpace
|
OptTypedTableElementList OptWith OnCommitOption OptTableSpace
|
||||||
{
|
{
|
||||||
CreateStmt *n = makeNode(CreateStmt);
|
CreateStmt *n = makeNode(CreateStmt);
|
||||||
$4->istemp = $2;
|
$4->relpersistence = $2;
|
||||||
n->relation = $4;
|
n->relation = $4;
|
||||||
n->tableElts = $7;
|
n->tableElts = $7;
|
||||||
n->ofTypename = makeTypeNameFromNameList($6);
|
n->ofTypename = makeTypeNameFromNameList($6);
|
||||||
@ -2327,7 +2328,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
|
|||||||
OptTypedTableElementList OptWith OnCommitOption OptTableSpace
|
OptTypedTableElementList OptWith OnCommitOption OptTableSpace
|
||||||
{
|
{
|
||||||
CreateStmt *n = makeNode(CreateStmt);
|
CreateStmt *n = makeNode(CreateStmt);
|
||||||
$7->istemp = $2;
|
$7->relpersistence = $2;
|
||||||
n->relation = $7;
|
n->relation = $7;
|
||||||
n->tableElts = $10;
|
n->tableElts = $10;
|
||||||
n->ofTypename = makeTypeNameFromNameList($9);
|
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
|
* NOTE: we accept both GLOBAL and LOCAL options; since we have no modules
|
||||||
* the LOCAL keyword is really meaningless.
|
* the LOCAL keyword is really meaningless.
|
||||||
*/
|
*/
|
||||||
OptTemp: TEMPORARY { $$ = TRUE; }
|
OptTemp: TEMPORARY { $$ = RELPERSISTENCE_TEMP; }
|
||||||
| TEMP { $$ = TRUE; }
|
| TEMP { $$ = RELPERSISTENCE_TEMP; }
|
||||||
| LOCAL TEMPORARY { $$ = TRUE; }
|
| LOCAL TEMPORARY { $$ = RELPERSISTENCE_TEMP; }
|
||||||
| LOCAL TEMP { $$ = TRUE; }
|
| LOCAL TEMP { $$ = RELPERSISTENCE_TEMP; }
|
||||||
| GLOBAL TEMPORARY { $$ = TRUE; }
|
| GLOBAL TEMPORARY { $$ = RELPERSISTENCE_TEMP; }
|
||||||
| GLOBAL TEMP { $$ = TRUE; }
|
| GLOBAL TEMP { $$ = RELPERSISTENCE_TEMP; }
|
||||||
| /*EMPTY*/ { $$ = FALSE; }
|
| /*EMPTY*/ { $$ = RELPERSISTENCE_PERMANENT; }
|
||||||
;
|
;
|
||||||
|
|
||||||
OptTableElementList:
|
OptTableElementList:
|
||||||
@ -2834,7 +2835,7 @@ CreateAsStmt:
|
|||||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
errmsg("CREATE TABLE AS cannot specify INTO"),
|
errmsg("CREATE TABLE AS cannot specify INTO"),
|
||||||
parser_errposition(exprLocation((Node *) n->intoClause))));
|
parser_errposition(exprLocation((Node *) n->intoClause))));
|
||||||
$4->rel->istemp = $2;
|
$4->rel->relpersistence = $2;
|
||||||
n->intoClause = $4;
|
n->intoClause = $4;
|
||||||
/* Implement WITH NO DATA by forcing top-level LIMIT 0 */
|
/* Implement WITH NO DATA by forcing top-level LIMIT 0 */
|
||||||
if (!$7)
|
if (!$7)
|
||||||
@ -2900,7 +2901,7 @@ CreateSeqStmt:
|
|||||||
CREATE OptTemp SEQUENCE qualified_name OptSeqOptList
|
CREATE OptTemp SEQUENCE qualified_name OptSeqOptList
|
||||||
{
|
{
|
||||||
CreateSeqStmt *n = makeNode(CreateSeqStmt);
|
CreateSeqStmt *n = makeNode(CreateSeqStmt);
|
||||||
$4->istemp = $2;
|
$4->relpersistence = $2;
|
||||||
n->sequence = $4;
|
n->sequence = $4;
|
||||||
n->options = $5;
|
n->options = $5;
|
||||||
n->ownerId = InvalidOid;
|
n->ownerId = InvalidOid;
|
||||||
@ -6621,7 +6622,7 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list
|
|||||||
{
|
{
|
||||||
ViewStmt *n = makeNode(ViewStmt);
|
ViewStmt *n = makeNode(ViewStmt);
|
||||||
n->view = $4;
|
n->view = $4;
|
||||||
n->view->istemp = $2;
|
n->view->relpersistence = $2;
|
||||||
n->aliases = $5;
|
n->aliases = $5;
|
||||||
n->query = $7;
|
n->query = $7;
|
||||||
n->replace = false;
|
n->replace = false;
|
||||||
@ -6632,7 +6633,7 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list
|
|||||||
{
|
{
|
||||||
ViewStmt *n = makeNode(ViewStmt);
|
ViewStmt *n = makeNode(ViewStmt);
|
||||||
n->view = $6;
|
n->view = $6;
|
||||||
n->view->istemp = $4;
|
n->view->relpersistence = $4;
|
||||||
n->aliases = $7;
|
n->aliases = $7;
|
||||||
n->query = $9;
|
n->query = $9;
|
||||||
n->replace = true;
|
n->replace = true;
|
||||||
@ -7328,7 +7329,7 @@ ExecuteStmt: EXECUTE name execute_param_clause
|
|||||||
ExecuteStmt *n = makeNode(ExecuteStmt);
|
ExecuteStmt *n = makeNode(ExecuteStmt);
|
||||||
n->name = $7;
|
n->name = $7;
|
||||||
n->params = $8;
|
n->params = $8;
|
||||||
$4->rel->istemp = $2;
|
$4->rel->relpersistence = $2;
|
||||||
n->into = $4;
|
n->into = $4;
|
||||||
if ($4->colNames)
|
if ($4->colNames)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -7889,42 +7890,42 @@ OptTempTableName:
|
|||||||
TEMPORARY opt_table qualified_name
|
TEMPORARY opt_table qualified_name
|
||||||
{
|
{
|
||||||
$$ = $3;
|
$$ = $3;
|
||||||
$$->istemp = true;
|
$$->relpersistence = RELPERSISTENCE_TEMP;
|
||||||
}
|
}
|
||||||
| TEMP opt_table qualified_name
|
| TEMP opt_table qualified_name
|
||||||
{
|
{
|
||||||
$$ = $3;
|
$$ = $3;
|
||||||
$$->istemp = true;
|
$$->relpersistence = RELPERSISTENCE_TEMP;
|
||||||
}
|
}
|
||||||
| LOCAL TEMPORARY opt_table qualified_name
|
| LOCAL TEMPORARY opt_table qualified_name
|
||||||
{
|
{
|
||||||
$$ = $4;
|
$$ = $4;
|
||||||
$$->istemp = true;
|
$$->relpersistence = RELPERSISTENCE_TEMP;
|
||||||
}
|
}
|
||||||
| LOCAL TEMP opt_table qualified_name
|
| LOCAL TEMP opt_table qualified_name
|
||||||
{
|
{
|
||||||
$$ = $4;
|
$$ = $4;
|
||||||
$$->istemp = true;
|
$$->relpersistence = RELPERSISTENCE_TEMP;
|
||||||
}
|
}
|
||||||
| GLOBAL TEMPORARY opt_table qualified_name
|
| GLOBAL TEMPORARY opt_table qualified_name
|
||||||
{
|
{
|
||||||
$$ = $4;
|
$$ = $4;
|
||||||
$$->istemp = true;
|
$$->relpersistence = RELPERSISTENCE_TEMP;
|
||||||
}
|
}
|
||||||
| GLOBAL TEMP opt_table qualified_name
|
| GLOBAL TEMP opt_table qualified_name
|
||||||
{
|
{
|
||||||
$$ = $4;
|
$$ = $4;
|
||||||
$$->istemp = true;
|
$$->relpersistence = RELPERSISTENCE_TEMP;
|
||||||
}
|
}
|
||||||
| TABLE qualified_name
|
| TABLE qualified_name
|
||||||
{
|
{
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
$$->istemp = false;
|
$$->relpersistence = RELPERSISTENCE_PERMANENT;
|
||||||
}
|
}
|
||||||
| qualified_name
|
| qualified_name
|
||||||
{
|
{
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
$$->istemp = false;
|
$$->relpersistence = RELPERSISTENCE_PERMANENT;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -10916,16 +10917,12 @@ qualified_name_list:
|
|||||||
qualified_name:
|
qualified_name:
|
||||||
ColId
|
ColId
|
||||||
{
|
{
|
||||||
$$ = makeNode(RangeVar);
|
$$ = makeRangeVar(NULL, $1, @1);
|
||||||
$$->catalogname = NULL;
|
|
||||||
$$->schemaname = NULL;
|
|
||||||
$$->relname = $1;
|
|
||||||
$$->location = @1;
|
|
||||||
}
|
}
|
||||||
| ColId indirection
|
| ColId indirection
|
||||||
{
|
{
|
||||||
check_qualified_name($2, yyscanner);
|
check_qualified_name($2, yyscanner);
|
||||||
$$ = makeNode(RangeVar);
|
$$ = makeRangeVar(NULL, NULL, @1);
|
||||||
switch (list_length($2))
|
switch (list_length($2))
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
@ -10946,7 +10943,6 @@ qualified_name:
|
|||||||
parser_errposition(@1)));
|
parser_errposition(@1)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$$->location = @1;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -12163,6 +12159,7 @@ makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r->relpersistence = RELPERSISTENCE_PERMANENT;
|
||||||
r->location = position;
|
r->location = position;
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
@ -158,10 +158,11 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
|
|||||||
* If the target relation name isn't schema-qualified, make it so. This
|
* If the target relation name isn't schema-qualified, make it so. This
|
||||||
* prevents some corner cases in which added-on rewritten commands might
|
* prevents some corner cases in which added-on rewritten commands might
|
||||||
* think they should apply to other relations that have the same name and
|
* think they should apply to other relations that have the same name and
|
||||||
* are earlier in the search path. "istemp" is equivalent to a
|
* are earlier in the search path. But a local temp table is effectively
|
||||||
* specification of pg_temp, so no need for anything extra in that case.
|
* 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);
|
Oid namespaceid = RangeVarGetCreationNamespace(stmt->relation);
|
||||||
|
|
||||||
|
@ -1975,7 +1975,7 @@ do_autovacuum(void)
|
|||||||
* Check if it is a temp table (presumably, of some other backend's).
|
* Check if it is a temp table (presumably, of some other backend's).
|
||||||
* We cannot safely process other backends' temp tables.
|
* We cannot safely process other backends' temp tables.
|
||||||
*/
|
*/
|
||||||
if (classForm->relistemp)
|
if (classForm->relpersistence == RELPERSISTENCE_TEMP)
|
||||||
{
|
{
|
||||||
int backendID;
|
int backendID;
|
||||||
|
|
||||||
@ -2072,7 +2072,7 @@ do_autovacuum(void)
|
|||||||
/*
|
/*
|
||||||
* We cannot safely process other backends' temp tables, so skip 'em.
|
* We cannot safely process other backends' temp tables, so skip 'em.
|
||||||
*/
|
*/
|
||||||
if (classForm->relistemp)
|
if (classForm->relpersistence == RELPERSISTENCE_TEMP)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
relid = HeapTupleGetOid(tuple);
|
relid = HeapTupleGetOid(tuple);
|
||||||
|
@ -123,7 +123,7 @@ PrefetchBuffer(Relation reln, ForkNumber forkNum, BlockNumber blockNum)
|
|||||||
/* Open it at the smgr level if not already done */
|
/* Open it at the smgr level if not already done */
|
||||||
RelationOpenSmgr(reln);
|
RelationOpenSmgr(reln);
|
||||||
|
|
||||||
if (reln->rd_istemp)
|
if (RelationUsesLocalBuffers(reln))
|
||||||
{
|
{
|
||||||
/* see comments in ReadBufferExtended */
|
/* see comments in ReadBufferExtended */
|
||||||
if (RELATION_IS_OTHER_TEMP(reln))
|
if (RELATION_IS_OTHER_TEMP(reln))
|
||||||
@ -2071,7 +2071,7 @@ FlushRelationBuffers(Relation rel)
|
|||||||
/* Open rel at the smgr level if not already done */
|
/* Open rel at the smgr level if not already done */
|
||||||
RelationOpenSmgr(rel);
|
RelationOpenSmgr(rel);
|
||||||
|
|
||||||
if (rel->rd_istemp)
|
if (RelationUsesLocalBuffers(rel))
|
||||||
{
|
{
|
||||||
for (i = 0; i < NLocBuffer; i++)
|
for (i = 0; i < NLocBuffer; i++)
|
||||||
{
|
{
|
||||||
|
@ -612,16 +612,26 @@ pg_relation_filepath(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If temporary, determine owning backend. */
|
/* Determine owning backend. */
|
||||||
if (!relform->relistemp)
|
switch (relform->relpersistence)
|
||||||
backend = InvalidBackendId;
|
|
||||||
else if (isTempOrToastNamespace(relform->relnamespace))
|
|
||||||
backend = MyBackendId;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* Do it the hard way. */
|
case RELPERSISTENCE_PERMANENT:
|
||||||
backend = GetTempNamespaceBackendId(relform->relnamespace);
|
backend = InvalidBackendId;
|
||||||
Assert(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);
|
ReleaseSysCache(tuple);
|
||||||
|
71
src/backend/utils/cache/relcache.c
vendored
71
src/backend/utils/cache/relcache.c
vendored
@ -849,20 +849,30 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
|
|||||||
relation->rd_isnailed = false;
|
relation->rd_isnailed = false;
|
||||||
relation->rd_createSubid = InvalidSubTransactionId;
|
relation->rd_createSubid = InvalidSubTransactionId;
|
||||||
relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
|
relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
|
||||||
relation->rd_istemp = relation->rd_rel->relistemp;
|
switch (relation->rd_rel->relpersistence)
|
||||||
if (!relation->rd_istemp)
|
|
||||||
relation->rd_backend = InvalidBackendId;
|
|
||||||
else if (isTempOrToastNamespace(relation->rd_rel->relnamespace))
|
|
||||||
relation->rd_backend = MyBackendId;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/*
|
case RELPERSISTENCE_PERMANENT:
|
||||||
* If it's a temporary table, but not one of ours, we have to use
|
relation->rd_backend = InvalidBackendId;
|
||||||
* the slow, grotty method to figure out the owning backend.
|
break;
|
||||||
*/
|
case RELPERSISTENCE_TEMP:
|
||||||
relation->rd_backend =
|
if (isTempOrToastNamespace(relation->rd_rel->relnamespace))
|
||||||
GetTempNamespaceBackendId(relation->rd_rel->relnamespace);
|
relation->rd_backend = MyBackendId;
|
||||||
Assert(relation->rd_backend != InvalidBackendId);
|
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_isnailed = true;
|
||||||
relation->rd_createSubid = InvalidSubTransactionId;
|
relation->rd_createSubid = InvalidSubTransactionId;
|
||||||
relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
|
relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
|
||||||
relation->rd_istemp = false;
|
|
||||||
relation->rd_backend = InvalidBackendId;
|
relation->rd_backend = InvalidBackendId;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1384,11 +1393,8 @@ formrdesc(const char *relationName, Oid relationReltype,
|
|||||||
if (isshared)
|
if (isshared)
|
||||||
relation->rd_rel->reltablespace = GLOBALTABLESPACE_OID;
|
relation->rd_rel->reltablespace = GLOBALTABLESPACE_OID;
|
||||||
|
|
||||||
/*
|
/* formrdesc is used only for permanent relations */
|
||||||
* Likewise, we must know if a relation is temp ... but formrdesc is not
|
relation->rd_rel->relpersistence = RELPERSISTENCE_PERMANENT;
|
||||||
* used for any temp relations.
|
|
||||||
*/
|
|
||||||
relation->rd_rel->relistemp = false;
|
|
||||||
|
|
||||||
relation->rd_rel->relpages = 1;
|
relation->rd_rel->relpages = 1;
|
||||||
relation->rd_rel->reltuples = 1;
|
relation->rd_rel->reltuples = 1;
|
||||||
@ -2366,7 +2372,8 @@ RelationBuildLocalRelation(const char *relname,
|
|||||||
Oid relid,
|
Oid relid,
|
||||||
Oid reltablespace,
|
Oid reltablespace,
|
||||||
bool shared_relation,
|
bool shared_relation,
|
||||||
bool mapped_relation)
|
bool mapped_relation,
|
||||||
|
char relpersistence)
|
||||||
{
|
{
|
||||||
Relation rel;
|
Relation rel;
|
||||||
MemoryContext oldcxt;
|
MemoryContext oldcxt;
|
||||||
@ -2440,10 +2447,6 @@ RelationBuildLocalRelation(const char *relname,
|
|||||||
/* must flag that we have rels created in this transaction */
|
/* must flag that we have rels created in this transaction */
|
||||||
need_eoxact_work = true;
|
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
|
* 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
|
* partly to copy it into the cache context, and partly because the new
|
||||||
@ -2483,6 +2486,21 @@ RelationBuildLocalRelation(const char *relname,
|
|||||||
/* needed when bootstrapping: */
|
/* needed when bootstrapping: */
|
||||||
rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
|
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
|
* Insert relation physical and logical identifiers (OIDs) into the right
|
||||||
* places. Note that the physical ID (relfilenode) is initially the same
|
* places. Note that the physical ID (relfilenode) is initially the same
|
||||||
@ -2491,7 +2509,6 @@ RelationBuildLocalRelation(const char *relname,
|
|||||||
* map.
|
* map.
|
||||||
*/
|
*/
|
||||||
rel->rd_rel->relisshared = shared_relation;
|
rel->rd_rel->relisshared = shared_relation;
|
||||||
rel->rd_rel->relistemp = rel->rd_istemp;
|
|
||||||
|
|
||||||
RelationGetRelid(rel) = relid;
|
RelationGetRelid(rel) = relid;
|
||||||
|
|
||||||
@ -2569,7 +2586,7 @@ RelationSetNewRelfilenode(Relation relation, TransactionId freezeXid)
|
|||||||
|
|
||||||
/* Allocate a new relfilenode */
|
/* Allocate a new relfilenode */
|
||||||
newrelfilenode = GetNewRelFileNode(relation->rd_rel->reltablespace, NULL,
|
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.
|
* 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 = relation->rd_node;
|
||||||
newrnode.node.relNode = newrelfilenode;
|
newrnode.node.relNode = newrelfilenode;
|
||||||
newrnode.backend = relation->rd_backend;
|
newrnode.backend = relation->rd_backend;
|
||||||
RelationCreateStorage(newrnode.node, relation->rd_istemp);
|
RelationCreateStorage(newrnode.node, relation->rd_rel->relpersistence);
|
||||||
smgrclosenode(newrnode);
|
smgrclosenode(newrnode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -56,6 +56,6 @@ extern Oid GetNewOid(Relation relation);
|
|||||||
extern Oid GetNewOidWithIndex(Relation relation, Oid indexId,
|
extern Oid GetNewOidWithIndex(Relation relation, Oid indexId,
|
||||||
AttrNumber oidcolumn);
|
AttrNumber oidcolumn);
|
||||||
extern Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class,
|
extern Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class,
|
||||||
BackendId backend);
|
char relpersistence);
|
||||||
|
|
||||||
#endif /* CATALOG_H */
|
#endif /* CATALOG_H */
|
||||||
|
@ -53,6 +53,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 201012031
|
#define CATALOG_VERSION_NO 201012131
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -40,6 +40,7 @@ extern Relation heap_create(const char *relname,
|
|||||||
Oid relid,
|
Oid relid,
|
||||||
TupleDesc tupDesc,
|
TupleDesc tupDesc,
|
||||||
char relkind,
|
char relkind,
|
||||||
|
char relpersistence,
|
||||||
bool shared_relation,
|
bool shared_relation,
|
||||||
bool mapped_relation,
|
bool mapped_relation,
|
||||||
bool allow_system_table_mods);
|
bool allow_system_table_mods);
|
||||||
@ -54,6 +55,7 @@ extern Oid heap_create_with_catalog(const char *relname,
|
|||||||
TupleDesc tupdesc,
|
TupleDesc tupdesc,
|
||||||
List *cooked_constraints,
|
List *cooked_constraints,
|
||||||
char relkind,
|
char relkind,
|
||||||
|
char relpersistence,
|
||||||
bool shared_relation,
|
bool shared_relation,
|
||||||
bool mapped_relation,
|
bool mapped_relation,
|
||||||
bool oidislocal,
|
bool oidislocal,
|
||||||
|
@ -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 */
|
Oid reltoastidxid; /* if toast table, OID of chunk_id index */
|
||||||
bool relhasindex; /* T if has (or has had) any indexes */
|
bool relhasindex; /* T if has (or has had) any indexes */
|
||||||
bool relisshared; /* T if shared across databases */
|
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 */
|
char relkind; /* see RELKIND_xxx constants below */
|
||||||
int2 relnatts; /* number of user attributes */
|
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_reltoastidxid 12
|
||||||
#define Anum_pg_class_relhasindex 13
|
#define Anum_pg_class_relhasindex 13
|
||||||
#define Anum_pg_class_relisshared 14
|
#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_relkind 16
|
||||||
#define Anum_pg_class_relnatts 17
|
#define Anum_pg_class_relnatts 17
|
||||||
#define Anum_pg_class_relchecks 18
|
#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 */
|
/* 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("");
|
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("");
|
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("");
|
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("");
|
DESCR("");
|
||||||
|
|
||||||
#define RELKIND_INDEX 'i' /* secondary index */
|
#define RELKIND_INDEX 'i' /* secondary index */
|
||||||
@ -149,4 +149,7 @@ DESCR("");
|
|||||||
#define RELKIND_VIEW 'v' /* view */
|
#define RELKIND_VIEW 'v' /* view */
|
||||||
#define RELKIND_COMPOSITE_TYPE 'c' /* composite type */
|
#define RELKIND_COMPOSITE_TYPE 'c' /* composite type */
|
||||||
|
|
||||||
|
#define RELPERSISTENCE_PERMANENT 'p'
|
||||||
|
#define RELPERSISTENCE_TEMP 't'
|
||||||
|
|
||||||
#endif /* PG_CLASS_H */
|
#endif /* PG_CLASS_H */
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include "storage/relfilenode.h"
|
#include "storage/relfilenode.h"
|
||||||
#include "utils/relcache.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 RelationDropStorage(Relation rel);
|
||||||
extern void RelationPreserveStorage(RelFileNode rnode);
|
extern void RelationPreserveStorage(RelFileNode rnode);
|
||||||
extern void RelationTruncate(Relation rel, BlockNumber nblocks);
|
extern void RelationTruncate(Relation rel, BlockNumber nblocks);
|
||||||
|
@ -47,7 +47,7 @@ extern void AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt);
|
|||||||
|
|
||||||
extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo);
|
extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo);
|
||||||
|
|
||||||
extern Oid GetDefaultTablespace(bool forTemp);
|
extern Oid GetDefaultTablespace(char relpersistence);
|
||||||
|
|
||||||
extern void PrepareTempTablespaces(void);
|
extern void PrepareTempTablespaces(void);
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ typedef struct RangeVar
|
|||||||
char *relname; /* the relation/sequence name */
|
char *relname; /* the relation/sequence name */
|
||||||
InhOption inhOpt; /* expand rel by inheritance? recursively act
|
InhOption inhOpt; /* expand rel by inheritance? recursively act
|
||||||
* on children? */
|
* 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 */
|
Alias *alias; /* table alias & optional column aliases */
|
||||||
int location; /* token location, or -1 if unknown */
|
int location; /* token location, or -1 if unknown */
|
||||||
} RangeVar;
|
} RangeVar;
|
||||||
|
@ -132,7 +132,6 @@ typedef struct RelationData
|
|||||||
struct SMgrRelationData *rd_smgr; /* cached file handle, or NULL */
|
struct SMgrRelationData *rd_smgr; /* cached file handle, or NULL */
|
||||||
int rd_refcnt; /* reference count */
|
int rd_refcnt; /* reference count */
|
||||||
BackendId rd_backend; /* owning backend id, if temporary relation */
|
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_isnailed; /* rel is nailed in cache */
|
||||||
bool rd_isvalid; /* relcache entry is valid */
|
bool rd_isvalid; /* relcache entry is valid */
|
||||||
char rd_indexvalid; /* state of rd_indexlist: 0 = not valid, 1 =
|
char rd_indexvalid; /* state of rd_indexlist: 0 = not valid, 1 =
|
||||||
@ -389,6 +388,27 @@ typedef struct StdRdOptions
|
|||||||
(relation)->rd_smgr->smgr_targblock = (targblock); \
|
(relation)->rd_smgr->smgr_targblock = (targblock); \
|
||||||
} while (0)
|
} 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
|
* RELATION_IS_LOCAL
|
||||||
* If a rel is either temp or newly created in the current transaction,
|
* If a rel is either temp or newly created in the current transaction,
|
||||||
@ -407,7 +427,8 @@ typedef struct StdRdOptions
|
|||||||
* Beware of multiple eval of argument
|
* Beware of multiple eval of argument
|
||||||
*/
|
*/
|
||||||
#define RELATION_IS_OTHER_TEMP(relation) \
|
#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 */
|
/* routines in utils/cache/relcache.c */
|
||||||
extern void RelationIncrementReferenceCount(Relation rel);
|
extern void RelationIncrementReferenceCount(Relation rel);
|
||||||
|
@ -69,7 +69,8 @@ extern Relation RelationBuildLocalRelation(const char *relname,
|
|||||||
Oid relid,
|
Oid relid,
|
||||||
Oid reltablespace,
|
Oid reltablespace,
|
||||||
bool shared_relation,
|
bool shared_relation,
|
||||||
bool mapped_relation);
|
bool mapped_relation,
|
||||||
|
char relpersistence);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Routine to manage assignment of new relfilenode to a relation
|
* Routine to manage assignment of new relfilenode to a relation
|
||||||
|
Loading…
x
Reference in New Issue
Block a user