Fix xslt_process() to ensure that it inserts a NULL terminator after the
[PostgreSQL.git] / src / backend / executor / nodeBitmapOr.c
blobe3c8070affe2fbdb7ed014de8057aa325f177025
1 /*-------------------------------------------------------------------------
3 * nodeBitmapOr.c
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
10 * IDENTIFICATION
11 * $PostgreSQL$
13 *-------------------------------------------------------------------------
15 /* INTERFACE ROUTINES
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
21 * NOTES
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
26 * execution.
29 #include "postgres.h"
31 #include "executor/execdebug.h"
32 #include "executor/instrument.h"
33 #include "executor/nodeBitmapOr.h"
34 #include "miscadmin.h"
37 /* ----------------------------------------------------------------
38 * ExecInitBitmapOr
40 * Begin all of the subscans of the BitmapOr node.
41 * ----------------------------------------------------------------
43 BitmapOrState *
44 ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
46 BitmapOrState *bitmaporstate = makeNode(BitmapOrState);
47 PlanState **bitmapplanstates;
48 int nplans;
49 int i;
50 ListCell *l;
51 Plan *initNode;
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".
84 i = 0;
85 foreach(l, node->bitmapplans)
87 initNode = (Plan *) lfirst(l);
88 bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
89 i++;
92 return bitmaporstate;
95 int
96 ExecCountSlotsBitmapOr(BitmapOr *node)
98 ListCell *plan;
99 int nSlots = 0;
101 foreach(plan, node->bitmapplans)
102 nSlots += ExecCountSlotsNode((Plan *) lfirst(plan));
103 return nSlots + BITMAPOR_NSLOTS;
106 /* ----------------------------------------------------------------
107 * MultiExecBitmapOr
108 * ----------------------------------------------------------------
110 Node *
111 MultiExecBitmapOr(BitmapOrState *node)
113 PlanState **bitmapplans;
114 int nplans;
115 int i;
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");
156 else
158 /* standard implementation */
159 subresult = (TIDBitmap *) MultiExecProcNode(subnode);
161 if (!subresult || !IsA(subresult, TIDBitmap))
162 elog(ERROR, "unrecognized result from subplan");
164 if (result == NULL)
165 result = subresult; /* first subplan */
166 else
168 tbm_union(result, subresult);
169 tbm_free(subresult);
174 /* We could return an empty result set here? */
175 if (result == NULL)
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 /* ----------------------------------------------------------------
186 * ExecEndBitmapOr
188 * Shuts down the subscans of the BitmapOr node.
190 * Returns nothing of interest.
191 * ----------------------------------------------------------------
193 void
194 ExecEndBitmapOr(BitmapOrState *node)
196 PlanState **bitmapplans;
197 int nplans;
198 int i;
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++)
211 if (bitmapplans[i])
212 ExecEndNode(bitmapplans[i]);
216 void
217 ExecReScanBitmapOr(BitmapOrState *node, ExprContext *exprCtxt)
219 int i;
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);