meta = (RelationMetapage) MemoryContextAllocZero(CacheMemoryContext,
sizeof(RelationMetapageData));
- /* Read and metapage. */
- buffer = ReadBuffer(relation, METAPAGE_BLKNO);
- page = BufferGetPage(buffer);
- LockBuffer(buffer, BUFFER_LOCK_SHARE);
-
- /* Copy real metapage, or for backward compatibility, create a fake one. */
- if (PageIsRelationMetapage(page))
- {
- memcpy(meta, BlindGetRelationMeta(page), sizeof(RelationMetapageData));
- UnlockReleaseBuffer(buffer);
- }
+ /*
+ * If the relation has a metapage, read it.
+ *
+ * XXX: It's pretty annoying to have to call RelationGetNumberOfBlocks.
+ * Can't we have an RBM_ERROR option for ReadBufferExtended?
+ */
+ if (RelationGetNumberOfBlocks(relation) > METAPAGE_BLKNO)
{
+ buffer = ReadBuffer(relation, METAPAGE_BLKNO);
+ page = BufferGetPage(buffer);
+ LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
+ /* If it's a metapage, copy it, cache it, and return it. */
+ if (PageIsRelationMetapage(page))
+ {
+ memcpy(meta, BlindGetRelationMeta(page),
+ sizeof(RelationMetapageData));
+ UnlockReleaseBuffer(buffer);
+ relation->rd_metapage = meta;
+ return meta;
+ }
+
+ /* It wasn't actually a metapage, so let it go. */
UnlockReleaseBuffer(buffer);
- meta->rmp_magic = METAPAGE_MAGIC;
- meta->rmp_version = 0; /* fake metapage */
- meta->rmp_dboid = relation->rd_node.dbNode;
- meta->rmp_tsoid = relation->rd_node.spcNode;
- meta->rmp_reloid = RelationGetRelid(relation);
- meta->rmp_relfilenode = relation->rd_node.relNode;
- meta->rmp_flags = 0;
- meta->rmp_minlayout = PG_PAGE_LAYOUT_VERSION;
- meta->rmp_maxlayout = PG_PAGE_LAYOUT_VERSION;
- meta->rmp_relfilenode_time = (pg_time_t) time(NULL);
}
+ /* There's no real metapage, so create a fake one. */
+ meta->rmp_magic = METAPAGE_MAGIC;
+ meta->rmp_version = 0; /* fake metapage */
+ meta->rmp_dboid = relation->rd_node.dbNode;
+ meta->rmp_tsoid = relation->rd_node.spcNode;
+ meta->rmp_reloid = RelationGetRelid(relation);
+ meta->rmp_relfilenode = relation->rd_node.relNode;
+ meta->rmp_flags = 0;
+ meta->rmp_minlayout = PG_PAGE_LAYOUT_VERSION;
+ meta->rmp_maxlayout = PG_PAGE_LAYOUT_VERSION;
+ meta->rmp_relfilenode_time = 0; /* unknown creation time */
+
/* Cache result for next time, and return it. */
relation->rd_metapage = meta;
return meta;
#include "access/heapam.h"
#include "access/hio.h"
+#include "access/metapage.h"
#include "access/multixact.h"
#include "access/relscan.h"
#include "access/sysattr.h"
{
scan->rs_syncscan = true;
scan->rs_startblock = ss_get_location(scan->rs_rd, scan->rs_nblocks);
+ if (scan->rs_startblock < scan->rs_lowpage)
+ scan->rs_startblock = scan->rs_lowpage;
}
else
{
scan->rs_syncscan = false;
- scan->rs_startblock = 0;
+ scan->rs_startblock = scan->rs_lowpage;
}
scan->rs_inited = false;
/*
* return null immediately if relation is empty
*/
- if (scan->rs_nblocks == 0)
+ if (scan->rs_nblocks == scan->rs_lowpage)
{
Assert(!BufferIsValid(scan->rs_cbuf));
tuple->t_data = NULL;
/*
* return null immediately if relation is empty
*/
- if (scan->rs_nblocks == 0)
+ if (scan->rs_nblocks == scan->rs_lowpage)
{
Assert(!BufferIsValid(scan->rs_cbuf));
tuple->t_data = NULL;
*/
scan->rs_syncscan = false;
/* start from last page of the scan */
- if (scan->rs_startblock > 0)
+ if (scan->rs_startblock > scan->rs_lowpage)
page = scan->rs_startblock - 1;
else
page = scan->rs_nblocks - 1;
if (backward)
{
finished = (page == scan->rs_startblock);
- if (page == 0)
+ if (page == scan->rs_lowpage)
page = scan->rs_nblocks;
page--;
}
{
page++;
if (page >= scan->rs_nblocks)
- page = 0;
+ page = scan->rs_lowpage;
finished = (page == scan->rs_startblock);
/*
scan->rs_strategy = NULL; /* set in initscan */
scan->rs_allow_strat = allow_strat;
scan->rs_allow_sync = allow_sync;
+ scan->rs_lowpage = RelationHasMetapage(relation) ? METAPAGE_BLKNO + 1 : 0;
/*
* we can use page-at-a-time mode if it's an MVCC-safe snapshot