1 /*-------------------------------------------------------------------------
4 * routines to handle BitmapAnd nodes.
6 * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/executor/nodeBitmapAnd.c
13 *-------------------------------------------------------------------------
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
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
31 #include "executor/execdebug.h"
32 #include "executor/nodeBitmapAnd.h"
35 /* ----------------------------------------------------------------
38 * Begin all of the subscans of the BitmapAnd node.
39 * ----------------------------------------------------------------
42 ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
44 BitmapAndState *bitmapandstate = makeNode(BitmapAndState);
45 PlanState **bitmapplanstates;
51 /* check for unsupported flags */
52 Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
55 * Set up empty vector of subplan states
57 nplans = list_length(node->bitmapplans);
59 bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
62 * create new BitmapAndState for our BitmapAnd node
64 bitmapandstate->ps.plan = (Plan *) node;
65 bitmapandstate->ps.state = estate;
66 bitmapandstate->bitmapplans = bitmapplanstates;
67 bitmapandstate->nplans = nplans;
70 * Miscellaneous initialization
72 * BitmapAnd plans don't have expression contexts because they never call
73 * ExecQual or ExecProject. They don't need any tuple slots either.
77 * call ExecInitNode on each of the plans to be executed and save the
78 * results into the array "bitmapplanstates".
81 foreach(l, node->bitmapplans)
83 initNode = (Plan *) lfirst(l);
84 bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
88 return bitmapandstate;
91 /* ----------------------------------------------------------------
93 * ----------------------------------------------------------------
96 MultiExecBitmapAnd(BitmapAndState *node)
98 PlanState **bitmapplans;
101 TIDBitmap *result = NULL;
103 /* must provide our own instrumentation support */
104 if (node->ps.instrument)
105 InstrStartNode(node->ps.instrument);
108 * get information from the node
110 bitmapplans = node->bitmapplans;
111 nplans = node->nplans;
114 * Scan all the subplans and AND their result bitmaps
116 for (i = 0; i < nplans; i++)
118 PlanState *subnode = bitmapplans[i];
119 TIDBitmap *subresult;
121 subresult = (TIDBitmap *) MultiExecProcNode(subnode);
123 if (!subresult || !IsA(subresult, TIDBitmap))
124 elog(ERROR, "unrecognized result from subplan");
127 result = subresult; /* first subplan */
130 tbm_intersect(result, subresult);
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
141 if (tbm_is_empty(result))
146 elog(ERROR, "BitmapAnd doesn't support zero inputs");
148 /* must provide our own instrumentation support */
149 if (node->ps.instrument)
150 InstrStopNode(node->ps.instrument, 0 /* XXX */ );
152 return (Node *) result;
155 /* ----------------------------------------------------------------
158 * Shuts down the subscans of the BitmapAnd node.
160 * Returns nothing of interest.
161 * ----------------------------------------------------------------
164 ExecEndBitmapAnd(BitmapAndState *node)
166 PlanState **bitmapplans;
171 * get information from the node
173 bitmapplans = node->bitmapplans;
174 nplans = node->nplans;
177 * shut down each of the subscans (that we've initialized)
179 for (i = 0; i < nplans; i++)
182 ExecEndNode(bitmapplans[i]);
187 ExecReScanBitmapAnd(BitmapAndState *node)
191 for (i = 0; i < node->nplans; i++)
193 PlanState *subnode = node->bitmapplans[i];
196 * ExecReScan doesn't know about my subplans, so I have to do
197 * changed-parameter signaling myself.
199 if (node->ps.chgParam != NULL)
200 UpdateChangedParamSet(subnode, node->ps.chgParam);
203 * If chgParam of subnode is not null then plan will be re-scanned by
204 * first ExecProcNode.
206 if (subnode->chgParam == NULL)