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 *
44 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 *
57 148 : ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
58 : {
59 148 : 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 */
67 : Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
68 :
69 : /*
70 : * Set up empty vector of subplan states
71 : */
72 148 : nplans = list_length(node->bitmapplans);
73 :
74 148 : bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
75 :
76 : /*
77 : * create new BitmapAndState for our BitmapAnd node
78 : */
79 148 : bitmapandstate->ps.plan = (Plan *) node;
80 148 : bitmapandstate->ps.state = estate;
81 148 : bitmapandstate->ps.ExecProcNode = ExecBitmapAnd;
82 148 : bitmapandstate->bitmapplans = bitmapplanstates;
83 148 : 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 : */
89 148 : i = 0;
90 444 : foreach(l, node->bitmapplans)
91 : {
92 296 : initNode = (Plan *) lfirst(l);
93 296 : bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
94 296 : 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 :
104 148 : return bitmapandstate;
105 : }
106 :
107 : /* ----------------------------------------------------------------
108 : * MultiExecBitmapAnd
109 : * ----------------------------------------------------------------
110 : */
111 : Node *
112 116 : MultiExecBitmapAnd(BitmapAndState *node)
113 : {
114 : PlanState **bitmapplans;
115 : int nplans;
116 : int i;
117 116 : TIDBitmap *result = NULL;
118 :
119 : /* must provide our own instrumentation support */
120 116 : if (node->ps.instrument)
121 0 : InstrStartNode(node->ps.instrument);
122 :
123 : /*
124 : * get information from the node
125 : */
126 116 : bitmapplans = node->bitmapplans;
127 116 : nplans = node->nplans;
128 :
129 : /*
130 : * Scan all the subplans and AND their result bitmaps
131 : */
132 344 : for (i = 0; i < nplans; i++)
133 : {
134 232 : PlanState *subnode = bitmapplans[i];
135 : TIDBitmap *subresult;
136 :
137 232 : subresult = (TIDBitmap *) MultiExecProcNode(subnode);
138 :
139 232 : if (!subresult || !IsA(subresult, TIDBitmap))
140 0 : elog(ERROR, "unrecognized result from subplan");
141 :
142 232 : if (result == NULL)
143 116 : result = subresult; /* first subplan */
144 : else
145 : {
146 116 : tbm_intersect(result, subresult);
147 116 : 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 : */
157 232 : if (tbm_is_empty(result))
158 4 : break;
159 : }
160 :
161 116 : if (result == NULL)
162 0 : elog(ERROR, "BitmapAnd doesn't support zero inputs");
163 :
164 : /* must provide our own instrumentation support */
165 116 : if (node->ps.instrument)
166 0 : InstrStopNode(node->ps.instrument, 0 /* XXX */ );
167 :
168 116 : 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 148 : ExecEndBitmapAnd(BitmapAndState *node)
181 : {
182 : PlanState **bitmapplans;
183 : int nplans;
184 : int i;
185 :
186 : /*
187 : * get information from the node
188 : */
189 148 : bitmapplans = node->bitmapplans;
190 148 : nplans = node->nplans;
191 :
192 : /*
193 : * shut down each of the subscans (that we've initialized)
194 : */
195 444 : for (i = 0; i < nplans; i++)
196 : {
197 296 : if (bitmapplans[i])
198 296 : ExecEndNode(bitmapplans[i]);
199 : }
200 148 : }
201 :
202 : void
203 84 : ExecReScanBitmapAnd(BitmapAndState *node)
204 : {
205 : int i;
206 :
207 252 : for (i = 0; i < node->nplans; i++)
208 : {
209 168 : 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 168 : 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 : */
222 168 : if (subnode->chgParam == NULL)
223 164 : ExecReScan(subnode);
224 : }
225 84 : }
|