]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeBitmapAnd.c
Make some small planner API cleanups.
[postgresql] / src / backend / executor / nodeBitmapAnd.c
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  */
41 static TupleTableSlot *
42 ExecBitmapAnd(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  */
54 BitmapAndState *
55 ExecInitBitmapAnd(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  */
109 Node *
110 MultiExecBitmapAnd(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  */
177 void
178 ExecEndBitmapAnd(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
200 void
201 ExecReScanBitmapAnd(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 }