/*------------------------------------------------------------------------- * * nodeBitmapOr.c * routines to handle BitmapOr 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/nodeBitmapOr.c,v 1.1 2005/04/19 22:35:12 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" /* ---------------------------------------------------------------- * ExecInitBitmapOr * * Begin all of the subscans of the BitmapOr node. * ---------------------------------------------------------------- */ BitmapOrState * ExecInitBitmapOr(BitmapOr *node, EState *estate) { BitmapOrState *bitmaporstate = makeNode(BitmapOrState); PlanState **bitmapplanstates; int nplans; int i; Plan *initNode; CXT1_printf("ExecInitBitmapOr: 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 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". */ for (i = 0; i < nplans; i++) { initNode = (Plan *) list_nth(node->bitmapplans, i); bitmapplanstates[i] = ExecInitNode(initNode, estate); } 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; 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) InstrStopNodeMulti(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); } }