nodeSeqscan.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:13k
- /*-------------------------------------------------------------------------
- *
- * nodeSeqscan.c
- * Support routines for sequential scans of relations.
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /usr/local/cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.18 1999/05/25 16:08:46 momjian 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 "postgres.h"
- #include "executor/executor.h"
- #include "executor/execdebug.h"
- #include "executor/nodeSeqscan.h"
- #include "access/heapam.h"
- #include "parser/parsetree.h"
- #include "nodes/print.h"
- static Oid InitScanRelation(SeqScan *node, EState *estate,
- CommonScanState *scanstate, Plan *outerPlan);
- static TupleTableSlot *SeqNext(SeqScan *node);
- /* ----------------------------------------------------------------
- * Scan Support
- * ----------------------------------------------------------------
- */
- /* ----------------------------------------------------------------
- * SeqNext
- *
- * This is a workhorse for ExecSeqScan
- * ----------------------------------------------------------------
- */
- static TupleTableSlot *
- SeqNext(SeqScan *node)
- {
- HeapTuple tuple;
- HeapScanDesc scandesc;
- CommonScanState *scanstate;
- EState *estate;
- ScanDirection direction;
- TupleTableSlot *slot;
- /* ----------------
- * get information from the estate and scan state
- * ----------------
- */
- estate = node->plan.state;
- scanstate = node->scanstate;
- scandesc = scanstate->css_currentScanDesc;
- direction = estate->es_direction;
- slot = scanstate->css_ScanTupleSlot;
- /*
- * Check if we are evaluating PlanQual for tuple of this relation.
- * Additional checking is not good, but no other way for now. We could
- * introduce new nodes for this case and handle SeqScan --> NewNode
- * switching in Init/ReScan plan...
- */
- if (estate->es_evTuple != NULL &&
- estate->es_evTuple[node->scanrelid - 1] != NULL)
- {
- slot->ttc_buffer = InvalidBuffer;
- slot->ttc_shouldFree = false;
- if (estate->es_evTupleNull[node->scanrelid - 1])
- {
- slot->val = NULL; /* must not free tuple! */
- return (slot);
- }
- slot->val = estate->es_evTuple[node->scanrelid - 1];
- /*
- * Note that unlike IndexScan, SeqScan never use keys in
- * heap_beginscan (and this is very bad) - so, here we have not
- * check are keys ok or not.
- */
- /* Flag for the next call that no more tuples */
- estate->es_evTupleNull[node->scanrelid - 1] = true;
- return (slot);
- }
- /* ----------------
- * get the next tuple from the access methods
- * ----------------
- */
- tuple = heap_getnext(scandesc, ScanDirectionIsBackward(direction));
- /* ----------------
- * 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 = ExecStoreTuple(tuple,/* tuple to store */
- slot, /* slot to store in */
- scandesc->rs_cbuf, /* 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
- * ----------------
- */
- if ((outerPlan = outerPlan((Plan *) node)) != NULL)
- slot = ExecProcNode(outerPlan, (Plan *) node);
- else
- slot = ExecScan(node, SeqNext);
- S1_printf("ExecSeqScan: returned tuple slot: %dn", slot);
- return slot;
- }
- /* ----------------------------------------------------------------
- * InitScanRelation
- *
- * This does the initialization for scan relations and
- * subplans of scans.
- * ----------------------------------------------------------------
- */
- static Oid
- InitScanRelation(SeqScan *node, EState *estate,
- CommonScanState *scanstate, Plan *outerPlan)
- {
- Index relid;
- List *rangeTable;
- RangeTblEntry *rtentry;
- Oid reloid;
- 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;
- direction = estate->es_direction;
- resultRelationInfo = estate->es_result_relation_info;
- ExecOpenScanR(reloid, /* relation */
- 0, /* nkeys */
- NULL, /* scan key */
- 0, /* is index */
- direction,/* scan direction */
- estate->es_snapshot,
- ¤tRelation, /* return: rel desc */
- (Pointer *) ¤tScanDesc); /* return: scan desc */
- scanstate->css_currentRelation = currentRelation;
- scanstate->css_currentScanDesc = currentScanDesc;
- ExecAssignScanType(scanstate,
- RelationGetDescr(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 rel;
- HeapScanDesc scan;
- ScanDirection direction;
- scanstate = node->scanstate;
- estate = node->plan.state;
- if ((outerPlan = outerPlan((Plan *) node)) != NULL)
- {
- /* we are scanning a subplan */
- outerPlan = outerPlan((Plan *) node);
- ExecReScan(outerPlan, exprCtxt, parent);
- }
- else
- /* otherwise, we are scanning a relation */
- {
- /* If this is re-scanning of PlanQual ... */
- if (estate->es_evTuple != NULL &&
- estate->es_evTuple[node->scanrelid - 1] != NULL)
- {
- estate->es_evTupleNull[node->scanrelid - 1] = false;
- return;
- }
- rel = scanstate->css_currentRelation;
- scan = scanstate->css_currentScanDesc;
- direction = estate->es_direction;
- scan = ExecReScanR(rel, scan, direction, 0, NULL);
- scanstate->css_currentScanDesc = scan;
- }
- }
- /* ----------------------------------------------------------------
- * ExecSeqMarkPos(node)
- *
- * Marks scan position.
- * ----------------------------------------------------------------
- */
- void
- ExecSeqMarkPos(SeqScan *node)
- {
- CommonScanState *scanstate;
- Plan *outerPlan;
- HeapScanDesc scan;
- 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..
- *
- * ----------------
- */
- scan = scanstate->css_currentScanDesc;
- heap_markpos(scan);
- return;
- }
- /* ----------------------------------------------------------------
- * ExecSeqRestrPos
- *
- * Restores scan position.
- * ----------------------------------------------------------------
- */
- void
- ExecSeqRestrPos(SeqScan *node)
- {
- CommonScanState *scanstate;
- Plan *outerPlan;
- HeapScanDesc scan;
- 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..
- * ----------------
- */
- scan = scanstate->css_currentScanDesc;
- heap_restrpos(scan);
- }