Header And Logo

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

Functions

nodeSetOp.h File Reference

#include "nodes/execnodes.h"
Include dependency graph for nodeSetOp.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

SetOpStateExecInitSetOp (SetOp *node, EState *estate, int eflags)
TupleTableSlotExecSetOp (SetOpState *node)
void ExecEndSetOp (SetOpState *node)
void ExecReScanSetOp (SetOpState *node)

Function Documentation

void ExecEndSetOp ( SetOpState node  ) 

Definition at line 586 of file nodeSetOp.c.

References ExecClearTuple(), ExecEndNode(), MemoryContextDelete(), outerPlanState, SetOpState::ps, PlanState::ps_ResultTupleSlot, SetOpState::tableContext, and SetOpState::tempContext.

Referenced by ExecEndNode().

{
    /* clean up tuple table */
    ExecClearTuple(node->ps.ps_ResultTupleSlot);

    /* free subsidiary stuff including hashtable */
    MemoryContextDelete(node->tempContext);
    if (node->tableContext)
        MemoryContextDelete(node->tableContext);

    ExecEndNode(outerPlanState(node));
}

SetOpState* ExecInitSetOp ( SetOp node,
EState estate,
int  eflags 
)

Definition at line 477 of file nodeSetOp.c.

References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), Assert, build_hash_table(), CurrentMemoryContext, SetOp::dupOperators, SetOpState::eqfunctions, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecAssignResultTypeFromTL(), ExecInitNode(), ExecInitResultTupleSlot(), execTuplesHashPrepare(), execTuplesMatchPrepare(), SetOpState::grp_firstTuple, SetOpState::hashfunctions, SetOpState::hashtable, makeNode, SetOp::numCols, SetOpState::numOutput, outerPlan, outerPlanState, palloc0(), SetOpState::pergroup, PlanState::plan, SetOpState::ps, PlanState::ps_ProjInfo, SetOpState::setop_done, SETOP_HASHED, PlanState::state, SetOp::strategy, SetOpState::table_filled, SetOpState::tableContext, and SetOpState::tempContext.

Referenced by ExecInitNode().

{
    SetOpState *setopstate;

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

    /*
     * create state structure
     */
    setopstate = makeNode(SetOpState);
    setopstate->ps.plan = (Plan *) node;
    setopstate->ps.state = estate;

    setopstate->eqfunctions = NULL;
    setopstate->hashfunctions = NULL;
    setopstate->setop_done = false;
    setopstate->numOutput = 0;
    setopstate->pergroup = NULL;
    setopstate->grp_firstTuple = NULL;
    setopstate->hashtable = NULL;
    setopstate->tableContext = NULL;

    /*
     * Miscellaneous initialization
     *
     * SetOp nodes have no ExprContext initialization because they never call
     * ExecQual or ExecProject.  But they do need a per-tuple memory context
     * anyway for calling execTuplesMatch.
     */
    setopstate->tempContext =
        AllocSetContextCreate(CurrentMemoryContext,
                              "SetOp",
                              ALLOCSET_DEFAULT_MINSIZE,
                              ALLOCSET_DEFAULT_INITSIZE,
                              ALLOCSET_DEFAULT_MAXSIZE);

    /*
     * If hashing, we also need a longer-lived context to store the hash
     * table.  The table can't just be kept in the per-query context because
     * we want to be able to throw it away in ExecReScanSetOp.
     */
    if (node->strategy == SETOP_HASHED)
        setopstate->tableContext =
            AllocSetContextCreate(CurrentMemoryContext,
                                  "SetOp hash table",
                                  ALLOCSET_DEFAULT_MINSIZE,
                                  ALLOCSET_DEFAULT_INITSIZE,
                                  ALLOCSET_DEFAULT_MAXSIZE);

    /*
     * Tuple table initialization
     */
    ExecInitResultTupleSlot(estate, &setopstate->ps);

    /*
     * initialize child nodes
     *
     * If we are hashing then the child plan does not need to handle REWIND
     * efficiently; see ExecReScanSetOp.
     */
    if (node->strategy == SETOP_HASHED)
        eflags &= ~EXEC_FLAG_REWIND;
    outerPlanState(setopstate) = ExecInitNode(outerPlan(node), estate, eflags);

    /*
     * setop nodes do no projections, so initialize projection info for this
     * node appropriately
     */
    ExecAssignResultTypeFromTL(&setopstate->ps);
    setopstate->ps.ps_ProjInfo = NULL;

    /*
     * Precompute fmgr lookup data for inner loop. We need both equality and
     * hashing functions to do it by hashing, but only equality if not
     * hashing.
     */
    if (node->strategy == SETOP_HASHED)
        execTuplesHashPrepare(node->numCols,
                              node->dupOperators,
                              &setopstate->eqfunctions,
                              &setopstate->hashfunctions);
    else
        setopstate->eqfunctions =
            execTuplesMatchPrepare(node->numCols,
                                   node->dupOperators);

    if (node->strategy == SETOP_HASHED)
    {
        build_hash_table(setopstate);
        setopstate->table_filled = false;
    }
    else
    {
        setopstate->pergroup =
            (SetOpStatePerGroup) palloc0(sizeof(SetOpStatePerGroupData));
    }

    return setopstate;
}

void ExecReScanSetOp ( SetOpState node  ) 

Definition at line 601 of file nodeSetOp.c.

References build_hash_table(), PlanState::chgParam, ExecClearTuple(), ExecReScan(), SetOpState::grp_firstTuple, SetOpState::hashiter, SetOpState::hashtable, heap_freetuple(), PlanState::lefttree, MemoryContextResetAndDeleteChildren(), NULL, SetOpState::numOutput, PlanState::plan, SetOpState::ps, PlanState::ps_ResultTupleSlot, ResetTupleHashIterator, SetOpState::setop_done, SETOP_HASHED, SetOpState::table_filled, and SetOpState::tableContext.

Referenced by ExecReScan().

{
    ExecClearTuple(node->ps.ps_ResultTupleSlot);
    node->setop_done = false;
    node->numOutput = 0;

    if (((SetOp *) node->ps.plan)->strategy == SETOP_HASHED)
    {
        /*
         * In the hashed case, if we haven't yet built the hash table then we
         * can just return; nothing done yet, so nothing to undo. If subnode's
         * chgParam is not NULL then it will be re-scanned by ExecProcNode,
         * else no reason to re-scan it at all.
         */
        if (!node->table_filled)
            return;

        /*
         * If we do have the hash table and the subplan does not have any
         * parameter changes, then we can just rescan the existing hash table;
         * no need to build it again.
         */
        if (node->ps.lefttree->chgParam == NULL)
        {
            ResetTupleHashIterator(node->hashtable, &node->hashiter);
            return;
        }
    }

    /* Release first tuple of group, if we have made a copy */
    if (node->grp_firstTuple != NULL)
    {
        heap_freetuple(node->grp_firstTuple);
        node->grp_firstTuple = NULL;
    }

    /* Release any hashtable storage */
    if (node->tableContext)
        MemoryContextResetAndDeleteChildren(node->tableContext);

    /* And rebuild empty hashtable if needed */
    if (((SetOp *) node->ps.plan)->strategy == SETOP_HASHED)
    {
        build_hash_table(node);
        node->table_filled = false;
    }

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

TupleTableSlot* ExecSetOp ( SetOpState node  ) 

Definition at line 195 of file nodeSetOp.c.

References SetOpState::numOutput, PlanState::plan, SetOpState::ps, PlanState::ps_ResultTupleSlot, SetOpState::setop_done, setop_fill_hash_table(), SETOP_HASHED, setop_retrieve_direct(), setop_retrieve_hash_table(), SetOp::strategy, and SetOpState::table_filled.

Referenced by ExecProcNode().

{
    SetOp      *plannode = (SetOp *) node->ps.plan;
    TupleTableSlot *resultTupleSlot = node->ps.ps_ResultTupleSlot;

    /*
     * If the previously-returned tuple needs to be returned more than once,
     * keep returning it.
     */
    if (node->numOutput > 0)
    {
        node->numOutput--;
        return resultTupleSlot;
    }

    /* Otherwise, we're done if we are out of groups */
    if (node->setop_done)
        return NULL;

    /* Fetch the next tuple group according to the correct strategy */
    if (plannode->strategy == SETOP_HASHED)
    {
        if (!node->table_filled)
            setop_fill_hash_table(node);
        return setop_retrieve_hash_table(node);
    }
    else
        return setop_retrieve_direct(node);
}