aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execScan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execScan.c')
-rw-r--r--src/backend/executor/execScan.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c
new file mode 100644
index 00000000000..96dd5551289
--- /dev/null
+++ b/src/backend/executor/execScan.c
@@ -0,0 +1,136 @@
+/*-------------------------------------------------------------------------
+ *
+ * execScan.c--
+ * This code provides support for generalized relation scans. ExecScan
+ * is passed a node and a pointer to a function to "do the right thing"
+ * and return a tuple from the relation. ExecScan then does the tedious
+ * stuff - checking the qualification and projecting the tuple
+ * appropriately.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/backend/executor/execScan.c,v 1.1.1.1 1996/07/09 06:21:25 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include <sys/file.h>
+#include "executor/executor.h"
+
+/* ----------------------------------------------------------------
+ * ExecScan
+ *
+ * Scans the relation using the 'access method' indicated and
+ * returns the next qualifying tuple in the direction specified
+ * in the global variable ExecDirection.
+ * The access method returns the next tuple and execScan() is
+ * responisble for checking the tuple returned against the qual-clause.
+ *
+ * Conditions:
+ * -- the "cursor" maintained by the AMI is positioned at the tuple
+ * returned previously.
+ *
+ * Initial States:
+ * -- the relation indicated is opened for scanning so that the
+ * "cursor" is positioned before the first qualifying tuple.
+ *
+ * May need to put startmmgr and endmmgr in here.
+ * ----------------------------------------------------------------
+ */
+TupleTableSlot *
+ExecScan(Scan *node,
+ TupleTableSlot* (*accessMtd)()) /* function returning a tuple */
+{
+ CommonScanState *scanstate;
+ EState *estate;
+ List *qual;
+ bool isDone;
+
+ TupleTableSlot *slot;
+ TupleTableSlot *resultSlot;
+ HeapTuple newTuple;
+
+ ExprContext *econtext;
+ ProjectionInfo *projInfo;
+
+
+ /* ----------------
+ * initialize misc variables
+ * ----------------
+ */
+ newTuple = NULL;
+ slot = NULL;
+
+ estate = node->plan.state;
+ scanstate = node->scanstate;
+
+ /* ----------------
+ * get the expression context
+ * ----------------
+ */
+ econtext = scanstate->cstate.cs_ExprContext;
+
+ /* ----------------
+ * initialize fields in ExprContext which don't change
+ * in the course of the scan..
+ * ----------------
+ */
+ qual = node->plan.qual;
+ econtext->ecxt_relation = scanstate->css_currentRelation;
+ econtext->ecxt_relid = node->scanrelid;
+
+ if (scanstate->cstate.cs_TupFromTlist) {
+ projInfo = scanstate->cstate.cs_ProjInfo;
+ resultSlot = ExecProject(projInfo, &isDone);
+ if (!isDone)
+ return resultSlot;
+ }
+ /*
+ * get a tuple from the access method
+ * loop until we obtain a tuple which passes the qualification.
+ */
+ for(;;) {
+ slot = (TupleTableSlot *) (*accessMtd)(node);
+
+ /* ----------------
+ * if the slot returned by the accessMtd contains
+ * NULL, then it means there is nothing more to scan
+ * so we just return the empty slot.
+ * ----------------
+ */
+ if (TupIsNull(slot)) return slot;
+
+ /* ----------------
+ * place the current tuple into the expr context
+ * ----------------
+ */
+ econtext->ecxt_scantuple = slot;
+
+ /* ----------------
+ * check that the current tuple satisfies the qual-clause
+ * if our qualification succeeds then we
+ * leave the loop.
+ * ----------------
+ */
+
+ /* add a check for non-nil qual here to avoid a
+ function call to ExecQual() when the qual is nil */
+ if (!qual || ExecQual(qual, econtext) == true)
+ break;
+ }
+
+ /* ----------------
+ * form a projection tuple, store it in the result tuple
+ * slot and return it.
+ * ----------------
+ */
+ projInfo = scanstate->cstate.cs_ProjInfo;
+
+ resultSlot = ExecProject(projInfo, &isDone);
+ scanstate->cstate.cs_TupFromTlist = !isDone;
+
+ return resultSlot;
+}
+