Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * nodeBitmapAnd.c
4 : * routines to handle BitmapAnd nodes.
5 : *
6 : * Portions Copyright (c) 1996-2017, 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 : */
41 : static TupleTableSlot *
42 0 : ExecBitmapAnd(PlanState *pstate)
43 : {
44 0 : 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 : */
54 : BitmapAndState *
55 3 : ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
56 : {
57 3 : 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 3 : Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
66 :
67 : /*
68 : * Set up empty vector of subplan states
69 : */
70 3 : nplans = list_length(node->bitmapplans);
71 :
72 3 : bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
73 :
74 : /*
75 : * create new BitmapAndState for our BitmapAnd node
76 : */
77 3 : bitmapandstate->ps.plan = (Plan *) node;
78 3 : bitmapandstate->ps.state = estate;
79 3 : bitmapandstate->ps.ExecProcNode = ExecBitmapAnd;
80 3 : bitmapandstate->bitmapplans = bitmapplanstates;
81 3 : bitmapandstate->nplans = nplans;
82 :
83 : /*
84 : * Miscellaneous initialization
85 : *
86 : * BitmapAnd plans don't have expression contexts because they never call
87 : * ExecQual or ExecProject. They don't need any tuple slots either.
88 : */
89 :
90 : /*
91 : * call ExecInitNode on each of the plans to be executed and save the
92 : * results into the array "bitmapplanstates".
93 : */
94 3 : i = 0;
95 9 : foreach(l, node->bitmapplans)
96 : {
97 6 : initNode = (Plan *) lfirst(l);
98 6 : bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
99 6 : i++;
100 : }
101 :
102 3 : return bitmapandstate;
103 : }
104 :
105 : /* ----------------------------------------------------------------
106 : * MultiExecBitmapAnd
107 : * ----------------------------------------------------------------
108 : */
109 : Node *
110 2 : MultiExecBitmapAnd(BitmapAndState *node)
111 : {
112 : PlanState **bitmapplans;
113 : int nplans;
114 : int i;
115 2 : TIDBitmap *result = NULL;
116 :
117 : /* must provide our own instrumentation support */
118 2 : if (node->ps.instrument)
119 0 : InstrStartNode(node->ps.instrument);
120 :
121 : /*
122 : * get information from the node
123 : */
124 2 : bitmapplans = node->bitmapplans;
125 2 : nplans = node->nplans;
126 :
127 : /*
128 : * Scan all the subplans and AND their result bitmaps
129 : */
130 6 : for (i = 0; i < nplans; i++)
131 : {
132 4 : PlanState *subnode = bitmapplans[i];
133 : TIDBitmap *subresult;
134 :
135 4 : subresult = (TIDBitmap *) MultiExecProcNode(subnode);
136 :
137 4 : if (!subresult || !IsA(subresult, TIDBitmap))
138 0 : elog(ERROR, "unrecognized result from subplan");
139 :
140 4 : if (result == NULL)
141 2 : result = subresult; /* first subplan */
142 : else
143 : {
144 2 : tbm_intersect(result, subresult);
145 2 : 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 4 : if (tbm_is_empty(result))
156 0 : break;
157 : }
158 :
159 2 : if (result == NULL)
160 0 : elog(ERROR, "BitmapAnd doesn't support zero inputs");
161 :
162 : /* must provide our own instrumentation support */
163 2 : if (node->ps.instrument)
164 0 : InstrStopNode(node->ps.instrument, 0 /* XXX */ );
165 :
166 2 : 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 : */
177 : void
178 3 : ExecEndBitmapAnd(BitmapAndState *node)
179 : {
180 : PlanState **bitmapplans;
181 : int nplans;
182 : int i;
183 :
184 : /*
185 : * get information from the node
186 : */
187 3 : bitmapplans = node->bitmapplans;
188 3 : nplans = node->nplans;
189 :
190 : /*
191 : * shut down each of the subscans (that we've initialized)
192 : */
193 9 : for (i = 0; i < nplans; i++)
194 : {
195 6 : if (bitmapplans[i])
196 6 : ExecEndNode(bitmapplans[i]);
197 : }
198 3 : }
199 :
200 : void
201 0 : ExecReScanBitmapAnd(BitmapAndState *node)
202 : {
203 : int i;
204 :
205 0 : for (i = 0; i < node->nplans; i++)
206 : {
207 0 : 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 0 : if (node->ps.chgParam != NULL)
214 0 : 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 0 : if (subnode->chgParam == NULL)
221 0 : ExecReScan(subnode);
222 : }
223 0 : }
|