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

nodeBitmapOr.c
/*-------------------------------------------------------------------------
 *
 * nodeBitmapOr.c
 *      routines to handle BitmapOr nodes.
 *
 * 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/nodeBitmapOr.c,v 1.10 2009/01/01 17:23:41 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */
/* INTERFACE ROUTINES
 *          ExecInitBitmapOr  - initialize the BitmapOr node
 *          MultiExecBitmapOr - retrieve the result bitmap from the node
 *          ExecEndBitmapOr         - shut down the BitmapOr node
 *          ExecReScanBitmapOr      - rescan the BitmapOr node
 *
 *     NOTES
 *          BitmapOr nodes don't make use of their left and right
 *          subtrees, rather they maintain a list of subplans,
 *          much like Append nodes.  The logic is much simpler than
 *          Append, however, since we needn't cope with forward/backward
 *          execution.
 */

#include "postgres.h"

#include "executor/execdebug.h"
#include "executor/instrument.h"
#include "executor/nodeBitmapOr.h"
#include "miscadmin.h"


/* ----------------------------------------------------------------
 *          ExecInitBitmapOr
 *
 *          Begin all of the subscans of the BitmapOr node.
 * ----------------------------------------------------------------
 */
BitmapOrState *
ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
{
      BitmapOrState *bitmaporstate = makeNode(BitmapOrState);
      PlanState **bitmapplanstates;
      int               nplans;
      int               i;
      ListCell   *l;
      Plan     *initNode;

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

      /*
       * Set up empty vector of subplan states
       */
      nplans = list_length(node->bitmapplans);

      bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));

      /*
       * create new BitmapOrState for our BitmapOr node
       */
      bitmaporstate->ps.plan = (Plan *) node;
      bitmaporstate->ps.state = estate;
      bitmaporstate->bitmapplans = bitmapplanstates;
      bitmaporstate->nplans = nplans;

      /*
       * Miscellaneous initialization
       *
       * BitmapOr plans don't have expression contexts because they never call
       * ExecQual or ExecProject.  They don't need any tuple slots either.
       */

#define BITMAPOR_NSLOTS 0

      /*
       * call ExecInitNode on each of the plans to be executed and save the
       * results into the array "bitmapplanstates".
       */
      i = 0;
      foreach(l, node->bitmapplans)
      {
            initNode = (Plan *) lfirst(l);
            bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
            i++;
      }

      return bitmaporstate;
}

int
ExecCountSlotsBitmapOr(BitmapOr *node)
{
      ListCell   *plan;
      int               nSlots = 0;

      foreach(plan, node->bitmapplans)
            nSlots += ExecCountSlotsNode((Plan *) lfirst(plan));
      return nSlots + BITMAPOR_NSLOTS;
}

/* ----------------------------------------------------------------
 *       MultiExecBitmapOr
 * ----------------------------------------------------------------
 */
Node *
MultiExecBitmapOr(BitmapOrState *node)
{
      PlanState **bitmapplans;
      int               nplans;
      int               i;
      TIDBitmap  *result = NULL;

      /* must provide our own instrumentation support */
      if (node->ps.instrument)
            InstrStartNode(node->ps.instrument);

      /*
       * get information from the node
       */
      bitmapplans = node->bitmapplans;
      nplans = node->nplans;

      /*
       * Scan all the subplans and OR their result bitmaps
       */
      for (i = 0; i < nplans; i++)
      {
            PlanState  *subnode = bitmapplans[i];
            TIDBitmap  *subresult;

            /*
             * We can special-case BitmapIndexScan children to avoid an explicit
             * tbm_union step for each child: just pass down the current result
             * bitmap and let the child OR directly into it.
             */
            if (IsA(subnode, BitmapIndexScanState))
            {
                  if (result == NULL) /* first subplan */
                  {
                        /* XXX should we use less than work_mem for this? */
                        result = tbm_create(work_mem * 1024L);
                  }

                  ((BitmapIndexScanState *) subnode)->biss_result = result;

                  subresult = (TIDBitmap *) MultiExecProcNode(subnode);

                  if (subresult != result)
                        elog(ERROR, "unrecognized result from subplan");
            }
            else
            {
                  /* standard implementation */
                  subresult = (TIDBitmap *) MultiExecProcNode(subnode);

                  if (!subresult || !IsA(subresult, TIDBitmap))
                        elog(ERROR, "unrecognized result from subplan");

                  if (result == NULL)
                        result = subresult;           /* first subplan */
                  else
                  {
                        tbm_union(result, subresult);
                        tbm_free(subresult);
                  }
            }
      }

      /* We could return an empty result set here? */
      if (result == NULL)
            elog(ERROR, "BitmapOr doesn't support zero inputs");

      /* must provide our own instrumentation support */
      if (node->ps.instrument)
            InstrStopNode(node->ps.instrument, 0 /* XXX */ );

      return (Node *) result;
}

/* ----------------------------------------------------------------
 *          ExecEndBitmapOr
 *
 *          Shuts down the subscans of the BitmapOr node.
 *
 *          Returns nothing of interest.
 * ----------------------------------------------------------------
 */
void
ExecEndBitmapOr(BitmapOrState *node)
{
      PlanState **bitmapplans;
      int               nplans;
      int               i;

      /*
       * get information from the node
       */
      bitmapplans = node->bitmapplans;
      nplans = node->nplans;

      /*
       * shut down each of the subscans (that we've initialized)
       */
      for (i = 0; i < nplans; i++)
      {
            if (bitmapplans[i])
                  ExecEndNode(bitmapplans[i]);
      }
}

void
ExecReScanBitmapOr(BitmapOrState *node, ExprContext *exprCtxt)
{
      int               i;

      for (i = 0; i < node->nplans; i++)
      {
            PlanState  *subnode = node->bitmapplans[i];

            /*
             * ExecReScan doesn't know about my subplans, so I have to do
             * changed-parameter signaling myself.
             */
            if (node->ps.chgParam != NULL)
                  UpdateChangedParamSet(subnode, node->ps.chgParam);

            /*
             * Always rescan the inputs immediately, to ensure we can pass down
             * any outer tuple that might be used in index quals.
             */
            ExecReScan(subnode, exprCtxt);
      }
}

Generated by  Doxygen 1.6.0   Back to index