blob: ecb8700d02688e5368b3969b8811af9ff7194fd4 [file] [log] [blame]
/*-------------------------------------------------------------------------
*
* nodeBitmapTableScan.c
* Routines to support bitmapped scans of relations
*
* NOTE: it is critical that this plan type only be used with MVCC-compliant
* snapshots (ie, regular snapshots, not SnapshotNow or one of the other
* special snapshots). The reason is that since index and heap scans are
* decoupled, there can be no assurance that the index tuple prompting a
* visit to a particular heap TID still exists when the visit is made.
* Therefore the tuple might not exist anymore either (which is OK because
* heap_fetch will cope) --- but worse, the tuple slot could have been
* re-used for a newer tuple. With an MVCC snapshot the newer tuple is
* certain to fail the time qual and so it will not be mistakenly returned.
* With SnapshotNow we might return a tuple that doesn't meet the required
* index qual conditions.
*
*
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*-------------------------------------------------------------------------
*/
/*
* INTERFACE ROUTINES
* ExecInitBitmapTableScan creates and initializes state info.
* ExecBitmapTableScan scans a relation using bitmap info
* ExecBitmapTableReScan prepares to rescan the plan.
* ExecEndBitmapTableScan releases all storage.
*/
#include "postgres.h"
#include "access/heapam.h"
#include "access/relscan.h"
#include "access/transam.h"
#include "executor/execdebug.h"
#include "executor/nodeBitmapTableScan.h"
#include "pgstat.h"
#include "storage/bufmgr.h"
#include "utils/memutils.h"
#include "miscadmin.h"
#include "parser/parsetree.h"
#include "cdb/cdbvars.h" /* gp_select_invisible */
#include "nodes/tidbitmap.h"
#include "cdb/cdbpartition.h"
#define BITMAPTABLESCAN_NSLOTS 2
/*
* Initializes the BitmapTableScanState, including creation of the
* scan description and the bitmapqualorig.
*/
BitmapTableScanState *
ExecInitBitmapTableScan(BitmapTableScan *node, EState *estate, int eflags)
{
/* check for unsupported flags */
Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
/*
* Assert caller didn't ask for an unsafe snapshot --- see comments at
* head of file.
*
* MPP-4703: the MVCC-snapshot restriction is required for correct results.
* our test-mode may deliberately return incorrect results, but that's OK.
*/
Assert(IsMVCCSnapshot(estate->es_snapshot) || gp_select_invisible);
BitmapTableScanState *state = makeNode(BitmapTableScanState);
BitmapTableScanBegin(state, (Plan *) node, estate, eflags);
/*
* initialize child nodes
*
* We do this last because the child nodes will open indexscans on our
* relation's indexes, and we want to be sure we have acquired a lock on
* the relation first.
*/
outerPlanState(state) = ExecInitNode(outerPlan(node), estate, eflags);
initGpmonPktForBitmapTableScan((Plan *)node, &state->ss.ps.gpmon_pkt, estate);
return state;
}
/*
* Retrieves the next tuple from the BitmapTableScan's underlying relation.
*/
TupleTableSlot *
ExecBitmapTableScan(BitmapTableScanState *node)
{
ScanState *scanState = (ScanState *)node;
TupleTableSlot *slot = DynamicScan_GetNextTuple(scanState, BitmapTableScanEndPartition,
BitmapTableScanBeginPartition, BitmapTableScanFetchNext);
if (!TupIsNull(slot))
{
Gpmon_M_Incr_Rows_Out(GpmonPktFromBitmapTableScanState(node));
CheckSendPlanStateGpmonPkt(&scanState->ps);
}
else if (!scanState->ps.delayEagerFree)
{
ExecEagerFreeBitmapTableScan(node);
}
return slot;
}
/*
* Prepares the BitmapTableScanState for a re-scan.
*/
void
ExecBitmapTableReScan(BitmapTableScanState *node, ExprContext *exprCtxt)
{
BitmapTableScanReScan(node, exprCtxt);
/*
* Always rescan the input immediately, to ensure we can pass down any
* outer tuple that might be used in index quals.
*/
Gpmon_M_Incr(GpmonPktFromBitmapTableScanState(node), GPMON_BITMAPTABLESCAN_RESCAN);
CheckSendPlanStateGpmonPkt(&node->ss.ps);
ExecReScan(outerPlanState(node), exprCtxt);
}
/* Cleans up once scanning is finished */
void
ExecEndBitmapTableScan(BitmapTableScanState *node)
{
BitmapTableScanEnd(node);
/*
* close down subplans
*/
ExecEndNode(outerPlanState(node));
EndPlanStateGpmonPkt(&node->ss.ps);
}
/* Returns the number of slots needed for this operator */
int
ExecCountSlotsBitmapTableScan(BitmapTableScan *node)
{
return ExecCountSlotsNode(outerPlan((Plan *) node)) +
ExecCountSlotsNode(innerPlan((Plan *) node)) + BITMAPTABLESCAN_NSLOTS;
}
/* Eagerly free memory held for scanning */
void
ExecEagerFreeBitmapTableScan(BitmapTableScanState *node)
{
DynamicScan_End((ScanState *)node, BitmapTableScanEndPartition);
}