diff options
Diffstat (limited to 'src/backend/executor/execProcnode.c')
-rw-r--r-- | src/backend/executor/execProcnode.c | 477 |
1 files changed, 477 insertions, 0 deletions
diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c new file mode 100644 index 00000000000..11a6f63a778 --- /dev/null +++ b/src/backend/executor/execProcnode.c @@ -0,0 +1,477 @@ +/*------------------------------------------------------------------------- + * + * execProcnode.c-- + * contains dispatch functions which call the appropriate "initialize", + * "get a tuple", and "cleanup" routines for the given node type. + * If the node has children, then it will presumably call ExecInitNode, + * ExecProcNode, or ExecEndNode on it's subnodes and do the appropriate + * processing.. + * + * Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.1.1.1 1996/07/09 06:21:25 scrappy Exp $ + * + *------------------------------------------------------------------------- + */ +/* + * INTERFACE ROUTINES + * ExecInitNode - initialize a plan node and it's subplans + * ExecProcNode - get a tuple by executing the plan node + * ExecEndNode - shut down a plan node and it's subplans + * + * NOTES + * This used to be three files. It is now all combined into + * one file so that it is easier to keep ExecInitNode, ExecProcNode, + * and ExecEndNode in sync when new nodes are added. + * + * EXAMPLE + * suppose we want the age of the manager of the shoe department and + * the number of employees in that department. so we have the query: + * + * retrieve (DEPT.no_emps, EMP.age) + * where EMP.name = DEPT.mgr and + * DEPT.name = "shoe" + * + * Suppose the planner gives us the following plan: + * + * Nest Loop (DEPT.mgr = EMP.name) + * / \ + * / \ + * Seq Scan Seq Scan + * DEPT EMP + * (name = "shoe") + * + * ExecStart() is called first. + * It calls InitPlan() which calls ExecInitNode() on + * the root of the plan -- the nest loop node. + * + * * ExecInitNode() notices that it is looking at a nest loop and + * as the code below demonstrates, it calls ExecInitNestLoop(). + * Eventually this calls ExecInitNode() on the right and left subplans + * and so forth until the entire plan is initialized. + * + * * Then when ExecRun() is called, it calls ExecutePlan() which + * calls ExecProcNode() repeatedly on the top node of the plan. + * Each time this happens, ExecProcNode() will end up calling + * ExecNestLoop(), which calls ExecProcNode() on its subplans. + * Each of these subplans is a sequential scan so ExecSeqScan() is + * called. The slots returned by ExecSeqScan() may contain + * tuples which contain the attributes ExecNestLoop() uses to + * form the tuples it returns. + * + * * Eventually ExecSeqScan() stops returning tuples and the nest + * loop join ends. Lastly, ExecEnd() calls ExecEndNode() which + * calls ExecEndNestLoop() which in turn calls ExecEndNode() on + * its subplans which result in ExecEndSeqScan(). + * + * This should show how the executor works by having + * ExecInitNode(), ExecProcNode() and ExecEndNode() dispatch + * their work to the appopriate node support routines which may + * in turn call these routines themselves on their subplans. + * + */ +#include "executor/executor.h" +#include "executor/nodeResult.h" +#include "executor/nodeAppend.h" +#include "executor/nodeSeqscan.h" +#include "executor/nodeIndexscan.h" +#include "executor/nodeNestloop.h" +#include "executor/nodeMergejoin.h" +#include "executor/nodeMaterial.h" +#include "executor/nodeSort.h" +#include "executor/nodeUnique.h" +#include "executor/nodeGroup.h" +#include "executor/nodeAgg.h" +#include "executor/nodeHash.h" +#include "executor/nodeHashjoin.h" +#include "executor/nodeTee.h" + +/* ------------------------------------------------------------------------ + * ExecInitNode + * + * Recursively initializes all the nodes in the plan rooted + * at 'node'. + * + * Initial States: + * 'node' is the plan produced by the query planner + * + * returns TRUE/FALSE on whether the plan was successfully initialized + * ------------------------------------------------------------------------ + */ +bool +ExecInitNode(Plan *node, EState *estate, Plan *parent) +{ + bool result; + + /* ---------------- + * do nothing when we get to the end + * of a leaf on tree. + * ---------------- + */ + if (node == NULL) + return FALSE; + + switch(nodeTag(node)) { + /* ---------------- + * control nodes + * ---------------- + */ + case T_Result: + result = ExecInitResult((Result *)node, estate, parent); + break; + + case T_Append: + result = ExecInitAppend((Append *)node, estate, parent); + break; + + /* ---------------- + * scan nodes + * ---------------- + */ + case T_SeqScan: + result = ExecInitSeqScan((SeqScan *)node, estate, parent); + break; + + case T_IndexScan: + result = ExecInitIndexScan((IndexScan *)node, estate, parent); + break; + + /* ---------------- + * join nodes + * ---------------- + */ + case T_NestLoop: + result = ExecInitNestLoop((NestLoop *)node, estate, parent); + break; + + case T_MergeJoin: + result = ExecInitMergeJoin((MergeJoin *)node, estate, parent); + break; + + /* ---------------- + * materialization nodes + * ---------------- + */ + case T_Material: + result = ExecInitMaterial((Material *)node, estate, parent); + break; + + case T_Sort: + result = ExecInitSort((Sort *)node, estate, parent); + break; + + case T_Unique: + result = ExecInitUnique((Unique *)node, estate, parent); + break; + + case T_Group: + result = ExecInitGroup((Group *)node, estate, parent); + break; + + case T_Agg: + result = ExecInitAgg((Agg *)node, estate, parent); + break; + + case T_Hash: + result = ExecInitHash((Hash *)node, estate, parent); + break; + + case T_HashJoin: + result = ExecInitHashJoin((HashJoin *)node, estate, parent); + break; + + case T_Tee: + result = ExecInitTee((Tee*)node, estate, parent); + break; + + default: + elog(DEBUG, "ExecInitNode: node not yet supported: %d", + nodeTag(node)); + result = FALSE; + } + + return result; +} + + +/* ---------------------------------------------------------------- + * ExecProcNode + * + * Initial States: + * the query tree must be initialized once by calling ExecInit. + * ---------------------------------------------------------------- + */ +TupleTableSlot * +ExecProcNode(Plan *node, Plan *parent) +{ + TupleTableSlot *result; + + /* ---------------- + * deal with NULL nodes.. + * ---------------- + */ + if (node == NULL) + return NULL; + + switch(nodeTag(node)) { + /* ---------------- + * control nodes + * ---------------- + */ + case T_Result: + result = ExecResult((Result *)node); + break; + + case T_Append: + result = ExecProcAppend((Append *)node); + break; + + /* ---------------- + * scan nodes + * ---------------- + */ + case T_SeqScan: + result = ExecSeqScan((SeqScan *)node); + break; + + case T_IndexScan: + result = ExecIndexScan((IndexScan *)node); + break; + + /* ---------------- + * join nodes + * ---------------- + */ + case T_NestLoop: + result = ExecNestLoop((NestLoop *)node, parent); + break; + + case T_MergeJoin: + result = ExecMergeJoin((MergeJoin *)node); + break; + + /* ---------------- + * materialization nodes + * ---------------- + */ + case T_Material: + result = ExecMaterial((Material *)node); + break; + + case T_Sort: + result = ExecSort((Sort *)node); + break; + + case T_Unique: + result = ExecUnique((Unique *)node); + break; + + case T_Group: + result = ExecGroup((Group *)node); + break; + + case T_Agg: + result = ExecAgg((Agg *)node); + break; + + case T_Hash: + result = ExecHash((Hash *)node); + break; + + case T_HashJoin: + result = ExecHashJoin((HashJoin *)node); + break; + + case T_Tee: + result = ExecTee((Tee*)node, parent); + break; + + default: + elog(DEBUG, "ExecProcNode: node not yet supported: %d", + nodeTag(node)); + result = FALSE; + } + + return result; +} + +int +ExecCountSlotsNode(Plan *node) +{ + if (node == (Plan *)NULL) + return 0; + + switch(nodeTag(node)) { + /* ---------------- + * control nodes + * ---------------- + */ + case T_Result: + return ExecCountSlotsResult((Result *)node); + + case T_Append: + return ExecCountSlotsAppend((Append *)node); + + /* ---------------- + * scan nodes + * ---------------- + */ + case T_SeqScan: + return ExecCountSlotsSeqScan((SeqScan *)node); + + case T_IndexScan: + return ExecCountSlotsIndexScan((IndexScan *)node); + + /* ---------------- + * join nodes + * ---------------- + */ + case T_NestLoop: + return ExecCountSlotsNestLoop((NestLoop *)node); + + case T_MergeJoin: + return ExecCountSlotsMergeJoin((MergeJoin *)node); + + /* ---------------- + * materialization nodes + * ---------------- + */ + case T_Material: + return ExecCountSlotsMaterial((Material *)node); + + case T_Sort: + return ExecCountSlotsSort((Sort *)node); + + case T_Unique: + return ExecCountSlotsUnique((Unique *)node); + + case T_Group: + return ExecCountSlotsGroup((Group *)node); + + case T_Agg: + return ExecCountSlotsAgg((Agg *)node); + + case T_Hash: + return ExecCountSlotsHash((Hash *)node); + + case T_HashJoin: + return ExecCountSlotsHashJoin((HashJoin *)node); + + case T_Tee: + return ExecCountSlotsTee((Tee*)node); + + default: + elog(WARN, "ExecCountSlotsNode: node not yet supported: %d", + nodeTag(node)); + break; + } + return 0; +} + +/* ---------------------------------------------------------------- + * ExecEndNode + * + * Recursively cleans up all the nodes in the plan rooted + * at 'node'. + * + * After this operation, the query plan will not be able to + * processed any further. This should be called only after + * the query plan has been fully executed. + * ---------------------------------------------------------------- + */ +void +ExecEndNode(Plan *node, Plan *parent) +{ + /* ---------------- + * do nothing when we get to the end + * of a leaf on tree. + * ---------------- + */ + if (node == NULL) + return; + + switch(nodeTag(node)) { + /* ---------------- + * control nodes + * ---------------- + */ + case T_Result: + ExecEndResult((Result *)node); + break; + + case T_Append: + ExecEndAppend((Append *)node); + break; + + /* ---------------- + * scan nodes + * ---------------- + */ + case T_SeqScan: + ExecEndSeqScan((SeqScan *)node); + break; + + case T_IndexScan: + ExecEndIndexScan((IndexScan *)node); + break; + + /* ---------------- + * join nodes + * ---------------- + */ + case T_NestLoop: + ExecEndNestLoop((NestLoop *)node); + break; + + case T_MergeJoin: + ExecEndMergeJoin((MergeJoin *)node); + break; + + /* ---------------- + * materialization nodes + * ---------------- + */ + case T_Material: + ExecEndMaterial((Material *)node); + break; + + case T_Sort: + ExecEndSort((Sort *)node); + break; + + case T_Unique: + ExecEndUnique((Unique *)node); + break; + + case T_Group: + ExecEndGroup((Group *)node); + break; + + case T_Agg: + ExecEndAgg((Agg *)node); + break; + + /* ---------------- + * XXX add hooks to these + * ---------------- + */ + case T_Hash: + ExecEndHash((Hash *) node); + break; + + case T_HashJoin: + ExecEndHashJoin((HashJoin *) node); + break; + + case T_Tee: + ExecEndTee((Tee*) node, parent); + break; + + default: + elog(DEBUG, "ExecEndNode: node not yet supported", + nodeTag(node)); + break; + } +} |