1 /*-------------------------------------------------------------------------
4 * routines to handle BitmapAnd nodes.
6 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
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/instrument.h"
33 #include "executor/nodeBitmapAnd.h"
36 /* ----------------------------------------------------------------
39 * Begin all of the subscans of the BitmapAnd node.
40 * ----------------------------------------------------------------
43 ExecInitBitmapAnd(BitmapAnd
*node
, EState
*estate
, int eflags
)
45 BitmapAndState
*bitmapandstate
= makeNode(BitmapAndState
);
46 PlanState
**bitmapplanstates
;
52 /* check for unsupported flags */
53 Assert(!(eflags
& (EXEC_FLAG_BACKWARD
| EXEC_FLAG_MARK
)));
56 * Set up empty vector of subplan states
58 nplans
= list_length(node
->bitmapplans
);
60 bitmapplanstates
= (PlanState
**) palloc0(nplans
* sizeof(PlanState
*));
63 * create new BitmapAndState for our BitmapAnd node
65 bitmapandstate
->ps
.plan
= (Plan
*) node
;
66 bitmapandstate
->ps
.state
= estate
;
67 bitmapandstate
->bitmapplans
= bitmapplanstates
;
68 bitmapandstate
->nplans
= nplans
;
71 * Miscellaneous initialization
73 * BitmapAnd plans don't have expression contexts because they never call
74 * ExecQual or ExecProject. They don't need any tuple slots either.
77 #define BITMAPAND_NSLOTS 0
80 * call ExecInitNode on each of the plans to be executed and save the
81 * results into the array "bitmapplanstates".
84 foreach(l
, node
->bitmapplans
)
86 initNode
= (Plan
*) lfirst(l
);
87 bitmapplanstates
[i
] = ExecInitNode(initNode
, estate
, eflags
);
91 return bitmapandstate
;
95 ExecCountSlotsBitmapAnd(BitmapAnd
*node
)
100 foreach(plan
, node
->bitmapplans
)
101 nSlots
+= ExecCountSlotsNode((Plan
*) lfirst(plan
));
102 return nSlots
+ BITMAPAND_NSLOTS
;
105 /* ----------------------------------------------------------------
107 * ----------------------------------------------------------------
110 MultiExecBitmapAnd(BitmapAndState
*node
)
112 PlanState
**bitmapplans
;
115 TIDBitmap
*result
= NULL
;
117 /* must provide our own instrumentation support */
118 if (node
->ps
.instrument
)
119 InstrStartNode(node
->ps
.instrument
);
122 * get information from the node
124 bitmapplans
= node
->bitmapplans
;
125 nplans
= node
->nplans
;
128 * Scan all the subplans and AND their result bitmaps
130 for (i
= 0; i
< nplans
; i
++)
132 PlanState
*subnode
= bitmapplans
[i
];
133 TIDBitmap
*subresult
;
135 subresult
= (TIDBitmap
*) MultiExecProcNode(subnode
);
137 if (!subresult
|| !IsA(subresult
, TIDBitmap
))
138 elog(ERROR
, "unrecognized result from subplan");
141 result
= subresult
; /* first subplan */
144 tbm_intersect(result
, subresult
);
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
155 if (tbm_is_empty(result
))
160 elog(ERROR
, "BitmapAnd doesn't support zero inputs");
162 /* must provide our own instrumentation support */
163 if (node
->ps
.instrument
)
164 InstrStopNode(node
->ps
.instrument
, 0 /* XXX */ );
166 return (Node
*) result
;
169 /* ----------------------------------------------------------------
172 * Shuts down the subscans of the BitmapAnd node.
174 * Returns nothing of interest.
175 * ----------------------------------------------------------------
178 ExecEndBitmapAnd(BitmapAndState
*node
)
180 PlanState
**bitmapplans
;
185 * get information from the node
187 bitmapplans
= node
->bitmapplans
;
188 nplans
= node
->nplans
;
191 * shut down each of the subscans (that we've initialized)
193 for (i
= 0; i
< nplans
; i
++)
196 ExecEndNode(bitmapplans
[i
]);
201 ExecReScanBitmapAnd(BitmapAndState
*node
, ExprContext
*exprCtxt
)
205 for (i
= 0; i
< node
->nplans
; i
++)
207 PlanState
*subnode
= node
->bitmapplans
[i
];
210 * ExecReScan doesn't know about my subplans, so I have to do
211 * changed-parameter signaling myself.
213 if (node
->ps
.chgParam
!= NULL
)
214 UpdateChangedParamSet(subnode
, node
->ps
.chgParam
);
217 * Always rescan the inputs immediately, to ensure we can pass down
218 * any outer tuple that might be used in index quals.
220 ExecReScan(subnode
, exprCtxt
);