home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / executor / ex_procnode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-10  |  14.1 KB  |  611 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    ex_procnode.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    contains dispatch functions which call the appropriate
  7.  *    "initialize", "get a tuple", and "cleanup" routines for the
  8.  *    given node type.  If the node has children, then it will
  9.  *    presumably call ExecInitNode, ExecProcNode, or ExecEndNode
  10.  *    on it's subnodes and do the appropriate processing..
  11.  *
  12.  *   INTERFACE ROUTINES
  13.  *    ExecInitNode    -    initialize a plan node and it's subplans
  14.  *    ExecProcNode    -    get a tuple by executing the plan node
  15.  *    ExecEndNode    -    shut down a plan node and it's subplans
  16.  *
  17.  *   NOTES
  18.  *    This used to be three files.  It is now all combined into
  19.  *    one file so that it is easier to keep ExecInitNode, ExecProcNode,
  20.  *    and ExecEndNode in sync when new nodes are added.
  21.  *    
  22.  *   EXAMPLE
  23.  *    suppose we want the age of the manager of the shoe department and
  24.  *    the number of employees in that department.  so we have the query:
  25.  *
  26.  *        retrieve (DEPT.no_emps, EMP.age)
  27.  *        where EMP.name = DEPT.mgr and
  28.  *              DEPT.name = "shoe"
  29.  *    
  30.  *    Suppose the planner gives us the following plan:
  31.  *    
  32.  *            Nest Loop (DEPT.mgr = EMP.name)
  33.  *            /    \ 
  34.  *               /         \
  35.  *           Seq Scan    Seq Scan
  36.  *            DEPT      EMP
  37.  *        (name = "shoe")
  38.  *    
  39.  *    ExecMain() is eventually called three times.  The first time
  40.  *    it is called it calls InitPlan() which calls ExecInitNode() on
  41.  *    the root of the plan -- the nest loop node.
  42.  *
  43.  *    *    ExecInitNode() notices that it is looking at a nest loop and
  44.  *    as the code below demonstrates, it calls ExecInitNestLoop().
  45.  *    Eventually this calls ExecInitNode() on the right and left subplans
  46.  *    and so forth until the entire plan is initialized.
  47.  *    
  48.  *    *    The second time ExecMain() is called, it calls ExecutePlan() which
  49.  *    calls ExecProcNode() repeatedly on the top node of the plan.
  50.  *    Each time this happens, ExecProcNode() will end up calling
  51.  *    ExecNestLoop(), which calls ExecProcNode() on its subplans.
  52.  *    Each of these subplans is a sequential scan so ExecSeqScan() is
  53.  *    called.  The slots returned by ExecSeqScan() may contain
  54.  *    tuples which contain the attributes ExecNestLoop() uses to
  55.  *    form the tuples it returns.
  56.  *
  57.  *    *    Eventually ExecSeqScan() stops returning tuples and the nest
  58.  *    loop join ends.  Lastly, ExecMain() calls ExecEndNode() which
  59.  *    calls ExecEndNestLoop() which in turn calls ExecEndNode() on
  60.  *    its subplans which result in ExecEndSeqScan().
  61.  *
  62.  *    This should show how the executor works by having
  63.  *    ExecInitNode(), ExecProcNode() and ExecEndNode() dispatch
  64.  *    their work to the appopriate node support routines which may
  65.  *    in turn call these routines themselves on their subplans.
  66.  *
  67.  *   IDENTIFICATION
  68.  *    $Header: /private/postgres/src/executor/RCS/ex_procnode.c,v 1.4 1992/08/04 17:37:45 mer Exp $
  69.  * ----------------------------------------------------------------
  70.  */
  71.  
  72. #include "executor/executor.h"
  73.  RcsId("$Header: /private/postgres/src/executor/RCS/ex_procnode.c,v 1.4 1992/08/04 17:37:45 mer Exp $");
  74.  
  75. /* ----------------------------------------------------------------
  76.  *    Hook processing macros.  these are used to simplify
  77.  *    the node processing routines below.  For example,
  78.  *
  79.  *        case classTag(Result):
  80.  *        END_WITH_HOOKS(Result,resstate);
  81.  *        break;
  82.  *
  83.  *    becomes
  84.  *    ----------------
  85.  *        case classTag(Result):
  86.  *            {
  87.  *            Pointer p = (Pointer) get_resstate(node);
  88.  *            DO_END_BEFORE_HOOK(p);
  89.  *            ExecEndResult((Result) node);
  90.  *            DO_END_AFTER_HOOK(p);
  91.  *        }
  92.  *        break;
  93.  *
  94.  *    which in turn expands to:
  95.  *    ----------------
  96.  *        case classTag(Result):
  97.  *            {
  98.  *            Pointer p = (Pointer) get_resstate(node);
  99.  *            hook = get_base_hook(p);
  100.  *            if (hook != NULL) {
  101.  *                proc = get_hook_pre_endnode(hook);
  102.  *            (*proc)(node, state);
  103.  *            }
  104.  *            ExecEndResult((Result) node);
  105.  *            if (hook != NULL) { 
  106.  *            proc = get_hook_post_endnode(hook);
  107.  *            (*proc)(node, state);
  108.  *            }
  109.  *        }
  110.  *        break;
  111.  *
  112.  *    Hook functions are currently only used for debugging and
  113.  *    generating plan traces.  If EXEC_ASSIGNDEBUGHOOKS is not defined
  114.  *    in H/executor/execdebug.h then the macros only expand to something
  115.  *    like:
  116.  *
  117.  *        case classTag(Result):
  118.  *        ExecEndResult((Result) node);
  119.  *        break;
  120.  *    
  121.  * ----------------------------------------------------------------
  122.  */
  123.  
  124. /* ----------------
  125.  *    do_hooks macros
  126.  * ----------------
  127.  */
  128. #define DO_INIT_AFTER_HOOK(state) \
  129.     hook = get_base_hook(state); \
  130.     if (hook != NULL) { \
  131.     proc = get_hook_post_initnode(hook); \
  132.     (*proc)(node, state); \
  133.     }
  134.  
  135. #define DO_PROC_BEFORE_HOOK(state) \
  136.     hook = get_base_hook(state); \
  137.     if (hook != NULL) { \
  138.     proc = get_hook_pre_procnode(hook); \
  139.     (*proc)(node, state); \
  140.     }
  141.  
  142. #define DO_PROC_AFTER_HOOK(state) \
  143.     if (hook != NULL) { \
  144.     proc = get_hook_post_procnode(hook); \
  145.     (*proc)(node, state); \
  146.     }
  147.  
  148. #define DO_END_BEFORE_HOOK(state) \
  149.     hook = get_base_hook(state); \
  150.     if (hook != NULL) { \
  151.     proc = get_hook_pre_endnode(hook); \
  152.     (*proc)(node, state); \
  153.     }
  154.  
  155. #define DO_END_AFTER_HOOK(state) \
  156.     if (hook != NULL) { \
  157.     proc = get_hook_post_endnode(hook); \
  158.     (*proc)(node, state); \
  159.     }
  160.  
  161. /* ----------------
  162.  *    with_hooks macros
  163.  * ----------------
  164.  */
  165. #ifdef EXEC_ASSIGNDEBUGHOOKS
  166.  
  167. #define INIT_WITH_HOOKS(n,s) \
  168. { \
  169.     Pointer p; \
  170.     result = (List) CppConcat(ExecInit,n)((n) node, estate, parent); \
  171.     p = (Pointer) CppConcat(get_,s)(node); \
  172.     DO_INIT_AFTER_HOOK(p); \
  173. }
  174.  
  175. #define PROC_WITH_HOOKS(f,n,s) \
  176. { \
  177.     Pointer p = (Pointer) CppConcat(get_,s)(node); \
  178.     DO_PROC_BEFORE_HOOK(p); \
  179.     result = (TupleTableSlot) f((n) node); \
  180.     DO_PROC_AFTER_HOOK(p); \
  181. }
  182.  
  183. #define END_WITH_HOOKS(n,s) \
  184. { \
  185.     Pointer p = (Pointer) CppConcat(get_,s)(node); \
  186.     DO_END_BEFORE_HOOK(p); \
  187.     CppConcat(ExecEnd,n)((n) node); \
  188.     DO_END_AFTER_HOOK(p); \
  189. }
  190.  
  191. #else /*EXEC_ASSIGNDEBUGHOOKS*/
  192.  
  193. #define INIT_WITH_HOOKS(n,s) \
  194.     result = (List) CppConcat(ExecInit,n)((n) node, estate, parent);
  195.  
  196. #define PROC_WITH_HOOKS(f,n,s) \
  197.     result = (TupleTableSlot) f((n) node);
  198.  
  199. #define END_WITH_HOOKS(n,s) \
  200.     CppConcat(ExecEnd,n)((n) node);
  201.     
  202. #endif /*EXEC_ASSIGNDEBUGHOOKS*/
  203.  
  204. /* ----------------------------------------------------------------
  205.  *       ExecInitNode
  206.  *   
  207.  *       Recursively initializes all the nodes in the plan rooted
  208.  *       at 'node'. 
  209.  *   
  210.  *       Initial States:
  211.  *         'node' is the plan produced by the query planner
  212.  * ----------------------------------------------------------------
  213.  */
  214. List
  215. ExecInitNode(node, estate, parent)
  216.     Plan     node;
  217.     EState     estate;
  218.     Plan     parent;
  219. {
  220.     List           result;
  221.     HookNode         hook;
  222.     HookFunction     proc;
  223.  
  224.     /* ----------------
  225.      *    do nothing when we get to the end
  226.      *  of a leaf on tree.
  227.      * ----------------
  228.      */   
  229.     if (node == NULL)
  230.     return LispNil;
  231.     
  232.     switch(NodeType(node)) {
  233.     /* ----------------
  234.      *    control nodes
  235.      * ----------------
  236.      */
  237.     case classTag(Result):
  238. /*    INIT_WITH_HOOKS( Result,resstate); type casting problem*/ 
  239.     result = (List) ExecInitResult((Plan) node, estate, parent);    
  240.     break;
  241.     
  242.     case classTag(Append):
  243.     INIT_WITH_HOOKS(Append,unionstate);
  244.     break;
  245.               
  246.     /* ----------------
  247.      *    scan nodes
  248.      * ----------------
  249.      */
  250.     case classTag(SeqScan):
  251. /*    INIT_WITH_HOOKS((Plan) SeqScan,scanstate); type casting problem */
  252.     result = (List) ExecInitSeqScan((Plan) node, estate, parent);    
  253.     break;
  254.  
  255.     case classTag(IndexScan):
  256.     INIT_WITH_HOOKS(IndexScan,indxstate);
  257.     break;
  258.     
  259.     /* ----------------
  260.      *    join nodes
  261.      * ----------------
  262.      */
  263.     case classTag(NestLoop):
  264.     INIT_WITH_HOOKS(NestLoop,nlstate);
  265.     break;
  266.  
  267.     case classTag(MergeJoin):
  268.     INIT_WITH_HOOKS(MergeJoin,mergestate);
  269.     break;
  270.     
  271.     /* ----------------
  272.      *    materialization nodes
  273.      * ----------------
  274.      */
  275.     case classTag(Material):
  276.     INIT_WITH_HOOKS(Material,matstate);
  277.     break;
  278.  
  279.     case classTag(Sort):
  280.     INIT_WITH_HOOKS(Sort,sortstate);
  281.     break;
  282.  
  283.     case classTag(Unique):
  284.     INIT_WITH_HOOKS(Unique,uniquestate);
  285.     break;
  286.  
  287.     case classTag(Agg):
  288.     INIT_WITH_HOOKS(Agg, aggstate);
  289.     break;
  290.         
  291.     /* ----------------
  292.      *    XXX add hooks to these
  293.      * ----------------
  294.      */
  295.     case classTag(Hash):
  296.     result = (List) ExecInitHash((Hash) node,
  297.                      estate,
  298.                      parent);
  299.     break;
  300.     
  301.     case classTag(HashJoin):
  302.     result = (List) ExecInitHashJoin((HashJoin) node,
  303.                      estate,
  304.                      parent);
  305.     break;
  306.     
  307.     case classTag(ScanTemps):
  308.     result = (List) ExecInitScanTemps((ScanTemps) node,
  309.                       estate,
  310.                       parent);
  311.     break;
  312.     
  313.     default:
  314.     elog(DEBUG, "ExecInitNode: node not yet supported: %d",
  315.          NodeGetTag(node));
  316.     result = LispNil;
  317.     }
  318.     
  319.     return result;
  320. }
  321.  
  322.  
  323. /* ----------------------------------------------------------------
  324.  *       ExecProcNode
  325.  *   
  326.  *       Initial States:
  327.  *         the query tree must be initialized once by calling ExecInit.
  328.  * ----------------------------------------------------------------
  329.  */
  330. TupleTableSlot
  331. ExecProcNode(node)
  332.     Plan node;
  333. {
  334.     TupleTableSlot    result;
  335.     HookNode         hook;
  336.     HookFunction     proc;
  337.  
  338.     extern int testFlag;
  339.     extern bool _exec_collect_stats_;
  340.  
  341.     /* ----------------
  342.      *    deal with NULL nodes..
  343.      * ----------------
  344.      */
  345.     if (node == NULL)
  346.     return NULL;
  347.  
  348.     switch(NodeType(node)) {
  349.     /* ----------------
  350.      *    control nodes
  351.      * ----------------
  352.      */
  353.     case classTag(Result):
  354.     PROC_WITH_HOOKS(ExecResult,Result,resstate);
  355.     break;
  356.     
  357.     case classTag(Append):
  358.     PROC_WITH_HOOKS(ExecProcAppend,Append,unionstate);
  359.     break;
  360.            
  361.     /* ----------------
  362.      *    scan nodes
  363.      * ----------------
  364.      */
  365.     case classTag(SeqScan):
  366.     PROC_WITH_HOOKS(ExecSeqScan,SeqScan,scanstate);
  367.     break;
  368.  
  369.     case classTag(IndexScan):
  370.     PROC_WITH_HOOKS(ExecIndexScan,IndexScan,indxstate);
  371.     break;
  372.  
  373.     /* ----------------
  374.      *    join nodes
  375.      * ----------------
  376.      */
  377.     case classTag(NestLoop):
  378.     PROC_WITH_HOOKS(ExecNestLoop,NestLoop,nlstate);
  379.     break;
  380.  
  381.     case classTag(MergeJoin):
  382.     PROC_WITH_HOOKS(ExecMergeJoin,MergeJoin,mergestate);
  383.     break;
  384.  
  385.     /* ----------------
  386.      *    materialization nodes
  387.      * ----------------
  388.      */
  389.     case classTag(Material):
  390.     PROC_WITH_HOOKS(ExecMaterial,Material,matstate);
  391.     break;
  392.  
  393.     case classTag(Sort):
  394.     PROC_WITH_HOOKS(ExecSort,Sort,sortstate);
  395.     break;
  396.  
  397.     case classTag(Unique):
  398.     PROC_WITH_HOOKS(ExecUnique,Unique,uniquestate);
  399.     break;
  400.  
  401.     case classTag(Agg):
  402.     PROC_WITH_HOOKS(ExecAgg, Agg, aggstate);
  403.     break;
  404.  
  405.  
  406.     /* ----------------
  407.      *  XXX add hooks to these
  408.      * ----------------
  409.      */
  410.     case classTag(Hash):
  411.     result = (TupleTableSlot) ExecHash((Hash) node);
  412.     break;
  413.    
  414.     case classTag(HashJoin):
  415.     result = (TupleTableSlot) ExecHashJoin((HashJoin) node);
  416.     break;
  417.     
  418.     case classTag(ScanTemps):
  419.     result = (TupleTableSlot) ExecScanTemps((ScanTemps) node);
  420.     break;
  421.  
  422.     default:
  423.     elog(DEBUG, "ExecProcNode: node not yet supported: %d",
  424.          NodeGetTag(node));
  425.     result = (TupleTableSlot) NULL;
  426.     }
  427.     
  428.     if (_exec_collect_stats_ && testFlag && !TupIsNull((Pointer) result))
  429.     set_plan_size(node, get_plan_size(node) + 1);
  430.     
  431.     return result;
  432. }
  433.  
  434. int
  435. ExecCountSlotsNode(node)
  436.     Plan node;
  437. {
  438.     if (node == (Plan)NULL)
  439.     return 0;
  440.  
  441.     switch(NodeType(node)) {
  442.     /* ----------------
  443.      *    control nodes
  444.      * ----------------
  445.      */
  446.     case classTag(Result):
  447.     return ExecCountSlotsResult(node);
  448.     
  449.     case classTag(Append):
  450.     return ExecCountSlotsAppend(node);
  451.               
  452.     /* ----------------
  453.      *    scan nodes
  454.      * ----------------
  455.      */
  456.     case classTag(SeqScan):
  457.     return ExecCountSlotsSeqScan(node);
  458.  
  459.     case classTag(IndexScan):
  460.     return ExecCountSlotsIndexScan(node);
  461.     
  462.     /* ----------------
  463.      *    join nodes
  464.      * ----------------
  465.      */
  466.     case classTag(NestLoop):
  467.     return ExecCountSlotsNestLoop(node);
  468.  
  469.     case classTag(MergeJoin):
  470.     return ExecCountSlotsMergeJoin(node);
  471.     
  472.     /* ----------------
  473.      *    materialization nodes
  474.      * ----------------
  475.      */
  476.     case classTag(Material):
  477.     return ExecCountSlotsMaterial(node);
  478.  
  479.     case classTag(Sort):
  480.     return ExecCountSlotsSort(node);
  481.  
  482.     case classTag(Unique):
  483.     return ExecCountSlotsUnique(node);
  484.  
  485.     case classTag(Agg):
  486.     return ExecCountSlotsAgg(node);
  487.         
  488.     case classTag(Hash):
  489.     return ExecCountSlotsHash(node);
  490.     
  491.     case classTag(HashJoin):
  492.     return ExecCountSlotsHashJoin(node);
  493.     
  494.     case classTag(ScanTemps):
  495.     return ExecCountSlotsScanTemps(node);
  496.     
  497.     default:
  498.     elog(WARN, "ExecCountSlotsNode: node not yet supported: %d",
  499.          NodeGetTag(node));
  500.     break;
  501.     }
  502.     return 0;
  503. }
  504.  
  505. /* ----------------------------------------------------------------  
  506.  *       ExecEndNode
  507.  *   
  508.  *       Recursively cleans up all the nodes in the plan rooted
  509.  *       at 'node'.
  510.  *
  511.  *       After this operation, the query plan will not be able to
  512.  *    processed any further.  This should be called only after
  513.  *    the query plan has been fully executed.
  514.  * ----------------------------------------------------------------  
  515.  */
  516. void
  517. ExecEndNode(node)
  518.     Plan node;
  519. {
  520.     HookNode         hook;
  521.     HookFunction     proc;
  522.  
  523.     /* ----------------
  524.      *    do nothing when we get to the end
  525.      *  of a leaf on tree.
  526.      * ----------------
  527.      */
  528.     if (node == NULL) 
  529.     return;
  530.  
  531.     switch(NodeType(node)) {
  532.     /* ----------------
  533.      *  control nodes
  534.      * ----------------
  535.      */
  536.     case classTag(Result):
  537.     END_WITH_HOOKS(Result,resstate);
  538.     break;
  539.     
  540.     case classTag(Append):
  541.     END_WITH_HOOKS(Append,unionstate);
  542.     break;
  543.     
  544.     /* ----------------
  545.      *    scan nodes
  546.      * ----------------
  547.      */
  548.     case classTag(SeqScan):
  549.     END_WITH_HOOKS(SeqScan,scanstate);
  550.     break;
  551.     
  552.     case classTag(IndexScan):
  553.     END_WITH_HOOKS(IndexScan,indxstate);
  554.     break;
  555.     
  556.     /* ----------------
  557.      *    join nodes
  558.      * ----------------
  559.      */
  560.     case classTag(NestLoop):
  561.     END_WITH_HOOKS(NestLoop,nlstate);
  562.     break;
  563.     
  564.     case classTag(MergeJoin):
  565.     END_WITH_HOOKS(MergeJoin,mergestate);
  566.     break;
  567.     
  568.     /* ----------------
  569.      *    materialization nodes
  570.      * ----------------
  571.      */
  572.     case classTag(Material):
  573.     END_WITH_HOOKS(Material,matstate);
  574.     break;
  575.     
  576.     case classTag(Sort):
  577.     END_WITH_HOOKS(Sort,sortstate);
  578.     break;
  579.     
  580.     case classTag(Unique):
  581.     END_WITH_HOOKS(Unique,uniquestate);
  582.     break;
  583.  
  584.     case classTag(Agg):
  585.     END_WITH_HOOKS(Agg, aggstate);
  586.     break;
  587.  
  588.  
  589.     /* ----------------
  590.      *    XXX add hooks to these
  591.      * ----------------
  592.      */
  593.     case classTag(Hash):
  594.     ExecEndHash((Hash) node);
  595.     break;
  596.     
  597.     case classTag(HashJoin):
  598.     ExecEndHashJoin((HashJoin) node);
  599.     break;
  600.     
  601.     case classTag(ScanTemps):
  602.     ExecEndScanTemps((ScanTemps) node);
  603.     break;
  604.  
  605.     default:
  606.     elog(DEBUG, "ExecEndNode: node not yet supported",
  607.          NodeGetTag(node));
  608.     break;
  609.     }
  610. }
  611.