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