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

« back to all changes in this revision

Viewing changes to src/backend/executor/execJunk.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
 * execJunk.c
 
4
 *        Junk attribute support stuff....
 
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/execJunk.c
 
12
 *
 
13
 *-------------------------------------------------------------------------
 
14
 */
 
15
#include "postgres.h"
 
16
 
 
17
#include "executor/executor.h"
 
18
 
 
19
/*-------------------------------------------------------------------------
 
20
 *              XXX this stuff should be rewritten to take advantage
 
21
 *                      of ExecProject() and the ProjectionInfo node.
 
22
 *                      -cim 6/3/91
 
23
 *
 
24
 * An attribute of a tuple living inside the executor, can be
 
25
 * either a normal attribute or a "junk" attribute. "junk" attributes
 
26
 * never make it out of the executor, i.e. they are never printed,
 
27
 * returned or stored on disk. Their only purpose in life is to
 
28
 * store some information useful only to the executor, mainly the values
 
29
 * of system attributes like "ctid", or sort key columns that are not to
 
30
 * be output.
 
31
 *
 
32
 * The general idea is the following: A target list consists of a list of
 
33
 * TargetEntry nodes containing expressions. Each TargetEntry has a field
 
34
 * called 'resjunk'. If the value of this field is true then the
 
35
 * corresponding attribute is a "junk" attribute.
 
36
 *
 
37
 * When we initialize a plan we call ExecInitJunkFilter to create a filter.
 
38
 *
 
39
 * We then execute the plan, treating the resjunk attributes like any others.
 
40
 *
 
41
 * Finally, when at the top level we get back a tuple, we can call
 
42
 * ExecFindJunkAttribute/ExecGetJunkAttribute to retrieve the values of the
 
43
 * junk attributes we are interested in, and ExecFilterJunk to remove all the
 
44
 * junk attributes from a tuple.  This new "clean" tuple is then printed,
 
45
 * inserted, or updated.
 
46
 *
 
47
 *-------------------------------------------------------------------------
 
48
 */
 
49
 
 
50
/*
 
51
 * ExecInitJunkFilter
 
52
 *
 
53
 * Initialize the Junk filter.
 
54
 *
 
55
 * The source targetlist is passed in.  The output tuple descriptor is
 
56
 * built from the non-junk tlist entries, plus the passed specification
 
57
 * of whether to include room for an OID or not.
 
58
 * An optional resultSlot can be passed as well.
 
59
 */
 
60
JunkFilter *
 
61
ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot)
 
62
{
 
63
        JunkFilter *junkfilter;
 
64
        TupleDesc       cleanTupType;
 
65
        int                     cleanLength;
 
66
        AttrNumber *cleanMap;
 
67
        ListCell   *t;
 
68
        AttrNumber      cleanResno;
 
69
 
 
70
        /*
 
71
         * Compute the tuple descriptor for the cleaned tuple.
 
72
         */
 
73
        cleanTupType = ExecCleanTypeFromTL(targetList, hasoid);
 
74
 
 
75
        /*
 
76
         * Use the given slot, or make a new slot if we weren't given one.
 
77
         */
 
78
        if (slot)
 
79
                ExecSetSlotDescriptor(slot, cleanTupType);
 
80
        else
 
81
                slot = MakeSingleTupleTableSlot(cleanTupType);
 
82
 
 
83
        /*
 
84
         * Now calculate the mapping between the original tuple's attributes and
 
85
         * the "clean" tuple's attributes.
 
86
         *
 
87
         * The "map" is an array of "cleanLength" attribute numbers, i.e. one
 
88
         * entry for every attribute of the "clean" tuple. The value of this entry
 
89
         * is the attribute number of the corresponding attribute of the
 
90
         * "original" tuple.  (Zero indicates a NULL output attribute, but we do
 
91
         * not use that feature in this routine.)
 
92
         */
 
93
        cleanLength = cleanTupType->natts;
 
94
        if (cleanLength > 0)
 
95
        {
 
96
                cleanMap = (AttrNumber *) palloc(cleanLength * sizeof(AttrNumber));
 
97
                cleanResno = 1;
 
98
                foreach(t, targetList)
 
99
                {
 
100
                        TargetEntry *tle = lfirst(t);
 
101
 
 
102
                        if (!tle->resjunk)
 
103
                        {
 
104
                                cleanMap[cleanResno - 1] = tle->resno;
 
105
                                cleanResno++;
 
106
                        }
 
107
                }
 
108
        }
 
109
        else
 
110
                cleanMap = NULL;
 
111
 
 
112
        /*
 
113
         * Finally create and initialize the JunkFilter struct.
 
114
         */
 
115
        junkfilter = makeNode(JunkFilter);
 
116
 
 
117
        junkfilter->jf_targetList = targetList;
 
118
        junkfilter->jf_cleanTupType = cleanTupType;
 
119
        junkfilter->jf_cleanMap = cleanMap;
 
120
        junkfilter->jf_resultSlot = slot;
 
121
 
 
122
        return junkfilter;
 
123
}
 
124
 
 
125
/*
 
126
 * ExecInitJunkFilterConversion
 
127
 *
 
128
 * Initialize a JunkFilter for rowtype conversions.
 
129
 *
 
130
 * Here, we are given the target "clean" tuple descriptor rather than
 
131
 * inferring it from the targetlist.  The target descriptor can contain
 
132
 * deleted columns.  It is assumed that the caller has checked that the
 
133
 * non-deleted columns match up with the non-junk columns of the targetlist.
 
134
 */
 
135
JunkFilter *
 
136
ExecInitJunkFilterConversion(List *targetList,
 
137
                                                         TupleDesc cleanTupType,
 
138
                                                         TupleTableSlot *slot)
 
139
{
 
140
        JunkFilter *junkfilter;
 
141
        int                     cleanLength;
 
142
        AttrNumber *cleanMap;
 
143
        ListCell   *t;
 
144
        int                     i;
 
145
 
 
146
        /*
 
147
         * Use the given slot, or make a new slot if we weren't given one.
 
148
         */
 
149
        if (slot)
 
150
                ExecSetSlotDescriptor(slot, cleanTupType);
 
151
        else
 
152
                slot = MakeSingleTupleTableSlot(cleanTupType);
 
153
 
 
154
        /*
 
155
         * Calculate the mapping between the original tuple's attributes and the
 
156
         * "clean" tuple's attributes.
 
157
         *
 
158
         * The "map" is an array of "cleanLength" attribute numbers, i.e. one
 
159
         * entry for every attribute of the "clean" tuple. The value of this entry
 
160
         * is the attribute number of the corresponding attribute of the
 
161
         * "original" tuple.  We store zero for any deleted attributes, marking
 
162
         * that a NULL is needed in the output tuple.
 
163
         */
 
164
        cleanLength = cleanTupType->natts;
 
165
        if (cleanLength > 0)
 
166
        {
 
167
                cleanMap = (AttrNumber *) palloc0(cleanLength * sizeof(AttrNumber));
 
168
                t = list_head(targetList);
 
169
                for (i = 0; i < cleanLength; i++)
 
170
                {
 
171
                        if (cleanTupType->attrs[i]->attisdropped)
 
172
                                continue;               /* map entry is already zero */
 
173
                        for (;;)
 
174
                        {
 
175
                                TargetEntry *tle = lfirst(t);
 
176
 
 
177
                                t = lnext(t);
 
178
                                if (!tle->resjunk)
 
179
                                {
 
180
                                        cleanMap[i] = tle->resno;
 
181
                                        break;
 
182
                                }
 
183
                        }
 
184
                }
 
185
        }
 
186
        else
 
187
                cleanMap = NULL;
 
188
 
 
189
        /*
 
190
         * Finally create and initialize the JunkFilter struct.
 
191
         */
 
192
        junkfilter = makeNode(JunkFilter);
 
193
 
 
194
        junkfilter->jf_targetList = targetList;
 
195
        junkfilter->jf_cleanTupType = cleanTupType;
 
196
        junkfilter->jf_cleanMap = cleanMap;
 
197
        junkfilter->jf_resultSlot = slot;
 
198
 
 
199
        return junkfilter;
 
200
}
 
201
 
 
202
/*
 
203
 * ExecFindJunkAttribute
 
204
 *
 
205
 * Locate the specified junk attribute in the junk filter's targetlist,
 
206
 * and return its resno.  Returns InvalidAttrNumber if not found.
 
207
 */
 
208
AttrNumber
 
209
ExecFindJunkAttribute(JunkFilter *junkfilter, const char *attrName)
 
210
{
 
211
        return ExecFindJunkAttributeInTlist(junkfilter->jf_targetList, attrName);
 
212
}
 
213
 
 
214
/*
 
215
 * ExecFindJunkAttributeInTlist
 
216
 *
 
217
 * Find a junk attribute given a subplan's targetlist (not necessarily
 
218
 * part of a JunkFilter).
 
219
 */
 
220
AttrNumber
 
221
ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
 
222
{
 
223
        ListCell   *t;
 
224
 
 
225
        foreach(t, targetlist)
 
226
        {
 
227
                TargetEntry *tle = lfirst(t);
 
228
 
 
229
                if (tle->resjunk && tle->resname &&
 
230
                        (strcmp(tle->resname, attrName) == 0))
 
231
                {
 
232
                        /* We found it ! */
 
233
                        return tle->resno;
 
234
                }
 
235
        }
 
236
 
 
237
        return InvalidAttrNumber;
 
238
}
 
239
 
 
240
/*
 
241
 * ExecGetJunkAttribute
 
242
 *
 
243
 * Given a junk filter's input tuple (slot) and a junk attribute's number
 
244
 * previously found by ExecFindJunkAttribute, extract & return the value and
 
245
 * isNull flag of the attribute.
 
246
 */
 
247
Datum
 
248
ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno,
 
249
                                         bool *isNull)
 
250
{
 
251
        Assert(attno > 0);
 
252
 
 
253
        return slot_getattr(slot, attno, isNull);
 
254
}
 
255
 
 
256
/*
 
257
 * ExecFilterJunk
 
258
 *
 
259
 * Construct and return a slot with all the junk attributes removed.
 
260
 */
 
261
TupleTableSlot *
 
262
ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
 
263
{
 
264
        TupleTableSlot *resultSlot;
 
265
        AttrNumber *cleanMap;
 
266
        TupleDesc       cleanTupType;
 
267
        int                     cleanLength;
 
268
        int                     i;
 
269
        Datum      *values;
 
270
        bool       *isnull;
 
271
        Datum      *old_values;
 
272
        bool       *old_isnull;
 
273
 
 
274
        /*
 
275
         * Extract all the values of the old tuple.
 
276
         */
 
277
        slot_getallattrs(slot);
 
278
        old_values = slot->tts_values;
 
279
        old_isnull = slot->tts_isnull;
 
280
 
 
281
        /*
 
282
         * get info from the junk filter
 
283
         */
 
284
        cleanTupType = junkfilter->jf_cleanTupType;
 
285
        cleanLength = cleanTupType->natts;
 
286
        cleanMap = junkfilter->jf_cleanMap;
 
287
        resultSlot = junkfilter->jf_resultSlot;
 
288
 
 
289
        /*
 
290
         * Prepare to build a virtual result tuple.
 
291
         */
 
292
        ExecClearTuple(resultSlot);
 
293
        values = resultSlot->tts_values;
 
294
        isnull = resultSlot->tts_isnull;
 
295
 
 
296
        /*
 
297
         * Transpose data into proper fields of the new tuple.
 
298
         */
 
299
        for (i = 0; i < cleanLength; i++)
 
300
        {
 
301
                int                     j = cleanMap[i];
 
302
 
 
303
                if (j == 0)
 
304
                {
 
305
                        values[i] = (Datum) 0;
 
306
                        isnull[i] = true;
 
307
                }
 
308
                else
 
309
                {
 
310
                        values[i] = old_values[j - 1];
 
311
                        isnull[i] = old_isnull[j - 1];
 
312
                }
 
313
        }
 
314
 
 
315
        /*
 
316
         * And return the virtual tuple.
 
317
         */
 
318
        return ExecStoreVirtualTuple(resultSlot);
 
319
}