aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeSeqscan.c
diff options
context:
space:
mode:
authorMarc G. Fournier <scrappy@hub.org>1996-07-09 06:22:35 +0000
committerMarc G. Fournier <scrappy@hub.org>1996-07-09 06:22:35 +0000
commitd31084e9d1118b25fd16580d9d8c2924b5740dff (patch)
tree3179e66307d54df9c7b966543550e601eb55e668 /src/backend/executor/nodeSeqscan.c
downloadpostgresql-PG95-1_01.tar.gz
postgresql-PG95-1_01.zip
Postgres95 1.01 Distribution - Virgin SourcesPG95-1_01
Diffstat (limited to 'src/backend/executor/nodeSeqscan.c')
-rw-r--r--src/backend/executor/nodeSeqscan.c449
1 files changed, 449 insertions, 0 deletions
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
new file mode 100644
index 00000000000..a0e434c4bb0
--- /dev/null
+++ b/src/backend/executor/nodeSeqscan.c
@@ -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 */
+ &currentRelation, /* return: rel desc */
+ (Pointer *) &currentScanDesc); /* 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);
+}