1 /*-------------------------------------------------------------------------
4 * routines to handle BitmapOr nodes.
6 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapOr.c,v 1.10 2009/01/01 17:23:41 momjian Exp $
13 *-------------------------------------------------------------------------
16 * ExecInitBitmapOr - initialize the BitmapOr node
17 * MultiExecBitmapOr - retrieve the result bitmap from the node
18 * ExecEndBitmapOr - shut down the BitmapOr node
19 * ExecReScanBitmapOr - rescan the BitmapOr node
22 * BitmapOr nodes don't make use of their left and right
23 * subtrees, rather they maintain a list of subplans,
24 * much like Append nodes. The logic is much simpler than
25 * Append, however, since we needn't cope with forward/backward
31 #include "executor/execdebug.h"
32 #include "executor/instrument.h"
33 #include "executor/nodeBitmapOr.h"
34 #include "miscadmin.h"
37 /* ----------------------------------------------------------------
40 * Begin all of the subscans of the BitmapOr node.
41 * ----------------------------------------------------------------
44 ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
46 BitmapOrState *bitmaporstate = makeNode(BitmapOrState);
47 PlanState **bitmapplanstates;
53 /* check for unsupported flags */
54 Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
57 * Set up empty vector of subplan states
59 nplans = list_length(node->bitmapplans);
61 bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
64 * create new BitmapOrState for our BitmapOr node
66 bitmaporstate->ps.plan = (Plan *) node;
67 bitmaporstate->ps.state = estate;
68 bitmaporstate->bitmapplans = bitmapplanstates;
69 bitmaporstate->nplans = nplans;
72 * Miscellaneous initialization
74 * BitmapOr plans don't have expression contexts because they never call
75 * ExecQual or ExecProject. They don't need any tuple slots either.
78 #define BITMAPOR_NSLOTS 0
81 * call ExecInitNode on each of the plans to be executed and save the
82 * results into the array "bitmapplanstates".
85 foreach(l, node->bitmapplans)
87 initNode = (Plan *) lfirst(l);
88 bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
96 ExecCountSlotsBitmapOr(BitmapOr *node)
101 foreach(plan, node->bitmapplans)
102 nSlots += ExecCountSlotsNode((Plan *) lfirst(plan));
103 return nSlots + BITMAPOR_NSLOTS;
106 /* ----------------------------------------------------------------
108 * ----------------------------------------------------------------
111 MultiExecBitmapOr(BitmapOrState *node)
113 PlanState **bitmapplans;
116 TIDBitmap *result = NULL;
118 /* must provide our own instrumentation support */
119 if (node->ps.instrument)
120 InstrStartNode(node->ps.instrument);
123 * get information from the node
125 bitmapplans = node->bitmapplans;
126 nplans = node->nplans;
129 * Scan all the subplans and OR their result bitmaps
131 for (i = 0; i < nplans; i++)
133 PlanState *subnode = bitmapplans[i];
134 TIDBitmap *subresult;
137 * We can special-case BitmapIndexScan children to avoid an explicit
138 * tbm_union step for each child: just pass down the current result
139 * bitmap and let the child OR directly into it.
141 if (IsA(subnode, BitmapIndexScanState))
143 if (result == NULL) /* first subplan */
145 /* XXX should we use less than work_mem for this? */
146 result = tbm_create(work_mem * 1024L);
149 ((BitmapIndexScanState *) subnode)->biss_result = result;
151 subresult = (TIDBitmap *) MultiExecProcNode(subnode);
153 if (subresult != result)
154 elog(ERROR, "unrecognized result from subplan");
158 /* standard implementation */
159 subresult = (TIDBitmap *) MultiExecProcNode(subnode);
161 if (!subresult || !IsA(subresult, TIDBitmap))
162 elog(ERROR, "unrecognized result from subplan");
165 result = subresult; /* first subplan */
168 tbm_union(result, subresult);
174 /* We could return an empty result set here? */
176 elog(ERROR, "BitmapOr doesn't support zero inputs");
178 /* must provide our own instrumentation support */
179 if (node->ps.instrument)
180 InstrStopNode(node->ps.instrument, 0 /* XXX */ );
182 return (Node *) result;
185 /* ----------------------------------------------------------------
188 * Shuts down the subscans of the BitmapOr node.
190 * Returns nothing of interest.
191 * ----------------------------------------------------------------
194 ExecEndBitmapOr(BitmapOrState *node)
196 PlanState **bitmapplans;
201 * get information from the node
203 bitmapplans = node->bitmapplans;
204 nplans = node->nplans;
207 * shut down each of the subscans (that we've initialized)
209 for (i = 0; i < nplans; i++)
212 ExecEndNode(bitmapplans[i]);
217 ExecReScanBitmapOr(BitmapOrState *node, ExprContext *exprCtxt)
221 for (i = 0; i < node->nplans; i++)
223 PlanState *subnode = node->bitmapplans[i];
226 * ExecReScan doesn't know about my subplans, so I have to do
227 * changed-parameter signaling myself.
229 if (node->ps.chgParam != NULL)
230 UpdateChangedParamSet(subnode, node->ps.chgParam);
233 * Always rescan the inputs immediately, to ensure we can pass down
234 * any outer tuple that might be used in index quals.
236 ExecReScan(subnode, exprCtxt);