1
/*-------------------------------------------------------------------------
4
* Junk attribute support stuff....
6
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
7
* Portions Copyright (c) 1994, Regents of the University of California
11
* src/backend/executor/execJunk.c
13
*-------------------------------------------------------------------------
17
#include "executor/executor.h"
19
/*-------------------------------------------------------------------------
20
* XXX this stuff should be rewritten to take advantage
21
* of ExecProject() and the ProjectionInfo node.
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
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.
37
* When we initialize a plan we call ExecInitJunkFilter to create a filter.
39
* We then execute the plan, treating the resjunk attributes like any others.
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.
47
*-------------------------------------------------------------------------
53
* Initialize the Junk filter.
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.
61
ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot)
63
JunkFilter *junkfilter;
64
TupleDesc cleanTupType;
68
AttrNumber cleanResno;
71
* Compute the tuple descriptor for the cleaned tuple.
73
cleanTupType = ExecCleanTypeFromTL(targetList, hasoid);
76
* Use the given slot, or make a new slot if we weren't given one.
79
ExecSetSlotDescriptor(slot, cleanTupType);
81
slot = MakeSingleTupleTableSlot(cleanTupType);
84
* Now calculate the mapping between the original tuple's attributes and
85
* the "clean" tuple's attributes.
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.)
93
cleanLength = cleanTupType->natts;
96
cleanMap = (AttrNumber *) palloc(cleanLength * sizeof(AttrNumber));
98
foreach(t, targetList)
100
TargetEntry *tle = lfirst(t);
104
cleanMap[cleanResno - 1] = tle->resno;
113
* Finally create and initialize the JunkFilter struct.
115
junkfilter = makeNode(JunkFilter);
117
junkfilter->jf_targetList = targetList;
118
junkfilter->jf_cleanTupType = cleanTupType;
119
junkfilter->jf_cleanMap = cleanMap;
120
junkfilter->jf_resultSlot = slot;
126
* ExecInitJunkFilterConversion
128
* Initialize a JunkFilter for rowtype conversions.
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.
136
ExecInitJunkFilterConversion(List *targetList,
137
TupleDesc cleanTupType,
138
TupleTableSlot *slot)
140
JunkFilter *junkfilter;
142
AttrNumber *cleanMap;
147
* Use the given slot, or make a new slot if we weren't given one.
150
ExecSetSlotDescriptor(slot, cleanTupType);
152
slot = MakeSingleTupleTableSlot(cleanTupType);
155
* Calculate the mapping between the original tuple's attributes and the
156
* "clean" tuple's attributes.
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.
164
cleanLength = cleanTupType->natts;
167
cleanMap = (AttrNumber *) palloc0(cleanLength * sizeof(AttrNumber));
168
t = list_head(targetList);
169
for (i = 0; i < cleanLength; i++)
171
if (cleanTupType->attrs[i]->attisdropped)
172
continue; /* map entry is already zero */
175
TargetEntry *tle = lfirst(t);
180
cleanMap[i] = tle->resno;
190
* Finally create and initialize the JunkFilter struct.
192
junkfilter = makeNode(JunkFilter);
194
junkfilter->jf_targetList = targetList;
195
junkfilter->jf_cleanTupType = cleanTupType;
196
junkfilter->jf_cleanMap = cleanMap;
197
junkfilter->jf_resultSlot = slot;
203
* ExecFindJunkAttribute
205
* Locate the specified junk attribute in the junk filter's targetlist,
206
* and return its resno. Returns InvalidAttrNumber if not found.
209
ExecFindJunkAttribute(JunkFilter *junkfilter, const char *attrName)
211
return ExecFindJunkAttributeInTlist(junkfilter->jf_targetList, attrName);
215
* ExecFindJunkAttributeInTlist
217
* Find a junk attribute given a subplan's targetlist (not necessarily
218
* part of a JunkFilter).
221
ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
225
foreach(t, targetlist)
227
TargetEntry *tle = lfirst(t);
229
if (tle->resjunk && tle->resname &&
230
(strcmp(tle->resname, attrName) == 0))
237
return InvalidAttrNumber;
241
* ExecGetJunkAttribute
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.
248
ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno,
253
return slot_getattr(slot, attno, isNull);
259
* Construct and return a slot with all the junk attributes removed.
262
ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
264
TupleTableSlot *resultSlot;
265
AttrNumber *cleanMap;
266
TupleDesc cleanTupType;
275
* Extract all the values of the old tuple.
277
slot_getallattrs(slot);
278
old_values = slot->tts_values;
279
old_isnull = slot->tts_isnull;
282
* get info from the junk filter
284
cleanTupType = junkfilter->jf_cleanTupType;
285
cleanLength = cleanTupType->natts;
286
cleanMap = junkfilter->jf_cleanMap;
287
resultSlot = junkfilter->jf_resultSlot;
290
* Prepare to build a virtual result tuple.
292
ExecClearTuple(resultSlot);
293
values = resultSlot->tts_values;
294
isnull = resultSlot->tts_isnull;
297
* Transpose data into proper fields of the new tuple.
299
for (i = 0; i < cleanLength; i++)
305
values[i] = (Datum) 0;
310
values[i] = old_values[j - 1];
311
isnull[i] = old_isnull[j - 1];
316
* And return the virtual tuple.
318
return ExecStoreVirtualTuple(resultSlot);