Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * nodeBitmapAnd.c
4 : : * routines to handle BitmapAnd 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/nodeBitmapAnd.c
12 : : *
13 : : *-------------------------------------------------------------------------
14 : : */
15 : : /*
16 : : * INTERFACE ROUTINES
17 : : * ExecInitBitmapAnd - initialize the BitmapAnd node
18 : : * MultiExecBitmapAnd - retrieve the result bitmap from the node
19 : : * ExecEndBitmapAnd - shut down the BitmapAnd node
20 : : * ExecReScanBitmapAnd - rescan the BitmapAnd node
21 : : *
22 : : * NOTES
23 : : * BitmapAnd 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/nodeBitmapAnd.h"
35 : : #include "nodes/tidbitmap.h"
36 : :
37 : :
38 : : /* ----------------------------------------------------------------
39 : : * ExecBitmapAnd
40 : : *
41 : : * stub for pro forma compliance
42 : : * ----------------------------------------------------------------
43 : : */
44 : : static TupleTableSlot *
3239 andres@anarazel.de 45 :UBC 0 : ExecBitmapAnd(PlanState *pstate)
46 : : {
47 [ # # ]: 0 : elog(ERROR, "BitmapAnd node does not support ExecProcNode call convention");
48 : : return NULL;
49 : : }
50 : :
51 : : /* ----------------------------------------------------------------
52 : : * ExecInitBitmapAnd
53 : : *
54 : : * Begin all of the subscans of the BitmapAnd node.
55 : : * ----------------------------------------------------------------
56 : : */
57 : : BitmapAndState *
7396 tgl@sss.pgh.pa.us 58 :CBC 146 : ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
59 : : {
7711 60 : 146 : BitmapAndState *bitmapandstate = makeNode(BitmapAndState);
61 : : PlanState **bitmapplanstates;
62 : : int nplans;
63 : : int i;
64 : : ListCell *l;
65 : : Plan *initNode;
66 : :
67 : : /* check for unsupported flags */
7396 68 [ - + ]: 146 : Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
69 : :
70 : : /*
71 : : * Set up empty vector of subplan states
72 : : */
7711 73 : 146 : nplans = list_length(node->bitmapplans);
74 : :
75 : 146 : bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
76 : :
77 : : /*
78 : : * create new BitmapAndState for our BitmapAnd node
79 : : */
80 : 146 : bitmapandstate->ps.plan = (Plan *) node;
81 : 146 : bitmapandstate->ps.state = estate;
3239 andres@anarazel.de 82 : 146 : bitmapandstate->ps.ExecProcNode = ExecBitmapAnd;
7711 tgl@sss.pgh.pa.us 83 : 146 : bitmapandstate->bitmapplans = bitmapplanstates;
84 : 146 : bitmapandstate->nplans = nplans;
85 : :
86 : : /*
87 : : * call ExecInitNode on each of the plans to be executed and save the
88 : : * results into the array "bitmapplanstates".
89 : : */
7710 90 : 146 : i = 0;
91 [ + - + + : 438 : foreach(l, node->bitmapplans)
+ + ]
92 : : {
93 : 292 : initNode = (Plan *) lfirst(l);
7396 94 : 292 : bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
7710 95 : 292 : i++;
96 : : }
97 : :
98 : : /*
99 : : * Miscellaneous initialization
100 : : *
101 : : * BitmapAnd plans don't have expression contexts because they never call
102 : : * ExecQual or ExecProject. They don't need any tuple slots either.
103 : : */
104 : :
7711 105 : 146 : return bitmapandstate;
106 : : }
107 : :
108 : : /* ----------------------------------------------------------------
109 : : * MultiExecBitmapAnd
110 : : * ----------------------------------------------------------------
111 : : */
112 : : Node *
113 : 114 : MultiExecBitmapAnd(BitmapAndState *node)
114 : : {
115 : : PlanState **bitmapplans;
116 : : int nplans;
117 : : int i;
118 : 114 : TIDBitmap *result = NULL;
119 : :
120 : : /* must provide our own instrumentation support */
121 [ - + ]: 114 : if (node->ps.instrument)
7711 tgl@sss.pgh.pa.us 122 :UBC 0 : InstrStartNode(node->ps.instrument);
123 : :
124 : : /*
125 : : * get information from the node
126 : : */
7711 tgl@sss.pgh.pa.us 127 :CBC 114 : bitmapplans = node->bitmapplans;
128 : 114 : nplans = node->nplans;
129 : :
130 : : /*
131 : : * Scan all the subplans and AND their result bitmaps
132 : : */
133 [ + + ]: 338 : for (i = 0; i < nplans; i++)
134 : : {
135 : 228 : PlanState *subnode = bitmapplans[i];
136 : : TIDBitmap *subresult;
137 : :
138 : 228 : subresult = (TIDBitmap *) MultiExecProcNode(subnode);
139 : :
140 [ + - - + ]: 228 : if (!subresult || !IsA(subresult, TIDBitmap))
7711 tgl@sss.pgh.pa.us 141 [ # # ]:UBC 0 : elog(ERROR, "unrecognized result from subplan");
142 : :
7711 tgl@sss.pgh.pa.us 143 [ + + ]:CBC 228 : if (result == NULL)
7532 bruce@momjian.us 144 : 114 : result = subresult; /* first subplan */
145 : : else
146 : : {
7711 tgl@sss.pgh.pa.us 147 : 114 : tbm_intersect(result, subresult);
148 : 114 : tbm_free(subresult);
149 : : }
150 : :
151 : : /*
152 : : * If at any stage we have a completely empty bitmap, we can fall out
153 : : * without evaluating the remaining subplans, since ANDing them can no
154 : : * longer change the result. (Note: the fact that indxpath.c orders
155 : : * the subplans by selectivity should make this case more likely to
156 : : * occur.)
157 : : */
7580 158 [ + + ]: 228 : if (tbm_is_empty(result))
159 : 4 : break;
160 : : }
161 : :
7711 162 [ - + ]: 114 : if (result == NULL)
7711 tgl@sss.pgh.pa.us 163 [ # # ]:UBC 0 : elog(ERROR, "BitmapAnd doesn't support zero inputs");
164 : :
165 : : /* must provide our own instrumentation support */
7711 tgl@sss.pgh.pa.us 166 [ - + ]:CBC 114 : if (node->ps.instrument)
7305 bruce@momjian.us 167 :UBC 0 : InstrStopNode(node->ps.instrument, 0 /* XXX */ );
168 : :
7711 tgl@sss.pgh.pa.us 169 :CBC 114 : return (Node *) result;
170 : : }
171 : :
172 : : /* ----------------------------------------------------------------
173 : : * ExecEndBitmapAnd
174 : : *
175 : : * Shuts down the subscans of the BitmapAnd node.
176 : : *
177 : : * Returns nothing of interest.
178 : : * ----------------------------------------------------------------
179 : : */
180 : : void
181 : 146 : ExecEndBitmapAnd(BitmapAndState *node)
182 : : {
183 : : PlanState **bitmapplans;
184 : : int nplans;
185 : : int i;
186 : :
187 : : /*
188 : : * get information from the node
189 : : */
190 : 146 : bitmapplans = node->bitmapplans;
191 : 146 : nplans = node->nplans;
192 : :
193 : : /*
194 : : * shut down each of the subscans (that we've initialized)
195 : : */
196 [ + + ]: 438 : for (i = 0; i < nplans; i++)
197 : : {
198 [ + - ]: 292 : if (bitmapplans[i])
199 : 292 : ExecEndNode(bitmapplans[i]);
200 : : }
201 : 146 : }
202 : :
203 : : void
5801 204 : 82 : ExecReScanBitmapAnd(BitmapAndState *node)
205 : : {
206 : : int i;
207 : :
7711 208 [ + + ]: 246 : for (i = 0; i < node->nplans; i++)
209 : : {
210 : 164 : PlanState *subnode = node->bitmapplans[i];
211 : :
212 : : /*
213 : : * ExecReScan doesn't know about my subplans, so I have to do
214 : : * changed-parameter signaling myself.
215 : : */
216 [ + + ]: 164 : if (node->ps.chgParam != NULL)
217 : 8 : UpdateChangedParamSet(subnode, node->ps.chgParam);
218 : :
219 : : /*
220 : : * If chgParam of subnode is not null then plan will be re-scanned by
221 : : * first ExecProcNode.
222 : : */
5801 223 [ + + ]: 164 : if (subnode->chgParam == NULL)
224 : 160 : ExecReScan(subnode);
225 : : }
7711 226 : 82 : }
|