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-2024, 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 : : /* 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
20 : : *
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.
27 : : */
28 : :
29 : : #include "postgres.h"
30 : :
31 : : #include "executor/executor.h"
32 : : #include "executor/nodeBitmapOr.h"
33 : : #include "miscadmin.h"
34 : :
35 : :
36 : : /* ----------------------------------------------------------------
37 : : * ExecBitmapOr
38 : : *
39 : : * stub for pro forma compliance
40 : : * ----------------------------------------------------------------
41 : : */
42 : : static TupleTableSlot *
2463 andres@anarazel.de 43 :UBC 0 : ExecBitmapOr(PlanState *pstate)
44 : : {
45 [ # # ]: 0 : elog(ERROR, "BitmapOr node does not support ExecProcNode call convention");
46 : : return NULL;
47 : : }
48 : :
49 : : /* ----------------------------------------------------------------
50 : : * ExecInitBitmapOr
51 : : *
52 : : * Begin all of the subscans of the BitmapOr node.
53 : : * ----------------------------------------------------------------
54 : : */
55 : : BitmapOrState *
6620 tgl@sss.pgh.pa.us 56 :CBC 141 : ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
57 : : {
6935 58 : 141 : BitmapOrState *bitmaporstate = makeNode(BitmapOrState);
59 : : PlanState **bitmapplanstates;
60 : : int nplans;
61 : : int i;
62 : : ListCell *l;
63 : : Plan *initNode;
64 : :
65 : : /* check for unsupported flags */
6620 66 [ - + ]: 141 : Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
67 : :
68 : : /*
69 : : * Set up empty vector of subplan states
70 : : */
6935 71 : 141 : nplans = list_length(node->bitmapplans);
72 : :
73 : 141 : bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
74 : :
75 : : /*
76 : : * create new BitmapOrState for our BitmapOr node
77 : : */
78 : 141 : bitmaporstate->ps.plan = (Plan *) node;
79 : 141 : bitmaporstate->ps.state = estate;
2463 andres@anarazel.de 80 : 141 : bitmaporstate->ps.ExecProcNode = ExecBitmapOr;
6935 tgl@sss.pgh.pa.us 81 : 141 : bitmaporstate->bitmapplans = bitmapplanstates;
82 : 141 : bitmaporstate->nplans = nplans;
83 : :
84 : : /*
85 : : * call ExecInitNode on each of the plans to be executed and save the
86 : : * results into the array "bitmapplanstates".
87 : : */
6934 88 : 141 : i = 0;
89 [ + - + + : 450 : foreach(l, node->bitmapplans)
+ + ]
90 : : {
91 : 309 : initNode = (Plan *) lfirst(l);
6620 92 : 309 : bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
6934 93 : 309 : i++;
94 : : }
95 : :
96 : : /*
97 : : * Miscellaneous initialization
98 : : *
99 : : * BitmapOr plans don't have expression contexts because they never call
100 : : * ExecQual or ExecProject. They don't need any tuple slots either.
101 : : */
102 : :
6935 103 : 141 : return bitmaporstate;
104 : : }
105 : :
106 : : /* ----------------------------------------------------------------
107 : : * MultiExecBitmapOr
108 : : * ----------------------------------------------------------------
109 : : */
110 : : Node *
111 : 112 : MultiExecBitmapOr(BitmapOrState *node)
112 : : {
113 : : PlanState **bitmapplans;
114 : : int nplans;
115 : : int i;
116 : 112 : TIDBitmap *result = NULL;
117 : :
118 : : /* must provide our own instrumentation support */
119 [ + + ]: 112 : if (node->ps.instrument)
120 : 21 : InstrStartNode(node->ps.instrument);
121 : :
122 : : /*
123 : : * get information from the node
124 : : */
125 : 112 : bitmapplans = node->bitmapplans;
126 : 112 : nplans = node->nplans;
127 : :
128 : : /*
129 : : * Scan all the subplans and OR their result bitmaps
130 : : */
131 [ + + ]: 357 : for (i = 0; i < nplans; i++)
132 : : {
133 : 245 : PlanState *subnode = bitmapplans[i];
134 : : TIDBitmap *subresult;
135 : :
136 : : /*
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.
140 : : */
6934 141 [ + - ]: 245 : if (IsA(subnode, BitmapIndexScanState))
142 : : {
6756 bruce@momjian.us 143 [ + + ]: 245 : if (result == NULL) /* first subplan */
144 : : {
145 : : /* XXX should we use less than work_mem for this? */
2594 rhaas@postgresql.org 146 :UBC 0 : result = tbm_create(work_mem * 1024L,
2594 rhaas@postgresql.org 147 [ - + ]:CBC 112 : ((BitmapOr *) node->ps.plan)->isshared ?
2594 rhaas@postgresql.org 148 :UBC 0 : node->ps.state->es_query_dsa : NULL);
149 : : }
150 : :
6934 tgl@sss.pgh.pa.us 151 :CBC 245 : ((BitmapIndexScanState *) subnode)->biss_result = result;
152 : :
153 : 245 : subresult = (TIDBitmap *) MultiExecProcNode(subnode);
154 : :
155 [ - + ]: 245 : if (subresult != result)
6934 tgl@sss.pgh.pa.us 156 [ # # ]:UBC 0 : elog(ERROR, "unrecognized result from subplan");
157 : : }
158 : : else
159 : : {
160 : : /* standard implementation */
161 : 0 : subresult = (TIDBitmap *) MultiExecProcNode(subnode);
162 : :
163 [ # # # # ]: 0 : if (!subresult || !IsA(subresult, TIDBitmap))
164 [ # # ]: 0 : elog(ERROR, "unrecognized result from subplan");
165 : :
166 [ # # ]: 0 : if (result == NULL)
2489 167 : 0 : result = subresult; /* first subplan */
168 : : else
169 : : {
6934 170 : 0 : tbm_union(result, subresult);
171 : 0 : tbm_free(subresult);
172 : : }
173 : : }
174 : : }
175 : :
176 : : /* We could return an empty result set here? */
6935 tgl@sss.pgh.pa.us 177 [ - + ]:CBC 112 : if (result == NULL)
6935 tgl@sss.pgh.pa.us 178 [ # # ]:UBC 0 : elog(ERROR, "BitmapOr doesn't support zero inputs");
179 : :
180 : : /* must provide our own instrumentation support */
6935 tgl@sss.pgh.pa.us 181 [ + + ]:CBC 112 : if (node->ps.instrument)
6529 bruce@momjian.us 182 : 21 : InstrStopNode(node->ps.instrument, 0 /* XXX */ );
183 : :
6935 tgl@sss.pgh.pa.us 184 : 112 : return (Node *) result;
185 : : }
186 : :
187 : : /* ----------------------------------------------------------------
188 : : * ExecEndBitmapOr
189 : : *
190 : : * Shuts down the subscans of the BitmapOr node.
191 : : *
192 : : * Returns nothing of interest.
193 : : * ----------------------------------------------------------------
194 : : */
195 : : void
196 : 141 : ExecEndBitmapOr(BitmapOrState *node)
197 : : {
198 : : PlanState **bitmapplans;
199 : : int nplans;
200 : : int i;
201 : :
202 : : /*
203 : : * get information from the node
204 : : */
205 : 141 : bitmapplans = node->bitmapplans;
206 : 141 : nplans = node->nplans;
207 : :
208 : : /*
209 : : * shut down each of the subscans (that we've initialized)
210 : : */
211 [ + + ]: 450 : for (i = 0; i < nplans; i++)
212 : : {
213 [ + - ]: 309 : if (bitmapplans[i])
214 : 309 : ExecEndNode(bitmapplans[i]);
215 : : }
216 : 141 : }
217 : :
218 : : void
5025 219 : 14 : ExecReScanBitmapOr(BitmapOrState *node)
220 : : {
221 : : int i;
222 : :
6935 223 [ + + ]: 42 : for (i = 0; i < node->nplans; i++)
224 : : {
225 : 28 : PlanState *subnode = node->bitmapplans[i];
226 : :
227 : : /*
228 : : * ExecReScan doesn't know about my subplans, so I have to do
229 : : * changed-parameter signaling myself.
230 : : */
231 [ + + ]: 28 : if (node->ps.chgParam != NULL)
232 : 6 : UpdateChangedParamSet(subnode, node->ps.chgParam);
233 : :
234 : : /*
235 : : * If chgParam of subnode is not null then plan will be re-scanned by
236 : : * first ExecProcNode.
237 : : */
5025 238 [ + + ]: 28 : if (subnode->chgParam == NULL)
239 : 25 : ExecReScan(subnode);
240 : : }
6935 241 : 14 : }
|