OSDN Git Service

Update copyright for 2009.
[pg-rex/syncrep.git] / src / backend / executor / nodeBitmapOr.c
1 /*-------------------------------------------------------------------------
2  *
3  * nodeBitmapOr.c
4  *        routines to handle BitmapOr nodes.
5  *
6  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/executor/nodeBitmapOr.c,v 1.10 2009/01/01 17:23:41 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
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
20  *
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.
27  */
28
29 #include "postgres.h"
30
31 #include "executor/execdebug.h"
32 #include "executor/instrument.h"
33 #include "executor/nodeBitmapOr.h"
34 #include "miscadmin.h"
35
36
37 /* ----------------------------------------------------------------
38  *              ExecInitBitmapOr
39  *
40  *              Begin all of the subscans of the BitmapOr node.
41  * ----------------------------------------------------------------
42  */
43 BitmapOrState *
44 ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
45 {
46         BitmapOrState *bitmaporstate = makeNode(BitmapOrState);
47         PlanState **bitmapplanstates;
48         int                     nplans;
49         int                     i;
50         ListCell   *l;
51         Plan       *initNode;
52
53         /* check for unsupported flags */
54         Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
55
56         /*
57          * Set up empty vector of subplan states
58          */
59         nplans = list_length(node->bitmapplans);
60
61         bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
62
63         /*
64          * create new BitmapOrState for our BitmapOr node
65          */
66         bitmaporstate->ps.plan = (Plan *) node;
67         bitmaporstate->ps.state = estate;
68         bitmaporstate->bitmapplans = bitmapplanstates;
69         bitmaporstate->nplans = nplans;
70
71         /*
72          * Miscellaneous initialization
73          *
74          * BitmapOr plans don't have expression contexts because they never call
75          * ExecQual or ExecProject.  They don't need any tuple slots either.
76          */
77
78 #define BITMAPOR_NSLOTS 0
79
80         /*
81          * call ExecInitNode on each of the plans to be executed and save the
82          * results into the array "bitmapplanstates".
83          */
84         i = 0;
85         foreach(l, node->bitmapplans)
86         {
87                 initNode = (Plan *) lfirst(l);
88                 bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
89                 i++;
90         }
91
92         return bitmaporstate;
93 }
94
95 int
96 ExecCountSlotsBitmapOr(BitmapOr *node)
97 {
98         ListCell   *plan;
99         int                     nSlots = 0;
100
101         foreach(plan, node->bitmapplans)
102                 nSlots += ExecCountSlotsNode((Plan *) lfirst(plan));
103         return nSlots + BITMAPOR_NSLOTS;
104 }
105
106 /* ----------------------------------------------------------------
107  *         MultiExecBitmapOr
108  * ----------------------------------------------------------------
109  */
110 Node *
111 MultiExecBitmapOr(BitmapOrState *node)
112 {
113         PlanState **bitmapplans;
114         int                     nplans;
115         int                     i;
116         TIDBitmap  *result = NULL;
117
118         /* must provide our own instrumentation support */
119         if (node->ps.instrument)
120                 InstrStartNode(node->ps.instrument);
121
122         /*
123          * get information from the node
124          */
125         bitmapplans = node->bitmapplans;
126         nplans = node->nplans;
127
128         /*
129          * Scan all the subplans and OR their result bitmaps
130          */
131         for (i = 0; i < nplans; i++)
132         {
133                 PlanState  *subnode = bitmapplans[i];
134                 TIDBitmap  *subresult;
135
136                 /*
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.
140                  */
141                 if (IsA(subnode, BitmapIndexScanState))
142                 {
143                         if (result == NULL) /* first subplan */
144                         {
145                                 /* XXX should we use less than work_mem for this? */
146                                 result = tbm_create(work_mem * 1024L);
147                         }
148
149                         ((BitmapIndexScanState *) subnode)->biss_result = result;
150
151                         subresult = (TIDBitmap *) MultiExecProcNode(subnode);
152
153                         if (subresult != result)
154                                 elog(ERROR, "unrecognized result from subplan");
155                 }
156                 else
157                 {
158                         /* standard implementation */
159                         subresult = (TIDBitmap *) MultiExecProcNode(subnode);
160
161                         if (!subresult || !IsA(subresult, TIDBitmap))
162                                 elog(ERROR, "unrecognized result from subplan");
163
164                         if (result == NULL)
165                                 result = subresult;             /* first subplan */
166                         else
167                         {
168                                 tbm_union(result, subresult);
169                                 tbm_free(subresult);
170                         }
171                 }
172         }
173
174         /* We could return an empty result set here? */
175         if (result == NULL)
176                 elog(ERROR, "BitmapOr doesn't support zero inputs");
177
178         /* must provide our own instrumentation support */
179         if (node->ps.instrument)
180                 InstrStopNode(node->ps.instrument, 0 /* XXX */ );
181
182         return (Node *) result;
183 }
184
185 /* ----------------------------------------------------------------
186  *              ExecEndBitmapOr
187  *
188  *              Shuts down the subscans of the BitmapOr node.
189  *
190  *              Returns nothing of interest.
191  * ----------------------------------------------------------------
192  */
193 void
194 ExecEndBitmapOr(BitmapOrState *node)
195 {
196         PlanState **bitmapplans;
197         int                     nplans;
198         int                     i;
199
200         /*
201          * get information from the node
202          */
203         bitmapplans = node->bitmapplans;
204         nplans = node->nplans;
205
206         /*
207          * shut down each of the subscans (that we've initialized)
208          */
209         for (i = 0; i < nplans; i++)
210         {
211                 if (bitmapplans[i])
212                         ExecEndNode(bitmapplans[i]);
213         }
214 }
215
216 void
217 ExecReScanBitmapOr(BitmapOrState *node, ExprContext *exprCtxt)
218 {
219         int                     i;
220
221         for (i = 0; i < node->nplans; i++)
222         {
223                 PlanState  *subnode = node->bitmapplans[i];
224
225                 /*
226                  * ExecReScan doesn't know about my subplans, so I have to do
227                  * changed-parameter signaling myself.
228                  */
229                 if (node->ps.chgParam != NULL)
230                         UpdateChangedParamSet(subnode, node->ps.chgParam);
231
232                 /*
233                  * Always rescan the inputs immediately, to ensure we can pass down
234                  * any outer tuple that might be used in index quals.
235                  */
236                 ExecReScan(subnode, exprCtxt);
237         }
238 }