1 /*-------------------------------------------------------------------------
4 * routines to handle BitmapOr nodes.
6 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
13 *-------------------------------------------------------------------------
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
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
31 #include "executor/execdebug.h"
32 #include "executor/instrument.h"
33 #include "executor/nodeBitmapOr.h"
34 #include "miscadmin.h"
37 /* ----------------------------------------------------------------
40 * Begin all of the subscans of the BitmapOr node.
41 * ----------------------------------------------------------------
44 ExecInitBitmapOr(BitmapOr
*node
, EState
*estate
, int eflags
)
46 BitmapOrState
*bitmaporstate
= makeNode(BitmapOrState
);
47 PlanState
**bitmapplanstates
;
53 /* check for unsupported flags */
54 Assert(!(eflags
& (EXEC_FLAG_BACKWARD
| EXEC_FLAG_MARK
)));
57 * Set up empty vector of subplan states
59 nplans
= list_length(node
->bitmapplans
);
61 bitmapplanstates
= (PlanState
**) palloc0(nplans
* sizeof(PlanState
*));
64 * create new BitmapOrState for our BitmapOr node
66 bitmaporstate
->ps
.plan
= (Plan
*) node
;
67 bitmaporstate
->ps
.state
= estate
;
68 bitmaporstate
->bitmapplans
= bitmapplanstates
;
69 bitmaporstate
->nplans
= nplans
;
72 * Miscellaneous initialization
74 * BitmapOr plans don't have expression contexts because they never call
75 * ExecQual or ExecProject. They don't need any tuple slots either.
78 #define BITMAPOR_NSLOTS 0
81 * call ExecInitNode on each of the plans to be executed and save the
82 * results into the array "bitmapplanstates".
85 foreach(l
, node
->bitmapplans
)
87 initNode
= (Plan
*) lfirst(l
);
88 bitmapplanstates
[i
] = ExecInitNode(initNode
, estate
, eflags
);
96 ExecCountSlotsBitmapOr(BitmapOr
*node
)
101 foreach(plan
, node
->bitmapplans
)
102 nSlots
+= ExecCountSlotsNode((Plan
*) lfirst(plan
));
103 return nSlots
+ BITMAPOR_NSLOTS
;
106 /* ----------------------------------------------------------------
108 * ----------------------------------------------------------------
111 MultiExecBitmapOr(BitmapOrState
*node
)
113 PlanState
**bitmapplans
;
116 TIDBitmap
*result
= NULL
;
118 /* must provide our own instrumentation support */
119 if (node
->ps
.instrument
)
120 InstrStartNode(node
->ps
.instrument
);
123 * get information from the node
125 bitmapplans
= node
->bitmapplans
;
126 nplans
= node
->nplans
;
129 * Scan all the subplans and OR their result bitmaps
131 for (i
= 0; i
< nplans
; i
++)
133 PlanState
*subnode
= bitmapplans
[i
];
134 TIDBitmap
*subresult
;
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.
141 if (IsA(subnode
, BitmapIndexScanState
))
143 if (result
== NULL
) /* first subplan */
145 /* XXX should we use less than work_mem for this? */
146 result
= tbm_create(work_mem
* 1024L);
149 ((BitmapIndexScanState
*) subnode
)->biss_result
= result
;
151 subresult
= (TIDBitmap
*) MultiExecProcNode(subnode
);
153 if (subresult
!= result
)
154 elog(ERROR
, "unrecognized result from subplan");
158 /* standard implementation */
159 subresult
= (TIDBitmap
*) MultiExecProcNode(subnode
);
161 if (!subresult
|| !IsA(subresult
, TIDBitmap
))
162 elog(ERROR
, "unrecognized result from subplan");
165 result
= subresult
; /* first subplan */
168 tbm_union(result
, subresult
);
174 /* We could return an empty result set here? */
176 elog(ERROR
, "BitmapOr doesn't support zero inputs");
178 /* must provide our own instrumentation support */
179 if (node
->ps
.instrument
)
180 InstrStopNode(node
->ps
.instrument
, 0 /* XXX */ );
182 return (Node
*) result
;
185 /* ----------------------------------------------------------------
188 * Shuts down the subscans of the BitmapOr node.
190 * Returns nothing of interest.
191 * ----------------------------------------------------------------
194 ExecEndBitmapOr(BitmapOrState
*node
)
196 PlanState
**bitmapplans
;
201 * get information from the node
203 bitmapplans
= node
->bitmapplans
;
204 nplans
= node
->nplans
;
207 * shut down each of the subscans (that we've initialized)
209 for (i
= 0; i
< nplans
; i
++)
212 ExecEndNode(bitmapplans
[i
]);
217 ExecReScanBitmapOr(BitmapOrState
*node
, ExprContext
*exprCtxt
)
221 for (i
= 0; i
< node
->nplans
; i
++)
223 PlanState
*subnode
= node
->bitmapplans
[i
];
226 * ExecReScan doesn't know about my subplans, so I have to do
227 * changed-parameter signaling myself.
229 if (node
->ps
.chgParam
!= NULL
)
230 UpdateChangedParamSet(subnode
, node
->ps
.chgParam
);
233 * Always rescan the inputs immediately, to ensure we can pass down
234 * any outer tuple that might be used in index quals.
236 ExecReScan(subnode
, exprCtxt
);