1 /*-------------------------------------------------------------------------
4 * routines to handle BitmapOr nodes.
6 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/executor/nodeBitmapOr.c
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/executor.h"
32 #include "executor/nodeBitmapOr.h"
33 #include "miscadmin.h"
36 /* ----------------------------------------------------------------
39 * stub for pro forma compliance
40 * ----------------------------------------------------------------
42 static TupleTableSlot
*
43 ExecBitmapOr(PlanState
*pstate
)
45 elog(ERROR
, "BitmapOr node does not support ExecProcNode call convention");
49 /* ----------------------------------------------------------------
52 * Begin all of the subscans of the BitmapOr node.
53 * ----------------------------------------------------------------
56 ExecInitBitmapOr(BitmapOr
*node
, EState
*estate
, int eflags
)
58 BitmapOrState
*bitmaporstate
= makeNode(BitmapOrState
);
59 PlanState
**bitmapplanstates
;
65 /* check for unsupported flags */
66 Assert(!(eflags
& (EXEC_FLAG_BACKWARD
| EXEC_FLAG_MARK
)));
69 * Set up empty vector of subplan states
71 nplans
= list_length(node
->bitmapplans
);
73 bitmapplanstates
= (PlanState
**) palloc0(nplans
* sizeof(PlanState
*));
76 * create new BitmapOrState for our BitmapOr node
78 bitmaporstate
->ps
.plan
= (Plan
*) node
;
79 bitmaporstate
->ps
.state
= estate
;
80 bitmaporstate
->ps
.ExecProcNode
= ExecBitmapOr
;
81 bitmaporstate
->bitmapplans
= bitmapplanstates
;
82 bitmaporstate
->nplans
= nplans
;
85 * call ExecInitNode on each of the plans to be executed and save the
86 * results into the array "bitmapplanstates".
89 foreach(l
, node
->bitmapplans
)
91 initNode
= (Plan
*) lfirst(l
);
92 bitmapplanstates
[i
] = ExecInitNode(initNode
, estate
, eflags
);
97 * Miscellaneous initialization
99 * BitmapOr plans don't have expression contexts because they never call
100 * ExecQual or ExecProject. They don't need any tuple slots either.
103 return bitmaporstate
;
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,
147 ((BitmapOr
*) node
->ps
.plan
)->isshared
?
148 node
->ps
.state
->es_query_dsa
: NULL
);
151 ((BitmapIndexScanState
*) subnode
)->biss_result
= result
;
153 subresult
= (TIDBitmap
*) MultiExecProcNode(subnode
);
155 if (subresult
!= result
)
156 elog(ERROR
, "unrecognized result from subplan");
160 /* standard implementation */
161 subresult
= (TIDBitmap
*) MultiExecProcNode(subnode
);
163 if (!subresult
|| !IsA(subresult
, TIDBitmap
))
164 elog(ERROR
, "unrecognized result from subplan");
167 result
= subresult
; /* first subplan */
170 tbm_union(result
, subresult
);
176 /* We could return an empty result set here? */
178 elog(ERROR
, "BitmapOr doesn't support zero inputs");
180 /* must provide our own instrumentation support */
181 if (node
->ps
.instrument
)
182 InstrStopNode(node
->ps
.instrument
, 0 /* XXX */ );
184 return (Node
*) result
;
187 /* ----------------------------------------------------------------
190 * Shuts down the subscans of the BitmapOr node.
192 * Returns nothing of interest.
193 * ----------------------------------------------------------------
196 ExecEndBitmapOr(BitmapOrState
*node
)
198 PlanState
**bitmapplans
;
203 * get information from the node
205 bitmapplans
= node
->bitmapplans
;
206 nplans
= node
->nplans
;
209 * shut down each of the subscans (that we've initialized)
211 for (i
= 0; i
< nplans
; i
++)
214 ExecEndNode(bitmapplans
[i
]);
219 ExecReScanBitmapOr(BitmapOrState
*node
)
223 for (i
= 0; i
< node
->nplans
; i
++)
225 PlanState
*subnode
= node
->bitmapplans
[i
];
228 * ExecReScan doesn't know about my subplans, so I have to do
229 * changed-parameter signaling myself.
231 if (node
->ps
.chgParam
!= NULL
)
232 UpdateChangedParamSet(subnode
, node
->ps
.chgParam
);
235 * If chgParam of subnode is not null then plan will be re-scanned by
236 * first ExecProcNode.
238 if (subnode
->chgParam
== NULL
)