nbtree: fix read page recheck typo.
[pgsql.git] / src / backend / executor / nodeBitmapOr.c
blob7029536c64382b7c78b86063369cfdce326ceaf5
1 /*-------------------------------------------------------------------------
3 * nodeBitmapOr.c
4 * routines to handle BitmapOr nodes.
6 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * IDENTIFICATION
11 * src/backend/executor/nodeBitmapOr.c
13 *-------------------------------------------------------------------------
15 /* INTERFACE ROUTINES
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
21 * NOTES
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
26 * execution.
29 #include "postgres.h"
31 #include "executor/executor.h"
32 #include "executor/nodeBitmapOr.h"
33 #include "miscadmin.h"
36 /* ----------------------------------------------------------------
37 * ExecBitmapOr
39 * stub for pro forma compliance
40 * ----------------------------------------------------------------
42 static TupleTableSlot *
43 ExecBitmapOr(PlanState *pstate)
45 elog(ERROR, "BitmapOr node does not support ExecProcNode call convention");
46 return NULL;
49 /* ----------------------------------------------------------------
50 * ExecInitBitmapOr
52 * Begin all of the subscans of the BitmapOr node.
53 * ----------------------------------------------------------------
55 BitmapOrState *
56 ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
58 BitmapOrState *bitmaporstate = makeNode(BitmapOrState);
59 PlanState **bitmapplanstates;
60 int nplans;
61 int i;
62 ListCell *l;
63 Plan *initNode;
65 /* check for unsupported flags */
66 Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
69 * Set up empty vector of subplan states
71 nplans = list_length(node->bitmapplans);
73 bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
76 * create new BitmapOrState for our BitmapOr node
78 bitmaporstate->ps.plan = (Plan *) node;
79 bitmaporstate->ps.state = estate;
80 bitmaporstate->ps.ExecProcNode = ExecBitmapOr;
81 bitmaporstate->bitmapplans = bitmapplanstates;
82 bitmaporstate->nplans = nplans;
85 * call ExecInitNode on each of the plans to be executed and save the
86 * results into the array "bitmapplanstates".
88 i = 0;
89 foreach(l, node->bitmapplans)
91 initNode = (Plan *) lfirst(l);
92 bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
93 i++;
97 * Miscellaneous initialization
99 * BitmapOr plans don't have expression contexts because they never call
100 * ExecQual or ExecProject. They don't need any tuple slots either.
103 return bitmaporstate;
106 /* ----------------------------------------------------------------
107 * MultiExecBitmapOr
108 * ----------------------------------------------------------------
110 Node *
111 MultiExecBitmapOr(BitmapOrState *node)
113 PlanState **bitmapplans;
114 int nplans;
115 int i;
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,
147 ((BitmapOr *) node->ps.plan)->isshared ?
148 node->ps.state->es_query_dsa : NULL);
151 ((BitmapIndexScanState *) subnode)->biss_result = result;
153 subresult = (TIDBitmap *) MultiExecProcNode(subnode);
155 if (subresult != result)
156 elog(ERROR, "unrecognized result from subplan");
158 else
160 /* standard implementation */
161 subresult = (TIDBitmap *) MultiExecProcNode(subnode);
163 if (!subresult || !IsA(subresult, TIDBitmap))
164 elog(ERROR, "unrecognized result from subplan");
166 if (result == NULL)
167 result = subresult; /* first subplan */
168 else
170 tbm_union(result, subresult);
171 tbm_free(subresult);
176 /* We could return an empty result set here? */
177 if (result == NULL)
178 elog(ERROR, "BitmapOr doesn't support zero inputs");
180 /* must provide our own instrumentation support */
181 if (node->ps.instrument)
182 InstrStopNode(node->ps.instrument, 0 /* XXX */ );
184 return (Node *) result;
187 /* ----------------------------------------------------------------
188 * ExecEndBitmapOr
190 * Shuts down the subscans of the BitmapOr node.
192 * Returns nothing of interest.
193 * ----------------------------------------------------------------
195 void
196 ExecEndBitmapOr(BitmapOrState *node)
198 PlanState **bitmapplans;
199 int nplans;
200 int i;
203 * get information from the node
205 bitmapplans = node->bitmapplans;
206 nplans = node->nplans;
209 * shut down each of the subscans (that we've initialized)
211 for (i = 0; i < nplans; i++)
213 if (bitmapplans[i])
214 ExecEndNode(bitmapplans[i]);
218 void
219 ExecReScanBitmapOr(BitmapOrState *node)
221 int i;
223 for (i = 0; i < node->nplans; i++)
225 PlanState *subnode = node->bitmapplans[i];
228 * ExecReScan doesn't know about my subplans, so I have to do
229 * changed-parameter signaling myself.
231 if (node->ps.chgParam != NULL)
232 UpdateChangedParamSet(subnode, node->ps.chgParam);
235 * If chgParam of subnode is not null then plan will be re-scanned by
236 * first ExecProcNode.
238 if (subnode->chgParam == NULL)
239 ExecReScan(subnode);