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