~ubuntu-branches/ubuntu/precise/postgresql-9.1/precise-security

« back to all changes in this revision

Viewing changes to src/backend/executor/nodeBitmapAnd.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * nodeBitmapAnd.c
 
4
 *        routines to handle BitmapAnd nodes.
 
5
 *
 
6
 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 *
 
10
 * IDENTIFICATION
 
11
 *        src/backend/executor/nodeBitmapAnd.c
 
12
 *
 
13
 *-------------------------------------------------------------------------
 
14
 */
 
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
 
20
 *
 
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.
 
27
 */
 
28
 
 
29
#include "postgres.h"
 
30
 
 
31
#include "executor/execdebug.h"
 
32
#include "executor/instrument.h"
 
33
#include "executor/nodeBitmapAnd.h"
 
34
 
 
35
 
 
36
/* ----------------------------------------------------------------
 
37
 *              ExecInitBitmapAnd
 
38
 *
 
39
 *              Begin all of the subscans of the BitmapAnd node.
 
40
 * ----------------------------------------------------------------
 
41
 */
 
42
BitmapAndState *
 
43
ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
 
44
{
 
45
        BitmapAndState *bitmapandstate = makeNode(BitmapAndState);
 
46
        PlanState **bitmapplanstates;
 
47
        int                     nplans;
 
48
        int                     i;
 
49
        ListCell   *l;
 
50
        Plan       *initNode;
 
51
 
 
52
        /* check for unsupported flags */
 
53
        Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
 
54
 
 
55
        /*
 
56
         * Set up empty vector of subplan states
 
57
         */
 
58
        nplans = list_length(node->bitmapplans);
 
59
 
 
60
        bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
 
61
 
 
62
        /*
 
63
         * create new BitmapAndState for our BitmapAnd node
 
64
         */
 
65
        bitmapandstate->ps.plan = (Plan *) node;
 
66
        bitmapandstate->ps.state = estate;
 
67
        bitmapandstate->bitmapplans = bitmapplanstates;
 
68
        bitmapandstate->nplans = nplans;
 
69
 
 
70
        /*
 
71
         * Miscellaneous initialization
 
72
         *
 
73
         * BitmapAnd plans don't have expression contexts because they never call
 
74
         * ExecQual or ExecProject.  They don't need any tuple slots either.
 
75
         */
 
76
 
 
77
        /*
 
78
         * call ExecInitNode on each of the plans to be executed and save the
 
79
         * results into the array "bitmapplanstates".
 
80
         */
 
81
        i = 0;
 
82
        foreach(l, node->bitmapplans)
 
83
        {
 
84
                initNode = (Plan *) lfirst(l);
 
85
                bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
 
86
                i++;
 
87
        }
 
88
 
 
89
        return bitmapandstate;
 
90
}
 
91
 
 
92
/* ----------------------------------------------------------------
 
93
 *         MultiExecBitmapAnd
 
94
 * ----------------------------------------------------------------
 
95
 */
 
96
Node *
 
97
MultiExecBitmapAnd(BitmapAndState *node)
 
98
{
 
99
        PlanState **bitmapplans;
 
100
        int                     nplans;
 
101
        int                     i;
 
102
        TIDBitmap  *result = NULL;
 
103
 
 
104
        /* must provide our own instrumentation support */
 
105
        if (node->ps.instrument)
 
106
                InstrStartNode(node->ps.instrument);
 
107
 
 
108
        /*
 
109
         * get information from the node
 
110
         */
 
111
        bitmapplans = node->bitmapplans;
 
112
        nplans = node->nplans;
 
113
 
 
114
        /*
 
115
         * Scan all the subplans and AND their result bitmaps
 
116
         */
 
117
        for (i = 0; i < nplans; i++)
 
118
        {
 
119
                PlanState  *subnode = bitmapplans[i];
 
120
                TIDBitmap  *subresult;
 
121
 
 
122
                subresult = (TIDBitmap *) MultiExecProcNode(subnode);
 
123
 
 
124
                if (!subresult || !IsA(subresult, TIDBitmap))
 
125
                        elog(ERROR, "unrecognized result from subplan");
 
126
 
 
127
                if (result == NULL)
 
128
                        result = subresult; /* first subplan */
 
129
                else
 
130
                {
 
131
                        tbm_intersect(result, subresult);
 
132
                        tbm_free(subresult);
 
133
                }
 
134
 
 
135
                /*
 
136
                 * If at any stage we have a completely empty bitmap, we can fall out
 
137
                 * without evaluating the remaining subplans, since ANDing them can no
 
138
                 * longer change the result.  (Note: the fact that indxpath.c orders
 
139
                 * the subplans by selectivity should make this case more likely to
 
140
                 * occur.)
 
141
                 */
 
142
                if (tbm_is_empty(result))
 
143
                        break;
 
144
        }
 
145
 
 
146
        if (result == NULL)
 
147
                elog(ERROR, "BitmapAnd doesn't support zero inputs");
 
148
 
 
149
        /* must provide our own instrumentation support */
 
150
        if (node->ps.instrument)
 
151
                InstrStopNode(node->ps.instrument, 0 /* XXX */ );
 
152
 
 
153
        return (Node *) result;
 
154
}
 
155
 
 
156
/* ----------------------------------------------------------------
 
157
 *              ExecEndBitmapAnd
 
158
 *
 
159
 *              Shuts down the subscans of the BitmapAnd node.
 
160
 *
 
161
 *              Returns nothing of interest.
 
162
 * ----------------------------------------------------------------
 
163
 */
 
164
void
 
165
ExecEndBitmapAnd(BitmapAndState *node)
 
166
{
 
167
        PlanState **bitmapplans;
 
168
        int                     nplans;
 
169
        int                     i;
 
170
 
 
171
        /*
 
172
         * get information from the node
 
173
         */
 
174
        bitmapplans = node->bitmapplans;
 
175
        nplans = node->nplans;
 
176
 
 
177
        /*
 
178
         * shut down each of the subscans (that we've initialized)
 
179
         */
 
180
        for (i = 0; i < nplans; i++)
 
181
        {
 
182
                if (bitmapplans[i])
 
183
                        ExecEndNode(bitmapplans[i]);
 
184
        }
 
185
}
 
186
 
 
187
void
 
188
ExecReScanBitmapAnd(BitmapAndState *node)
 
189
{
 
190
        int                     i;
 
191
 
 
192
        for (i = 0; i < node->nplans; i++)
 
193
        {
 
194
                PlanState  *subnode = node->bitmapplans[i];
 
195
 
 
196
                /*
 
197
                 * ExecReScan doesn't know about my subplans, so I have to do
 
198
                 * changed-parameter signaling myself.
 
199
                 */
 
200
                if (node->ps.chgParam != NULL)
 
201
                        UpdateChangedParamSet(subnode, node->ps.chgParam);
 
202
 
 
203
                /*
 
204
                 * If chgParam of subnode is not null then plan will be re-scanned by
 
205
                 * first ExecProcNode.
 
206
                 */
 
207
                if (subnode->chgParam == NULL)
 
208
                        ExecReScan(subnode);
 
209
        }
 
210
}