Logo Search packages:      
Sourcecode: postgresql-8.4 version File versions

nodeSubqueryscan.c

/*-------------------------------------------------------------------------
 *
 * nodeSubqueryscan.c
 *      Support routines for scanning subqueries (subselects in rangetable).
 *
 * This is just enough different from sublinks (nodeSubplan.c) to mean that
 * we need two sets of code.  Ought to look at trying to unify the cases.
 *
 *
 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *      $PostgreSQL: pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.40 2009/01/01 17:23:42 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */
/*
 * INTERFACE ROUTINES
 *          ExecSubqueryScan              scans a subquery.
 *          ExecSubqueryNext              retrieve next tuple in sequential order.
 *          ExecInitSubqueryScan          creates and initializes a subqueryscan node.
 *          ExecEndSubqueryScan                 releases any storage allocated.
 *          ExecSubqueryReScan                  rescans the relation
 *
 */
#include "postgres.h"

#include "executor/execdebug.h"
#include "executor/nodeSubqueryscan.h"

static TupleTableSlot *SubqueryNext(SubqueryScanState *node);

/* ----------------------------------------------------------------
 *                                  Scan Support
 * ----------------------------------------------------------------
 */
/* ----------------------------------------------------------------
 *          SubqueryNext
 *
 *          This is a workhorse for ExecSubqueryScan
 * ----------------------------------------------------------------
 */
static TupleTableSlot *
SubqueryNext(SubqueryScanState *node)
{
      TupleTableSlot *slot;

      /*
       * We need not support EvalPlanQual here, since we are not scanning a real
       * relation.
       */

      /*
       * Get the next tuple from the sub-query.
       */
      slot = ExecProcNode(node->subplan);

      /*
       * We just overwrite our ScanTupleSlot with the subplan's result slot,
       * rather than expending the cycles for ExecCopySlot().
       */
      node->ss.ss_ScanTupleSlot = slot;

      return slot;
}

/* ----------------------------------------------------------------
 *          ExecSubqueryScan(node)
 *
 *          Scans the subquery sequentially and returns the next qualifying
 *          tuple.
 *          It calls the ExecScan() routine and passes it the access method
 *          which retrieve tuples sequentially.
 *
 */

TupleTableSlot *
ExecSubqueryScan(SubqueryScanState *node)
{
      /*
       * use SubqueryNext as access method
       */
      return ExecScan(&node->ss, (ExecScanAccessMtd) SubqueryNext);
}

/* ----------------------------------------------------------------
 *          ExecInitSubqueryScan
 * ----------------------------------------------------------------
 */
SubqueryScanState *
ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
{
      SubqueryScanState *subquerystate;

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

      /*
       * SubqueryScan should not have any "normal" children.      Also, if planner
       * left anything in subrtable, it's fishy.
       */
      Assert(outerPlan(node) == NULL);
      Assert(innerPlan(node) == NULL);
      Assert(node->subrtable == NIL);

      /*
       * create state structure
       */
      subquerystate = makeNode(SubqueryScanState);
      subquerystate->ss.ps.plan = (Plan *) node;
      subquerystate->ss.ps.state = estate;

      /*
       * Miscellaneous initialization
       *
       * create expression context for node
       */
      ExecAssignExprContext(estate, &subquerystate->ss.ps);

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

#define SUBQUERYSCAN_NSLOTS 2

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

      /*
       * initialize subquery
       */
      subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);

      subquerystate->ss.ps.ps_TupFromTlist = false;

      /*
       * Initialize scan tuple type (needed by ExecAssignScanProjectionInfo)
       */
      ExecAssignScanType(&subquerystate->ss,
                                 ExecGetResultType(subquerystate->subplan));

      /*
       * Initialize result tuple type and projection info.
       */
      ExecAssignResultTypeFromTL(&subquerystate->ss.ps);
      ExecAssignScanProjectionInfo(&subquerystate->ss);

      return subquerystate;
}

int
ExecCountSlotsSubqueryScan(SubqueryScan *node)
{
      Assert(outerPlan(node) == NULL);
      Assert(innerPlan(node) == NULL);
      return ExecCountSlotsNode(node->subplan) +
            SUBQUERYSCAN_NSLOTS;
}

/* ----------------------------------------------------------------
 *          ExecEndSubqueryScan
 *
 *          frees any storage allocated through C routines.
 * ----------------------------------------------------------------
 */
void
ExecEndSubqueryScan(SubqueryScanState *node)
{
      /*
       * Free the exprcontext
       */
      ExecFreeExprContext(&node->ss.ps);

      /*
       * clean out the upper tuple table
       */
      ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
      node->ss.ss_ScanTupleSlot = NULL;   /* not ours to clear */

      /*
       * close down subquery
       */
      ExecEndNode(node->subplan);
}

/* ----------------------------------------------------------------
 *          ExecSubqueryReScan
 *
 *          Rescans the relation.
 * ----------------------------------------------------------------
 */
void
ExecSubqueryReScan(SubqueryScanState *node, ExprContext *exprCtxt)
{
      EState         *estate;

      estate = node->ss.ps.state;

      /*
       * ExecReScan doesn't know about my subplan, so I have to do
       * changed-parameter signaling myself.    This is just as well, because the
       * subplan has its own memory context in which its chgParam state lives.
       */
      if (node->ss.ps.chgParam != NULL)
            UpdateChangedParamSet(node->subplan, node->ss.ps.chgParam);

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

      node->ss.ss_ScanTupleSlot = NULL;
      node->ss.ps.ps_TupFromTlist = false;
}

Generated by  Doxygen 1.6.0   Back to index