1 /*-------------------------------------------------------------------------
4 * routines to handle BitmapOr nodes.
6 * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/executor/nodeBitmapOr.c
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/nodeBitmapOr.h"
33 #include "miscadmin.h"
36 /* ----------------------------------------------------------------
39 * Begin all of the subscans of the BitmapOr node.
40 * ----------------------------------------------------------------
43 ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
45 BitmapOrState *bitmaporstate = makeNode(BitmapOrState);
46 PlanState **bitmapplanstates;
52 /* check for unsupported flags */
53 Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
56 * Set up empty vector of subplan states
58 nplans = list_length(node->bitmapplans);
60 bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
63 * create new BitmapOrState for our BitmapOr node
65 bitmaporstate->ps.plan = (Plan *) node;
66 bitmaporstate->ps.state = estate;
67 bitmaporstate->bitmapplans = bitmapplanstates;
68 bitmaporstate->nplans = nplans;
71 * Miscellaneous initialization
73 * BitmapOr plans don't have expression contexts because they never call
74 * ExecQual or ExecProject. They don't need any tuple slots either.
78 * call ExecInitNode on each of the plans to be executed and save the
79 * results into the array "bitmapplanstates".
82 foreach(l, node->bitmapplans)
84 initNode = (Plan *) lfirst(l);
85 bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
92 /* ----------------------------------------------------------------
94 * ----------------------------------------------------------------
97 MultiExecBitmapOr(BitmapOrState *node)
99 PlanState **bitmapplans;
102 TIDBitmap *result = NULL;
104 /* must provide our own instrumentation support */
105 if (node->ps.instrument)
106 InstrStartNode(node->ps.instrument);
109 * get information from the node
111 bitmapplans = node->bitmapplans;
112 nplans = node->nplans;
115 * Scan all the subplans and OR their result bitmaps
117 for (i = 0; i < nplans; i++)
119 PlanState *subnode = bitmapplans[i];
120 TIDBitmap *subresult;
123 * We can special-case BitmapIndexScan children to avoid an explicit
124 * tbm_union step for each child: just pass down the current result
125 * bitmap and let the child OR directly into it.
127 if (IsA(subnode, BitmapIndexScanState))
129 if (result == NULL) /* first subplan */
131 /* XXX should we use less than work_mem for this? */
132 result = tbm_create(work_mem * 1024L,
133 ((BitmapOr *) node->ps.plan)->isshared ?
134 node->ps.state->es_query_dsa : NULL);
137 ((BitmapIndexScanState *) subnode)->biss_result = result;
139 subresult = (TIDBitmap *) MultiExecProcNode(subnode);
141 if (subresult != result)
142 elog(ERROR, "unrecognized result from subplan");
146 /* standard implementation */
147 subresult = (TIDBitmap *) MultiExecProcNode(subnode);
149 if (!subresult || !IsA(subresult, TIDBitmap))
150 elog(ERROR, "unrecognized result from subplan");
153 result = subresult; /* first subplan */
156 tbm_union(result, subresult);
162 /* We could return an empty result set here? */
164 elog(ERROR, "BitmapOr doesn't support zero inputs");
166 /* must provide our own instrumentation support */
167 if (node->ps.instrument)
168 InstrStopNode(node->ps.instrument, 0 /* XXX */ );
170 return (Node *) result;
173 /* ----------------------------------------------------------------
176 * Shuts down the subscans of the BitmapOr node.
178 * Returns nothing of interest.
179 * ----------------------------------------------------------------
182 ExecEndBitmapOr(BitmapOrState *node)
184 PlanState **bitmapplans;
189 * get information from the node
191 bitmapplans = node->bitmapplans;
192 nplans = node->nplans;
195 * shut down each of the subscans (that we've initialized)
197 for (i = 0; i < nplans; i++)
200 ExecEndNode(bitmapplans[i]);
205 ExecReScanBitmapOr(BitmapOrState *node)
209 for (i = 0; i < node->nplans; i++)
211 PlanState *subnode = node->bitmapplans[i];
214 * ExecReScan doesn't know about my subplans, so I have to do
215 * changed-parameter signaling myself.
217 if (node->ps.chgParam != NULL)
218 UpdateChangedParamSet(subnode, node->ps.chgParam);
221 * If chgParam of subnode is not null then plan will be re-scanned by
222 * first ExecProcNode.
224 if (subnode->chgParam == NULL)