diff options
Diffstat (limited to 'src/backend/executor/execScan.c')
-rw-r--r-- | src/backend/executor/execScan.c | 136 |
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; +} + |