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