mirror of
https://github.com/postgres/postgres.git
synced 2025-06-30 21:42:05 +03:00
Postgres95 1.01 Distribution - Virgin Sources
This commit is contained in:
449
src/backend/executor/nodeSeqscan.c
Normal file
449
src/backend/executor/nodeSeqscan.c
Normal file
@ -0,0 +1,449 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* nodeSeqscan.c--
|
||||
* Support routines for sequential scans of relations.
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.1.1.1 1996/07/09 06:21:27 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
/*
|
||||
* INTERFACE ROUTINES
|
||||
* ExecSeqScan sequentially scans a relation.
|
||||
* ExecSeqNext retrieve next tuple in sequential order.
|
||||
* ExecInitSeqScan creates and initializes a seqscan node.
|
||||
* ExecEndSeqScan releases any storage allocated.
|
||||
* ExecSeqReScan rescans the relation
|
||||
* ExecMarkPos marks scan position
|
||||
* ExecRestrPos restores scan position
|
||||
*
|
||||
*/
|
||||
#include "executor/executor.h"
|
||||
#include "executor/nodeSeqscan.h"
|
||||
#include "parser/parsetree.h"
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* Scan Support
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
/* ----------------------------------------------------------------
|
||||
* SeqNext
|
||||
*
|
||||
* This is a workhorse for ExecSeqScan
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
TupleTableSlot *
|
||||
SeqNext(SeqScan *node)
|
||||
{
|
||||
HeapTuple tuple;
|
||||
HeapScanDesc scandesc;
|
||||
CommonScanState *scanstate;
|
||||
EState *estate;
|
||||
ScanDirection direction;
|
||||
TupleTableSlot *slot;
|
||||
Buffer buffer;
|
||||
|
||||
/* ----------------
|
||||
* get information from the estate and scan state
|
||||
* ----------------
|
||||
*/
|
||||
estate = node->plan.state;
|
||||
scanstate = node->scanstate;
|
||||
scandesc = scanstate->css_currentScanDesc;
|
||||
direction = estate->es_direction;
|
||||
|
||||
/* ----------------
|
||||
* get the next tuple from the access methods
|
||||
* ----------------
|
||||
*/
|
||||
tuple = heap_getnext(scandesc, /* scan desc */
|
||||
ScanDirectionIsBackward(direction), /*backward flag*/
|
||||
&buffer); /* return: buffer */
|
||||
|
||||
/* ----------------
|
||||
* save the tuple and the buffer returned to us by the access methods
|
||||
* in our scan tuple slot and return the slot. Note: we pass 'false'
|
||||
* because tuples returned by heap_getnext() are pointers onto
|
||||
* disk pages and were not created with palloc() and so should not
|
||||
* be pfree()'d.
|
||||
* ----------------
|
||||
*/
|
||||
slot = scanstate->css_ScanTupleSlot;
|
||||
|
||||
slot = ExecStoreTuple(tuple, /* tuple to store */
|
||||
slot, /* slot to store in */
|
||||
buffer, /* buffer associated with this tuple */
|
||||
false); /* don't pfree this pointer */
|
||||
|
||||
/* ----------------
|
||||
* XXX -- mao says: The sequential scan for heap relations will
|
||||
* automatically unpin the buffer this tuple is on when we cross
|
||||
* a page boundary. The clearslot code also does this. We bump
|
||||
* the pin count on the page here, since we actually have two
|
||||
* pointers to it -- one in the scan desc and one in the tuple
|
||||
* table slot. --mar 20 91
|
||||
* ----------------
|
||||
*/
|
||||
ExecIncrSlotBufferRefcnt(slot);
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecSeqScan(node)
|
||||
*
|
||||
* Scans the relation sequentially and returns the next qualifying
|
||||
* tuple.
|
||||
* It calls the ExecScan() routine and passes it the access method
|
||||
* which retrieve tuples sequentially.
|
||||
*
|
||||
*/
|
||||
|
||||
TupleTableSlot *
|
||||
ExecSeqScan(SeqScan *node)
|
||||
{
|
||||
TupleTableSlot *slot;
|
||||
Plan *outerPlan;
|
||||
|
||||
S_printf("ExecSeqScan: scanning node: "); S_nodeDisplay(node);
|
||||
|
||||
/* ----------------
|
||||
* if there is an outer subplan, get a tuple from it
|
||||
* else, scan the relation
|
||||
* ----------------
|
||||
*/
|
||||
outerPlan = outerPlan((Plan *) node);
|
||||
if (outerPlan) {
|
||||
slot = ExecProcNode(outerPlan, (Plan*) node);
|
||||
} else {
|
||||
slot = ExecScan(node, SeqNext);
|
||||
}
|
||||
|
||||
S1_printf("ExecSeqScan: returned tuple slot: %d\n", slot);
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* InitScanRelation
|
||||
*
|
||||
* This does the initialization for scan relations and
|
||||
* subplans of scans.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
Oid
|
||||
InitScanRelation(SeqScan *node, EState *estate,
|
||||
CommonScanState *scanstate, Plan *outerPlan)
|
||||
{
|
||||
Index relid;
|
||||
List *rangeTable;
|
||||
RangeTblEntry *rtentry;
|
||||
Oid reloid;
|
||||
TimeQual timeQual;
|
||||
ScanDirection direction;
|
||||
Relation currentRelation;
|
||||
HeapScanDesc currentScanDesc;
|
||||
RelationInfo *resultRelationInfo;
|
||||
|
||||
if (outerPlan == NULL) {
|
||||
/* ----------------
|
||||
* if the outer node is nil then we are doing a simple
|
||||
* sequential scan of a relation...
|
||||
*
|
||||
* get the relation object id from the relid'th entry
|
||||
* in the range table, open that relation and initialize
|
||||
* the scan state...
|
||||
* ----------------
|
||||
*/
|
||||
relid = node->scanrelid;
|
||||
rangeTable = estate->es_range_table;
|
||||
rtentry = rt_fetch(relid, rangeTable);
|
||||
reloid = rtentry->relid;
|
||||
timeQual = rtentry->timeQual;
|
||||
direction = estate->es_direction;
|
||||
resultRelationInfo = estate->es_result_relation_info;
|
||||
|
||||
ExecOpenScanR(reloid, /* relation */
|
||||
0, /* nkeys */
|
||||
NULL, /* scan key */
|
||||
0, /* is index */
|
||||
direction, /* scan direction */
|
||||
timeQual, /* time qual */
|
||||
¤tRelation, /* return: rel desc */
|
||||
(Pointer *) ¤tScanDesc); /* return: scan desc */
|
||||
|
||||
scanstate->css_currentRelation = currentRelation;
|
||||
scanstate->css_currentScanDesc = currentScanDesc;
|
||||
|
||||
ExecAssignScanType(scanstate,
|
||||
RelationGetTupleDescriptor(currentRelation));
|
||||
} else {
|
||||
/* ----------------
|
||||
* otherwise we are scanning tuples from the
|
||||
* outer subplan so we initialize the outer plan
|
||||
* and nullify
|
||||
* ----------------
|
||||
*/
|
||||
ExecInitNode(outerPlan, estate, (Plan*)node);
|
||||
|
||||
node->scanrelid = 0;
|
||||
scanstate->css_currentRelation = NULL;
|
||||
scanstate->css_currentScanDesc = NULL;
|
||||
ExecAssignScanType(scanstate, NULL);
|
||||
reloid = InvalidOid;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* return the relation
|
||||
* ----------------
|
||||
*/
|
||||
return reloid;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecInitSeqScan
|
||||
*
|
||||
* old comments
|
||||
* Creates the run-time state information for the seqscan node
|
||||
* and sets the relation id to contain relevant descriptors.
|
||||
*
|
||||
* If there is a outer subtree (sort), the outer subtree
|
||||
* is initialized and the relation id is set to the descriptors
|
||||
* returned by the subtree.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
bool
|
||||
ExecInitSeqScan(SeqScan *node, EState *estate, Plan *parent)
|
||||
{
|
||||
CommonScanState *scanstate;
|
||||
Plan *outerPlan;
|
||||
Oid reloid;
|
||||
HeapScanDesc scandesc;
|
||||
|
||||
/* ----------------
|
||||
* assign the node's execution state
|
||||
* ----------------
|
||||
*/
|
||||
node->plan.state = estate;
|
||||
|
||||
/* ----------------
|
||||
* create new CommonScanState for node
|
||||
* ----------------
|
||||
*/
|
||||
scanstate = makeNode(CommonScanState);
|
||||
node->scanstate = scanstate;
|
||||
|
||||
/* ----------------
|
||||
* Miscellanious initialization
|
||||
*
|
||||
* + assign node's base_id
|
||||
* + create expression context for node
|
||||
* ----------------
|
||||
*/
|
||||
ExecAssignNodeBaseInfo(estate, &scanstate->cstate, parent);
|
||||
ExecAssignExprContext(estate, &scanstate->cstate);
|
||||
|
||||
#define SEQSCAN_NSLOTS 3
|
||||
/* ----------------
|
||||
* tuple table initialization
|
||||
* ----------------
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &scanstate->cstate);
|
||||
ExecInitScanTupleSlot(estate, scanstate);
|
||||
|
||||
/* ----------------
|
||||
* initialize scan relation or outer subplan
|
||||
* ----------------
|
||||
*/
|
||||
outerPlan = outerPlan((Plan *)node);
|
||||
|
||||
reloid = InitScanRelation(node, estate, scanstate, outerPlan);
|
||||
|
||||
scandesc = scanstate->css_currentScanDesc;
|
||||
scanstate->cstate.cs_TupFromTlist = false;
|
||||
|
||||
/* ----------------
|
||||
* initialize tuple type
|
||||
* ----------------
|
||||
*/
|
||||
ExecAssignResultTypeFromTL((Plan*)node, &scanstate->cstate);
|
||||
ExecAssignProjectionInfo((Plan*)node, &scanstate->cstate);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
ExecCountSlotsSeqScan(SeqScan *node)
|
||||
{
|
||||
return ExecCountSlotsNode(outerPlan(node)) +
|
||||
ExecCountSlotsNode(innerPlan(node)) +
|
||||
SEQSCAN_NSLOTS;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecEndSeqScan
|
||||
*
|
||||
* frees any storage allocated through C routines.
|
||||
*| ...and also closes relations and/or shuts down outer subplan
|
||||
*| -cim 8/14/89
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
ExecEndSeqScan(SeqScan *node)
|
||||
{
|
||||
CommonScanState *scanstate;
|
||||
Plan *outerPlan;
|
||||
|
||||
/* ----------------
|
||||
* get information from node
|
||||
* ----------------
|
||||
*/
|
||||
scanstate = node->scanstate;
|
||||
|
||||
/* ----------------
|
||||
* Free the projection info and the scan attribute info
|
||||
*
|
||||
* Note: we don't ExecFreeResultType(scanstate)
|
||||
* because the rule manager depends on the tupType
|
||||
* returned by ExecMain(). So for now, this
|
||||
* is freed at end-transaction time. -cim 6/2/91
|
||||
* ----------------
|
||||
*/
|
||||
ExecFreeProjectionInfo(&scanstate->cstate);
|
||||
|
||||
/* ----------------
|
||||
* close scan relation
|
||||
* ----------------
|
||||
*/
|
||||
ExecCloseR((Plan*) node);
|
||||
|
||||
/* ----------------
|
||||
* clean up outer subtree (does nothing if there is no outerPlan)
|
||||
* ----------------
|
||||
*/
|
||||
outerPlan = outerPlan((Plan *)node);
|
||||
ExecEndNode(outerPlan, (Plan*)node);
|
||||
|
||||
/* ----------------
|
||||
* clean out the tuple table
|
||||
* ----------------
|
||||
*/
|
||||
ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
|
||||
ExecClearTuple(scanstate->css_ScanTupleSlot);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* Join Support
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecSeqReScan
|
||||
*
|
||||
* Rescans the relation.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan* parent)
|
||||
{
|
||||
CommonScanState *scanstate;
|
||||
EState *estate;
|
||||
Plan *outerPlan;
|
||||
Relation rdesc;
|
||||
HeapScanDesc sdesc;
|
||||
ScanDirection direction;
|
||||
|
||||
scanstate = node->scanstate;
|
||||
estate = node->plan.state;
|
||||
|
||||
outerPlan = outerPlan((Plan*)node);
|
||||
if (outerPlan) {
|
||||
/* we are scanning a subplan */
|
||||
outerPlan = outerPlan((Plan *)node);
|
||||
ExecReScan(outerPlan, exprCtxt, parent);
|
||||
} else {
|
||||
/* otherwise, we are scanning a relation */
|
||||
rdesc = scanstate->css_currentRelation;
|
||||
sdesc = scanstate->css_currentScanDesc;
|
||||
direction = estate->es_direction;
|
||||
sdesc = ExecReScanR(rdesc, sdesc, direction, 0, NULL);
|
||||
scanstate->css_currentScanDesc = sdesc;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecSeqMarkPos(node)
|
||||
*
|
||||
* Marks scan position.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
ExecSeqMarkPos(SeqScan *node)
|
||||
{
|
||||
CommonScanState *scanstate;
|
||||
Plan *outerPlan;
|
||||
HeapScanDesc sdesc;
|
||||
|
||||
scanstate = node->scanstate;
|
||||
|
||||
/* ----------------
|
||||
* if we are scanning a subplan then propagate
|
||||
* the ExecMarkPos() request to the subplan
|
||||
* ----------------
|
||||
*/
|
||||
outerPlan = outerPlan((Plan*)node);
|
||||
if (outerPlan) {
|
||||
ExecMarkPos(outerPlan);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* otherwise we are scanning a relation so mark the
|
||||
* position using the access methods..
|
||||
*
|
||||
* ----------------
|
||||
*/
|
||||
sdesc = scanstate->css_currentScanDesc;
|
||||
heap_markpos(sdesc);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecSeqRestrPos
|
||||
*
|
||||
* Restores scan position.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
ExecSeqRestrPos(SeqScan *node)
|
||||
{
|
||||
CommonScanState *scanstate;
|
||||
Plan *outerPlan;
|
||||
HeapScanDesc sdesc;
|
||||
|
||||
scanstate = node->scanstate;
|
||||
|
||||
/* ----------------
|
||||
* if we are scanning a subplan then propagate
|
||||
* the ExecRestrPos() request to the subplan
|
||||
* ----------------
|
||||
*/
|
||||
outerPlan = outerPlan((Plan*)node);
|
||||
if (outerPlan) {
|
||||
ExecRestrPos(outerPlan);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* otherwise we are scanning a relation so restore the
|
||||
* position using the access methods..
|
||||
* ----------------
|
||||
*/
|
||||
sdesc = scanstate->css_currentScanDesc;
|
||||
heap_restrpos(sdesc);
|
||||
}
|
Reference in New Issue
Block a user