Skip to content
Snippets Groups Projects
Select Git revision
  • benchmark-tools
  • postgres-lambda
  • master default
  • REL9_4_25
  • REL9_5_20
  • REL9_6_16
  • REL_10_11
  • REL_11_6
  • REL_12_1
  • REL_12_0
  • REL_12_RC1
  • REL_12_BETA4
  • REL9_4_24
  • REL9_5_19
  • REL9_6_15
  • REL_10_10
  • REL_11_5
  • REL_12_BETA3
  • REL9_4_23
  • REL9_5_18
  • REL9_6_14
  • REL_10_9
  • REL_11_4
23 results

nodeBitmapOr.c

Blame
  • nodeBitmapOr.c 5.52 KiB
    /*-------------------------------------------------------------------------
     *
     * 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.11 2009/09/27 21:10:53 tgl 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.
    	 */
    
    	/*
    	 * 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;
    }
    
    /* ----------------------------------------------------------------
     *	   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);
    	}
    }