postgresql/src/backend/executor/nodeBitmapAnd.c

212 lines
5.0 KiB
C

/*-------------------------------------------------------------------------
*
* nodeBitmapAnd.c
* routines to handle BitmapAnd nodes.
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapAnd.c,v 1.2 2005/04/20 15:48:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* INTERFACE ROUTINES
* ExecInitBitmapAnd - initialize the BitmapAnd node
* MultiExecBitmapAnd - retrieve the result bitmap from the node
* ExecEndBitmapAnd - shut down the BitmapAnd node
* ExecReScanBitmapAnd - rescan the BitmapAnd node
*
* NOTES
* BitmapAnd 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/nodeBitmapAnd.h"
/* ----------------------------------------------------------------
* ExecInitBitmapAnd
*
* Begin all of the subscans of the BitmapAnd node.
* ----------------------------------------------------------------
*/
BitmapAndState *
ExecInitBitmapAnd(BitmapAnd *node, EState *estate)
{
BitmapAndState *bitmapandstate = makeNode(BitmapAndState);
PlanState **bitmapplanstates;
int nplans;
int i;
ListCell *l;
Plan *initNode;
CXT1_printf("ExecInitBitmapAnd: context is %d\n", CurrentMemoryContext);
/*
* Set up empty vector of subplan states
*/
nplans = list_length(node->bitmapplans);
bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
/*
* create new BitmapAndState for our BitmapAnd node
*/
bitmapandstate->ps.plan = (Plan *) node;
bitmapandstate->ps.state = estate;
bitmapandstate->bitmapplans = bitmapplanstates;
bitmapandstate->nplans = nplans;
/*
* Miscellaneous initialization
*
* BitmapAnd plans don't have expression contexts because they never call
* ExecQual or ExecProject. They don't need any tuple slots either.
*/
#define BITMAPAND_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);
i++;
}
return bitmapandstate;
}
int
ExecCountSlotsBitmapAnd(BitmapAnd *node)
{
ListCell *plan;
int nSlots = 0;
foreach(plan, node->bitmapplans)
nSlots += ExecCountSlotsNode((Plan *) lfirst(plan));
return nSlots + BITMAPAND_NSLOTS;
}
/* ----------------------------------------------------------------
* MultiExecBitmapAnd
* ----------------------------------------------------------------
*/
Node *
MultiExecBitmapAnd(BitmapAndState *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 AND their result bitmaps
*/
for (i = 0; i < nplans; i++)
{
PlanState *subnode = bitmapplans[i];
TIDBitmap *subresult;
subresult = (TIDBitmap *) MultiExecProcNode(subnode);
if (!subresult || !IsA(subresult, TIDBitmap))
elog(ERROR, "unrecognized result from subplan");
if (result == NULL)
result = subresult; /* first subplan */
else
{
tbm_intersect(result, subresult);
tbm_free(subresult);
}
}
if (result == NULL)
elog(ERROR, "BitmapAnd doesn't support zero inputs");
/* must provide our own instrumentation support */
if (node->ps.instrument)
InstrStopNodeMulti(node->ps.instrument, 0 /* XXX */);
return (Node *) result;
}
/* ----------------------------------------------------------------
* ExecEndBitmapAnd
*
* Shuts down the subscans of the BitmapAnd node.
*
* Returns nothing of interest.
* ----------------------------------------------------------------
*/
void
ExecEndBitmapAnd(BitmapAndState *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
ExecReScanBitmapAnd(BitmapAndState *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);
}
}