Header And Logo

PostgreSQL
| The world's most advanced open source database.

Functions

nodeGroup.c File Reference

#include "postgres.h"
#include "executor/executor.h"
#include "executor/nodeGroup.h"
Include dependency graph for nodeGroup.c:

Go to the source code of this file.

Functions

TupleTableSlotExecGroup (GroupState *node)
GroupStateExecInitGroup (Group *node, EState *estate, int eflags)
void ExecEndGroup (GroupState *node)
void ExecReScanGroup (GroupState *node)

Function Documentation

void ExecEndGroup ( GroupState node  ) 

Definition at line 267 of file nodeGroup.c.

References ExecClearTuple(), ExecEndNode(), ExecFreeExprContext(), outerPlanState, ScanState::ps, GroupState::ss, and ScanState::ss_ScanTupleSlot.

Referenced by ExecEndNode().

{
    PlanState  *outerPlan;

    ExecFreeExprContext(&node->ss.ps);

    /* clean up tuple table */
    ExecClearTuple(node->ss.ss_ScanTupleSlot);

    outerPlan = outerPlanState(node);
    ExecEndNode(outerPlan);
}

TupleTableSlot* ExecGroup ( GroupState node  ) 

Definition at line 35 of file nodeGroup.c.

References ExprContext::ecxt_outertuple, ExprContext::ecxt_per_tuple_memory, GroupState::eqfunctions, ExecCopySlot(), ExecProcNode(), ExecProject(), ExecQual(), execTuplesMatch(), ExprEndResult, ExprMultipleResult, GroupState::grp_done, InstrCountFiltered1, outerPlanState, PlanState::plan, ScanState::ps, PlanState::ps_ExprContext, PlanState::ps_ProjInfo, PlanState::ps_TupFromTlist, PlanState::qual, GroupState::ss, ScanState::ss_ScanTupleSlot, and TupIsNull.

Referenced by ExecProcNode().

{
    ExprContext *econtext;
    int         numCols;
    AttrNumber *grpColIdx;
    TupleTableSlot *firsttupleslot;
    TupleTableSlot *outerslot;

    /*
     * get state info from node
     */
    if (node->grp_done)
        return NULL;
    econtext = node->ss.ps.ps_ExprContext;
    numCols = ((Group *) node->ss.ps.plan)->numCols;
    grpColIdx = ((Group *) node->ss.ps.plan)->grpColIdx;

    /*
     * Check to see if we're still projecting out tuples from a previous group
     * tuple (because there is a function-returning-set in the projection
     * expressions).  If so, try to project another one.
     */
    if (node->ss.ps.ps_TupFromTlist)
    {
        TupleTableSlot *result;
        ExprDoneCond isDone;

        result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
        if (isDone == ExprMultipleResult)
            return result;
        /* Done with that source tuple... */
        node->ss.ps.ps_TupFromTlist = false;
    }

    /*
     * The ScanTupleSlot holds the (copied) first tuple of each group.
     */
    firsttupleslot = node->ss.ss_ScanTupleSlot;

    /*
     * We need not call ResetExprContext here because execTuplesMatch will
     * reset the per-tuple memory context once per input tuple.
     */

    /*
     * If first time through, acquire first input tuple and determine whether
     * to return it or not.
     */
    if (TupIsNull(firsttupleslot))
    {
        outerslot = ExecProcNode(outerPlanState(node));
        if (TupIsNull(outerslot))
        {
            /* empty input, so return nothing */
            node->grp_done = TRUE;
            return NULL;
        }
        /* Copy tuple into firsttupleslot */
        ExecCopySlot(firsttupleslot, outerslot);

        /*
         * Set it up as input for qual test and projection.  The expressions
         * will access the input tuple as varno OUTER.
         */
        econtext->ecxt_outertuple = firsttupleslot;

        /*
         * Check the qual (HAVING clause); if the group does not match, ignore
         * it and fall into scan loop.
         */
        if (ExecQual(node->ss.ps.qual, econtext, false))
        {
            /*
             * Form and return a projection tuple using the first input tuple.
             */
            TupleTableSlot *result;
            ExprDoneCond isDone;

            result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);

            if (isDone != ExprEndResult)
            {
                node->ss.ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
                return result;
            }
        }
        else
            InstrCountFiltered1(node, 1);
    }

    /*
     * This loop iterates once per input tuple group.  At the head of the
     * loop, we have finished processing the first tuple of the group and now
     * need to scan over all the other group members.
     */
    for (;;)
    {
        /*
         * Scan over all remaining tuples that belong to this group
         */
        for (;;)
        {
            outerslot = ExecProcNode(outerPlanState(node));
            if (TupIsNull(outerslot))
            {
                /* no more groups, so we're done */
                node->grp_done = TRUE;
                return NULL;
            }

            /*
             * Compare with first tuple and see if this tuple is of the same
             * group.  If so, ignore it and keep scanning.
             */
            if (!execTuplesMatch(firsttupleslot, outerslot,
                                 numCols, grpColIdx,
                                 node->eqfunctions,
                                 econtext->ecxt_per_tuple_memory))
                break;
        }

        /*
         * We have the first tuple of the next input group.  See if we want to
         * return it.
         */
        /* Copy tuple, set up as input for qual test and projection */
        ExecCopySlot(firsttupleslot, outerslot);
        econtext->ecxt_outertuple = firsttupleslot;

        /*
         * Check the qual (HAVING clause); if the group does not match, ignore
         * it and loop back to scan the rest of the group.
         */
        if (ExecQual(node->ss.ps.qual, econtext, false))
        {
            /*
             * Form and return a projection tuple using the first input tuple.
             */
            TupleTableSlot *result;
            ExprDoneCond isDone;

            result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);

            if (isDone != ExprEndResult)
            {
                node->ss.ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
                return result;
            }
        }
        else
            InstrCountFiltered1(node, 1);
    }
}

GroupState* ExecInitGroup ( Group node,
EState estate,
int  eflags 
)

Definition at line 197 of file nodeGroup.c.

References Assert, GroupState::eqfunctions, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecAssignProjectionInfo(), ExecAssignResultTypeFromTL(), ExecAssignScanTypeFromOuterPlan(), ExecInitExpr(), ExecInitNode(), ExecInitResultTupleSlot(), ExecInitScanTupleSlot(), execTuplesMatchPrepare(), GroupState::grp_done, Group::grpOperators, makeNode, NULL, Group::numCols, outerPlan, outerPlanState, Group::plan, PlanState::plan, ScanState::ps, PlanState::ps_TupFromTlist, Plan::qual, PlanState::qual, GroupState::ss, PlanState::state, Plan::targetlist, and PlanState::targetlist.

Referenced by ExecInitNode().

{
    GroupState *grpstate;

    /* check for unsupported flags */
    Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));

    /*
     * create state structure
     */
    grpstate = makeNode(GroupState);
    grpstate->ss.ps.plan = (Plan *) node;
    grpstate->ss.ps.state = estate;
    grpstate->grp_done = FALSE;

    /*
     * create expression context
     */
    ExecAssignExprContext(estate, &grpstate->ss.ps);

    /*
     * tuple table initialization
     */
    ExecInitScanTupleSlot(estate, &grpstate->ss);
    ExecInitResultTupleSlot(estate, &grpstate->ss.ps);

    /*
     * initialize child expressions
     */
    grpstate->ss.ps.targetlist = (List *)
        ExecInitExpr((Expr *) node->plan.targetlist,
                     (PlanState *) grpstate);
    grpstate->ss.ps.qual = (List *)
        ExecInitExpr((Expr *) node->plan.qual,
                     (PlanState *) grpstate);

    /*
     * initialize child nodes
     */
    outerPlanState(grpstate) = ExecInitNode(outerPlan(node), estate, eflags);

    /*
     * initialize tuple type.
     */
    ExecAssignScanTypeFromOuterPlan(&grpstate->ss);

    /*
     * Initialize result tuple type and projection info.
     */
    ExecAssignResultTypeFromTL(&grpstate->ss.ps);
    ExecAssignProjectionInfo(&grpstate->ss.ps, NULL);

    grpstate->ss.ps.ps_TupFromTlist = false;

    /*
     * Precompute fmgr lookup data for inner loop
     */
    grpstate->eqfunctions =
        execTuplesMatchPrepare(node->numCols,
                               node->grpOperators);

    return grpstate;
}

void ExecReScanGroup ( GroupState node  ) 

Definition at line 281 of file nodeGroup.c.

References PlanState::chgParam, ExecClearTuple(), ExecReScan(), GroupState::grp_done, PlanState::lefttree, NULL, ScanState::ps, PlanState::ps_TupFromTlist, GroupState::ss, and ScanState::ss_ScanTupleSlot.

Referenced by ExecReScan().

{
    node->grp_done = FALSE;
    node->ss.ps.ps_TupFromTlist = false;
    /* must clear first tuple */
    ExecClearTuple(node->ss.ss_ScanTupleSlot);

    /*
     * if chgParam of subnode is not null then plan will be re-scanned by
     * first ExecProcNode.
     */
    if (node->ss.ps.lefttree &&
        node->ss.ps.lefttree->chgParam == NULL)
        ExecReScan(node->ss.ps.lefttree);
}