Fix xslt_process() to ensure that it inserts a NULL terminator after the
[PostgreSQL.git] / src / backend / executor / nodeBitmapAnd.c
blob650d07fd417b12bb681b0f02262ec52e14b7acb2
1 /*-------------------------------------------------------------------------
3 * nodeBitmapAnd.c
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
10 * IDENTIFICATION
11 * $PostgreSQL$
13 *-------------------------------------------------------------------------
15 /* INTERFACE ROUTINES
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
21 * NOTES
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
26 * execution.
29 #include "postgres.h"
31 #include "executor/execdebug.h"
32 #include "executor/instrument.h"
33 #include "executor/nodeBitmapAnd.h"
36 /* ----------------------------------------------------------------
37 * ExecInitBitmapAnd
39 * Begin all of the subscans of the BitmapAnd node.
40 * ----------------------------------------------------------------
42 BitmapAndState *
43 ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
45 BitmapAndState *bitmapandstate = makeNode(BitmapAndState);
46 PlanState **bitmapplanstates;
47 int nplans;
48 int i;
49 ListCell *l;
50 Plan *initNode;
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".
83 i = 0;
84 foreach(l, node->bitmapplans)
86 initNode = (Plan *) lfirst(l);
87 bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
88 i++;
91 return bitmapandstate;
94 int
95 ExecCountSlotsBitmapAnd(BitmapAnd *node)
97 ListCell *plan;
98 int nSlots = 0;
100 foreach(plan, node->bitmapplans)
101 nSlots += ExecCountSlotsNode((Plan *) lfirst(plan));
102 return nSlots + BITMAPAND_NSLOTS;
105 /* ----------------------------------------------------------------
106 * MultiExecBitmapAnd
107 * ----------------------------------------------------------------
109 Node *
110 MultiExecBitmapAnd(BitmapAndState *node)
112 PlanState **bitmapplans;
113 int nplans;
114 int i;
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");
140 if (result == NULL)
141 result = subresult; /* first subplan */
142 else
144 tbm_intersect(result, subresult);
145 tbm_free(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
153 * occur.)
155 if (tbm_is_empty(result))
156 break;
159 if (result == NULL)
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 /* ----------------------------------------------------------------
170 * ExecEndBitmapAnd
172 * Shuts down the subscans of the BitmapAnd node.
174 * Returns nothing of interest.
175 * ----------------------------------------------------------------
177 void
178 ExecEndBitmapAnd(BitmapAndState *node)
180 PlanState **bitmapplans;
181 int nplans;
182 int i;
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++)
195 if (bitmapplans[i])
196 ExecEndNode(bitmapplans[i]);
200 void
201 ExecReScanBitmapAnd(BitmapAndState *node, ExprContext *exprCtxt)
203 int i;
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);