Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * nodeBitmapOr.c
4 : * routines to handle BitmapOr 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/nodeBitmapOr.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : /* INTERFACE ROUTINES
16 : * ExecInitBitmapOr - initialize the BitmapOr node
17 : * MultiExecBitmapOr - retrieve the result bitmap from the node
18 : * ExecEndBitmapOr - shut down the BitmapOr node
19 : * ExecReScanBitmapOr - rescan the BitmapOr node
20 : *
21 : * NOTES
22 : * BitmapOr 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/nodeBitmapOr.h"
33 : #include "miscadmin.h"
34 :
35 :
36 : /* ----------------------------------------------------------------
37 : * ExecBitmapOr
38 : *
39 : * stub for pro forma compliance
40 : * ----------------------------------------------------------------
41 : */
42 : static TupleTableSlot *
43 0 : ExecBitmapOr(PlanState *pstate)
44 : {
45 0 : elog(ERROR, "BitmapOr node does not support ExecProcNode call convention");
46 : return NULL;
47 : }
48 :
49 : /* ----------------------------------------------------------------
50 : * ExecInitBitmapOr
51 : *
52 : * Begin all of the subscans of the BitmapOr node.
53 : * ----------------------------------------------------------------
54 : */
55 : BitmapOrState *
56 17 : ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
57 : {
58 17 : BitmapOrState *bitmaporstate = makeNode(BitmapOrState);
59 : PlanState **bitmapplanstates;
60 : int nplans;
61 : int i;
62 : ListCell *l;
63 : Plan *initNode;
64 :
65 : /* check for unsupported flags */
66 17 : Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
67 :
68 : /*
69 : * Set up empty vector of subplan states
70 : */
71 17 : nplans = list_length(node->bitmapplans);
72 :
73 17 : bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
74 :
75 : /*
76 : * create new BitmapOrState for our BitmapOr node
77 : */
78 17 : bitmaporstate->ps.plan = (Plan *) node;
79 17 : bitmaporstate->ps.state = estate;
80 17 : bitmaporstate->ps.ExecProcNode = ExecBitmapOr;
81 17 : bitmaporstate->bitmapplans = bitmapplanstates;
82 17 : bitmaporstate->nplans = nplans;
83 :
84 : /*
85 : * Miscellaneous initialization
86 : *
87 : * BitmapOr plans don't have expression contexts because they never call
88 : * ExecQual or ExecProject. They don't need any tuple slots either.
89 : */
90 :
91 : /*
92 : * call ExecInitNode on each of the plans to be executed and save the
93 : * results into the array "bitmapplanstates".
94 : */
95 17 : i = 0;
96 56 : foreach(l, node->bitmapplans)
97 : {
98 39 : initNode = (Plan *) lfirst(l);
99 39 : bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
100 39 : i++;
101 : }
102 :
103 17 : return bitmaporstate;
104 : }
105 :
106 : /* ----------------------------------------------------------------
107 : * MultiExecBitmapOr
108 : * ----------------------------------------------------------------
109 : */
110 : Node *
111 7 : MultiExecBitmapOr(BitmapOrState *node)
112 : {
113 : PlanState **bitmapplans;
114 : int nplans;
115 : int i;
116 7 : TIDBitmap *result = NULL;
117 :
118 : /* must provide our own instrumentation support */
119 7 : if (node->ps.instrument)
120 0 : InstrStartNode(node->ps.instrument);
121 :
122 : /*
123 : * get information from the node
124 : */
125 7 : bitmapplans = node->bitmapplans;
126 7 : nplans = node->nplans;
127 :
128 : /*
129 : * Scan all the subplans and OR their result bitmaps
130 : */
131 24 : for (i = 0; i < nplans; i++)
132 : {
133 17 : PlanState *subnode = bitmapplans[i];
134 : TIDBitmap *subresult;
135 :
136 : /*
137 : * We can special-case BitmapIndexScan children to avoid an explicit
138 : * tbm_union step for each child: just pass down the current result
139 : * bitmap and let the child OR directly into it.
140 : */
141 17 : if (IsA(subnode, BitmapIndexScanState))
142 : {
143 17 : if (result == NULL) /* first subplan */
144 : {
145 : /* XXX should we use less than work_mem for this? */
146 7 : result = tbm_create(work_mem * 1024L,
147 7 : ((BitmapOr *) node->ps.plan)->isshared ?
148 0 : node->ps.state->es_query_dsa : NULL);
149 : }
150 :
151 17 : ((BitmapIndexScanState *) subnode)->biss_result = result;
152 :
153 17 : subresult = (TIDBitmap *) MultiExecProcNode(subnode);
154 :
155 17 : if (subresult != result)
156 0 : elog(ERROR, "unrecognized result from subplan");
157 : }
158 : else
159 : {
160 : /* standard implementation */
161 0 : subresult = (TIDBitmap *) MultiExecProcNode(subnode);
162 :
163 0 : if (!subresult || !IsA(subresult, TIDBitmap))
164 0 : elog(ERROR, "unrecognized result from subplan");
165 :
166 0 : if (result == NULL)
167 0 : result = subresult; /* first subplan */
168 : else
169 : {
170 0 : tbm_union(result, subresult);
171 0 : tbm_free(subresult);
172 : }
173 : }
174 : }
175 :
176 : /* We could return an empty result set here? */
177 7 : if (result == NULL)
178 0 : elog(ERROR, "BitmapOr doesn't support zero inputs");
179 :
180 : /* must provide our own instrumentation support */
181 7 : if (node->ps.instrument)
182 0 : InstrStopNode(node->ps.instrument, 0 /* XXX */ );
183 :
184 7 : return (Node *) result;
185 : }
186 :
187 : /* ----------------------------------------------------------------
188 : * ExecEndBitmapOr
189 : *
190 : * Shuts down the subscans of the BitmapOr node.
191 : *
192 : * Returns nothing of interest.
193 : * ----------------------------------------------------------------
194 : */
195 : void
196 17 : ExecEndBitmapOr(BitmapOrState *node)
197 : {
198 : PlanState **bitmapplans;
199 : int nplans;
200 : int i;
201 :
202 : /*
203 : * get information from the node
204 : */
205 17 : bitmapplans = node->bitmapplans;
206 17 : nplans = node->nplans;
207 :
208 : /*
209 : * shut down each of the subscans (that we've initialized)
210 : */
211 56 : for (i = 0; i < nplans; i++)
212 : {
213 39 : if (bitmapplans[i])
214 39 : ExecEndNode(bitmapplans[i]);
215 : }
216 17 : }
217 :
218 : void
219 0 : ExecReScanBitmapOr(BitmapOrState *node)
220 : {
221 : int i;
222 :
223 0 : for (i = 0; i < node->nplans; i++)
224 : {
225 0 : PlanState *subnode = node->bitmapplans[i];
226 :
227 : /*
228 : * ExecReScan doesn't know about my subplans, so I have to do
229 : * changed-parameter signaling myself.
230 : */
231 0 : if (node->ps.chgParam != NULL)
232 0 : UpdateChangedParamSet(subnode, node->ps.chgParam);
233 :
234 : /*
235 : * If chgParam of subnode is not null then plan will be re-scanned by
236 : * first ExecProcNode.
237 : */
238 0 : if (subnode->chgParam == NULL)
239 0 : ExecReScan(subnode);
240 : }
241 0 : }
|