Fix xslt_process() to ensure that it inserts a NULL terminator after the
[PostgreSQL.git] / src / backend / executor / execJunk.c
blob564347ffd75c91fb58335ee554a44ba517345033
1 /*-------------------------------------------------------------------------
3 * execJunk.c
4 * Junk attribute support stuff....
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 #include "postgres.h"
17 #include "executor/executor.h"
19 /*-------------------------------------------------------------------------
20 * XXX this stuff should be rewritten to take advantage
21 * of ExecProject() and the ProjectionInfo node.
22 * -cim 6/3/91
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.
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
38 * and store the appropriate information in the es_junkFilter attribute of
39 * EState.
41 * We then execute the plan, treating the resjunk attributes like any others.
43 * Finally, when at the top level we get back a tuple, we can call
44 * ExecFindJunkAttribute/ExecGetJunkAttribute to retrieve the values of the
45 * junk attributes we are interested in, and ExecFilterJunk or ExecRemoveJunk
46 * to remove all the junk attributes from a tuple. This new "clean" tuple is
47 * then printed, replaced, deleted or inserted.
49 *-------------------------------------------------------------------------
53 * ExecInitJunkFilter
55 * Initialize the Junk filter.
57 * The source targetlist is passed in. The output tuple descriptor is
58 * built from the non-junk tlist entries, plus the passed specification
59 * of whether to include room for an OID or not.
60 * An optional resultSlot can be passed as well.
62 JunkFilter *
63 ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot)
65 JunkFilter *junkfilter;
66 TupleDesc cleanTupType;
67 int cleanLength;
68 AttrNumber *cleanMap;
69 ListCell *t;
70 AttrNumber cleanResno;
73 * Compute the tuple descriptor for the cleaned tuple.
75 cleanTupType = ExecCleanTypeFromTL(targetList, hasoid);
78 * Use the given slot, or make a new slot if we weren't given one.
80 if (slot)
81 ExecSetSlotDescriptor(slot, cleanTupType);
82 else
83 slot = MakeSingleTupleTableSlot(cleanTupType);
86 * Now calculate the mapping between the original tuple's attributes and
87 * the "clean" tuple's attributes.
89 * The "map" is an array of "cleanLength" attribute numbers, i.e. one
90 * entry for every attribute of the "clean" tuple. The value of this entry
91 * is the attribute number of the corresponding attribute of the
92 * "original" tuple. (Zero indicates a NULL output attribute, but we do
93 * not use that feature in this routine.)
95 cleanLength = cleanTupType->natts;
96 if (cleanLength > 0)
98 cleanMap = (AttrNumber *) palloc(cleanLength * sizeof(AttrNumber));
99 cleanResno = 1;
100 foreach(t, targetList)
102 TargetEntry *tle = lfirst(t);
104 if (!tle->resjunk)
106 cleanMap[cleanResno - 1] = tle->resno;
107 cleanResno++;
111 else
112 cleanMap = NULL;
115 * Finally create and initialize the JunkFilter struct.
117 junkfilter = makeNode(JunkFilter);
119 junkfilter->jf_targetList = targetList;
120 junkfilter->jf_cleanTupType = cleanTupType;
121 junkfilter->jf_cleanMap = cleanMap;
122 junkfilter->jf_resultSlot = slot;
124 return junkfilter;
128 * ExecInitJunkFilterConversion
130 * Initialize a JunkFilter for rowtype conversions.
132 * Here, we are given the target "clean" tuple descriptor rather than
133 * inferring it from the targetlist. The target descriptor can contain
134 * deleted columns. It is assumed that the caller has checked that the
135 * non-deleted columns match up with the non-junk columns of the targetlist.
137 JunkFilter *
138 ExecInitJunkFilterConversion(List *targetList,
139 TupleDesc cleanTupType,
140 TupleTableSlot *slot)
142 JunkFilter *junkfilter;
143 int cleanLength;
144 AttrNumber *cleanMap;
145 ListCell *t;
146 int i;
149 * Use the given slot, or make a new slot if we weren't given one.
151 if (slot)
152 ExecSetSlotDescriptor(slot, cleanTupType);
153 else
154 slot = MakeSingleTupleTableSlot(cleanTupType);
157 * Calculate the mapping between the original tuple's attributes and the
158 * "clean" tuple's attributes.
160 * The "map" is an array of "cleanLength" attribute numbers, i.e. one
161 * entry for every attribute of the "clean" tuple. The value of this entry
162 * is the attribute number of the corresponding attribute of the
163 * "original" tuple. We store zero for any deleted attributes, marking
164 * that a NULL is needed in the output tuple.
166 cleanLength = cleanTupType->natts;
167 if (cleanLength > 0)
169 cleanMap = (AttrNumber *) palloc0(cleanLength * sizeof(AttrNumber));
170 t = list_head(targetList);
171 for (i = 0; i < cleanLength; i++)
173 if (cleanTupType->attrs[i]->attisdropped)
174 continue; /* map entry is already zero */
175 for (;;)
177 TargetEntry *tle = lfirst(t);
179 t = lnext(t);
180 if (!tle->resjunk)
182 cleanMap[i] = tle->resno;
183 break;
188 else
189 cleanMap = NULL;
192 * Finally create and initialize the JunkFilter struct.
194 junkfilter = makeNode(JunkFilter);
196 junkfilter->jf_targetList = targetList;
197 junkfilter->jf_cleanTupType = cleanTupType;
198 junkfilter->jf_cleanMap = cleanMap;
199 junkfilter->jf_resultSlot = slot;
201 return junkfilter;
205 * ExecFindJunkAttribute
207 * Locate the specified junk attribute in the junk filter's targetlist,
208 * and return its resno. Returns InvalidAttrNumber if not found.
210 AttrNumber
211 ExecFindJunkAttribute(JunkFilter *junkfilter, const char *attrName)
213 ListCell *t;
215 foreach(t, junkfilter->jf_targetList)
217 TargetEntry *tle = lfirst(t);
219 if (tle->resjunk && tle->resname &&
220 (strcmp(tle->resname, attrName) == 0))
222 /* We found it ! */
223 return tle->resno;
227 return InvalidAttrNumber;
231 * ExecGetJunkAttribute
233 * Given a junk filter's input tuple (slot) and a junk attribute's number
234 * previously found by ExecFindJunkAttribute, extract & return the value and
235 * isNull flag of the attribute.
237 Datum
238 ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno,
239 bool *isNull)
241 Assert(attno > 0);
243 return slot_getattr(slot, attno, isNull);
247 * ExecFilterJunk
249 * Construct and return a slot with all the junk attributes removed.
251 TupleTableSlot *
252 ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
254 TupleTableSlot *resultSlot;
255 AttrNumber *cleanMap;
256 TupleDesc cleanTupType;
257 int cleanLength;
258 int i;
259 Datum *values;
260 bool *isnull;
261 Datum *old_values;
262 bool *old_isnull;
265 * Extract all the values of the old tuple.
267 slot_getallattrs(slot);
268 old_values = slot->tts_values;
269 old_isnull = slot->tts_isnull;
272 * get info from the junk filter
274 cleanTupType = junkfilter->jf_cleanTupType;
275 cleanLength = cleanTupType->natts;
276 cleanMap = junkfilter->jf_cleanMap;
277 resultSlot = junkfilter->jf_resultSlot;
280 * Prepare to build a virtual result tuple.
282 ExecClearTuple(resultSlot);
283 values = resultSlot->tts_values;
284 isnull = resultSlot->tts_isnull;
287 * Transpose data into proper fields of the new tuple.
289 for (i = 0; i < cleanLength; i++)
291 int j = cleanMap[i];
293 if (j == 0)
295 values[i] = (Datum) 0;
296 isnull[i] = true;
298 else
300 values[i] = old_values[j - 1];
301 isnull[i] = old_isnull[j - 1];
306 * And return the virtual tuple.
308 return ExecStoreVirtualTuple(resultSlot);
312 * ExecRemoveJunk
314 * Convenience routine to generate a physical clean tuple,
315 * rather than just a virtual slot.
317 HeapTuple
318 ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
320 return ExecCopySlotTuple(ExecFilterJunk(junkfilter, slot));