Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * nodeBitmapOr.c
4 : : * routines to handle BitmapOr nodes.
5 : : *
6 : : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 : : * Portions Copyright (c) 1994, Regents of the University of California
8 : : *
9 : : *
10 : : * IDENTIFICATION
11 : : * src/backend/executor/nodeBitmapOr.c
12 : : *
13 : : *-------------------------------------------------------------------------
14 : : */
15 : : /*
16 : : * INTERFACE ROUTINES
17 : : * ExecInitBitmapOr - initialize the BitmapOr node
18 : : * MultiExecBitmapOr - retrieve the result bitmap from the node
19 : : * ExecEndBitmapOr - shut down the BitmapOr node
20 : : * ExecReScanBitmapOr - rescan the BitmapOr node
21 : : *
22 : : * NOTES
23 : : * BitmapOr nodes don't make use of their left and right
24 : : * subtrees, rather they maintain a list of subplans,
25 : : * much like Append nodes. The logic is much simpler than
26 : : * Append, however, since we needn't cope with forward/backward
27 : : * execution.
28 : : */
29 : :
30 : : #include "postgres.h"
31 : :
32 : : #include "executor/executor.h"
33 : : #include "executor/instrument.h"
34 : : #include "executor/nodeBitmapOr.h"
35 : : #include "nodes/tidbitmap.h"
36 : : #include "miscadmin.h"
37 : :
38 : :
39 : : /* ----------------------------------------------------------------
40 : : * ExecBitmapOr
41 : : *
42 : : * stub for pro forma compliance
43 : : * ----------------------------------------------------------------
44 : : */
45 : : static TupleTableSlot *
3239 andres@anarazel.de 46 :UBC 0 : ExecBitmapOr(PlanState *pstate)
47 : : {
48 [ # # ]: 0 : elog(ERROR, "BitmapOr node does not support ExecProcNode call convention");
49 : : return NULL;
50 : : }
51 : :
52 : : /* ----------------------------------------------------------------
53 : : * ExecInitBitmapOr
54 : : *
55 : : * Begin all of the subscans of the BitmapOr node.
56 : : * ----------------------------------------------------------------
57 : : */
58 : : BitmapOrState *
7396 tgl@sss.pgh.pa.us 59 :CBC 254 : ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
60 : : {
7711 61 : 254 : BitmapOrState *bitmaporstate = makeNode(BitmapOrState);
62 : : PlanState **bitmapplanstates;
63 : : int nplans;
64 : : int i;
65 : : ListCell *l;
66 : : Plan *initNode;
67 : :
68 : : /* check for unsupported flags */
7396 69 [ - + ]: 254 : Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
70 : :
71 : : /*
72 : : * Set up empty vector of subplan states
73 : : */
7711 74 : 254 : nplans = list_length(node->bitmapplans);
75 : :
76 : 254 : bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
77 : :
78 : : /*
79 : : * create new BitmapOrState for our BitmapOr node
80 : : */
81 : 254 : bitmaporstate->ps.plan = (Plan *) node;
82 : 254 : bitmaporstate->ps.state = estate;
3239 andres@anarazel.de 83 : 254 : bitmaporstate->ps.ExecProcNode = ExecBitmapOr;
7711 tgl@sss.pgh.pa.us 84 : 254 : bitmaporstate->bitmapplans = bitmapplanstates;
85 : 254 : bitmaporstate->nplans = nplans;
86 : :
87 : : /*
88 : : * call ExecInitNode on each of the plans to be executed and save the
89 : : * results into the array "bitmapplanstates".
90 : : */
7710 91 : 254 : i = 0;
92 [ + - + + : 766 : foreach(l, node->bitmapplans)
+ + ]
93 : : {
94 : 512 : initNode = (Plan *) lfirst(l);
7396 95 : 512 : bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
7710 96 : 512 : i++;
97 : : }
98 : :
99 : : /*
100 : : * Miscellaneous initialization
101 : : *
102 : : * BitmapOr plans don't have expression contexts because they never call
103 : : * ExecQual or ExecProject. They don't need any tuple slots either.
104 : : */
105 : :
7711 106 : 254 : return bitmaporstate;
107 : : }
108 : :
109 : : /* ----------------------------------------------------------------
110 : : * MultiExecBitmapOr
111 : : * ----------------------------------------------------------------
112 : : */
113 : : Node *
114 : 177 : MultiExecBitmapOr(BitmapOrState *node)
115 : : {
116 : : PlanState **bitmapplans;
117 : : int nplans;
118 : : int i;
119 : 177 : TIDBitmap *result = NULL;
120 : :
121 : : /* must provide our own instrumentation support */
122 [ + + ]: 177 : if (node->ps.instrument)
123 : 4 : InstrStartNode(node->ps.instrument);
124 : :
125 : : /*
126 : : * get information from the node
127 : : */
128 : 177 : bitmapplans = node->bitmapplans;
129 : 177 : nplans = node->nplans;
130 : :
131 : : /*
132 : : * Scan all the subplans and OR their result bitmaps
133 : : */
134 [ + + ]: 531 : for (i = 0; i < nplans; i++)
135 : : {
136 : 354 : PlanState *subnode = bitmapplans[i];
137 : : TIDBitmap *subresult;
138 : :
139 : : /*
140 : : * We can special-case BitmapIndexScan children to avoid an explicit
141 : : * tbm_union step for each child: just pass down the current result
142 : : * bitmap and let the child OR directly into it.
143 : : */
7710 144 [ + + ]: 354 : if (IsA(subnode, BitmapIndexScanState))
145 : : {
7532 bruce@momjian.us 146 [ + + ]: 350 : if (result == NULL) /* first subplan */
147 : : {
148 : : /* XXX should we use less than work_mem for this? */
484 tgl@sss.pgh.pa.us 149 : 173 : result = tbm_create(work_mem * (Size) 1024,
3370 rhaas@postgresql.org 150 [ - + ]: 173 : ((BitmapOr *) node->ps.plan)->isshared ?
3370 rhaas@postgresql.org 151 :UBC 0 : node->ps.state->es_query_dsa : NULL);
152 : : }
153 : :
7710 tgl@sss.pgh.pa.us 154 :CBC 350 : ((BitmapIndexScanState *) subnode)->biss_result = result;
155 : :
156 : 350 : subresult = (TIDBitmap *) MultiExecProcNode(subnode);
157 : :
158 [ - + ]: 350 : if (subresult != result)
7710 tgl@sss.pgh.pa.us 159 [ # # ]:UBC 0 : elog(ERROR, "unrecognized result from subplan");
160 : : }
161 : : else
162 : : {
163 : : /* standard implementation */
7710 tgl@sss.pgh.pa.us 164 :CBC 4 : subresult = (TIDBitmap *) MultiExecProcNode(subnode);
165 : :
166 [ + - - + ]: 4 : if (!subresult || !IsA(subresult, TIDBitmap))
7710 tgl@sss.pgh.pa.us 167 [ # # ]:UBC 0 : elog(ERROR, "unrecognized result from subplan");
168 : :
7710 tgl@sss.pgh.pa.us 169 [ + - ]:CBC 4 : if (result == NULL)
3265 170 : 4 : result = subresult; /* first subplan */
171 : : else
172 : : {
7710 tgl@sss.pgh.pa.us 173 :UBC 0 : tbm_union(result, subresult);
174 : 0 : tbm_free(subresult);
175 : : }
176 : : }
177 : : }
178 : :
179 : : /* We could return an empty result set here? */
7711 tgl@sss.pgh.pa.us 180 [ - + ]:CBC 177 : if (result == NULL)
7711 tgl@sss.pgh.pa.us 181 [ # # ]:UBC 0 : elog(ERROR, "BitmapOr doesn't support zero inputs");
182 : :
183 : : /* must provide our own instrumentation support */
7711 tgl@sss.pgh.pa.us 184 [ + + ]:CBC 177 : if (node->ps.instrument)
7305 bruce@momjian.us 185 : 4 : InstrStopNode(node->ps.instrument, 0 /* XXX */ );
186 : :
7711 tgl@sss.pgh.pa.us 187 : 177 : return (Node *) result;
188 : : }
189 : :
190 : : /* ----------------------------------------------------------------
191 : : * ExecEndBitmapOr
192 : : *
193 : : * Shuts down the subscans of the BitmapOr node.
194 : : *
195 : : * Returns nothing of interest.
196 : : * ----------------------------------------------------------------
197 : : */
198 : : void
199 : 254 : ExecEndBitmapOr(BitmapOrState *node)
200 : : {
201 : : PlanState **bitmapplans;
202 : : int nplans;
203 : : int i;
204 : :
205 : : /*
206 : : * get information from the node
207 : : */
208 : 254 : bitmapplans = node->bitmapplans;
209 : 254 : nplans = node->nplans;
210 : :
211 : : /*
212 : : * shut down each of the subscans (that we've initialized)
213 : : */
214 [ + + ]: 766 : for (i = 0; i < nplans; i++)
215 : : {
216 [ + - ]: 512 : if (bitmapplans[i])
217 : 512 : ExecEndNode(bitmapplans[i]);
218 : : }
219 : 254 : }
220 : :
221 : : void
5801 222 : 25 : ExecReScanBitmapOr(BitmapOrState *node)
223 : : {
224 : : int i;
225 : :
7711 226 [ + + ]: 75 : for (i = 0; i < node->nplans; i++)
227 : : {
228 : 50 : PlanState *subnode = node->bitmapplans[i];
229 : :
230 : : /*
231 : : * ExecReScan doesn't know about my subplans, so I have to do
232 : : * changed-parameter signaling myself.
233 : : */
234 [ + + ]: 50 : if (node->ps.chgParam != NULL)
235 : 8 : UpdateChangedParamSet(subnode, node->ps.chgParam);
236 : :
237 : : /*
238 : : * If chgParam of subnode is not null then plan will be re-scanned by
239 : : * first ExecProcNode.
240 : : */
5801 241 [ + + ]: 50 : if (subnode->chgParam == NULL)
242 : 46 : ExecReScan(subnode);
243 : : }
7711 244 : 25 : }
|