aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execJunk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execJunk.c')
-rw-r--r--src/backend/executor/execJunk.c638
1 files changed, 334 insertions, 304 deletions
diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c
index 8779647a113..3ad41bd393f 100644
--- a/src/backend/executor/execJunk.c
+++ b/src/backend/executor/execJunk.c
@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* junk.c--
- * Junk attribute support stuff....
+ * Junk attribute support stuff....
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.5 1997/08/26 23:31:37 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.6 1997/09/07 04:41:14 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,37 +20,37 @@
#include "access/heapam.h"
#include "executor/executor.h"
#include "nodes/relation.h"
-#include "optimizer/tlist.h" /* for MakeTLE */
+#include "optimizer/tlist.h" /* for MakeTLE */
/*-------------------------------------------------------------------------
- * XXX this stuff should be rewritten to take advantage
- * of ExecProject() and the ProjectionInfo node.
- * -cim 6/3/91
- *
+ * XXX this stuff should be rewritten to take advantage
+ * of ExecProject() and the ProjectionInfo node.
+ * -cim 6/3/91
+ *
* An attribute of a tuple living inside the executor, can be
* either a normal attribute or a "junk" attribute. "junk" attributes
* never make it out of the executor, i.e. they are never printed,
* returned or stored in disk. Their only purpose in life is to
* store some information useful only to the executor, mainly the values
* of some system attributes like "ctid" or rule locks.
- *
+ *
* The general idea is the following: A target list consists of a list of
* Resdom nodes & expression pairs. Each Resdom node has an attribute
* called 'resjunk'. If the value of this attribute is 1 then the
* corresponding attribute is a "junk" attribute.
- *
+ *
* When we initialize a plan we call 'ExecInitJunkFilter' to create
* and store the appropriate information in the 'es_junkFilter' attribute of
* EState.
- *
+ *
* We then execute the plan ignoring the "resjunk" attributes.
- *
+ *
* Finally, when at the top level we get back a tuple, we can call
* 'ExecGetJunkAttribute' to retrieve the value of the junk attributes we
* are interested in, and 'ExecRemoveJunk' to remove all the junk attributes
* from a tuple. This new "clean" tuple is then printed, replaced, deleted
* or inserted.
- *
+ *
*-------------------------------------------------------------------------
*/
@@ -60,174 +60,196 @@
* Initialize the Junk filter.
*-------------------------------------------------------------------------
*/
-JunkFilter *
-ExecInitJunkFilter(List *targetList)
+JunkFilter *
+ExecInitJunkFilter(List * targetList)
{
- JunkFilter *junkfilter;
- List *cleanTargetList;
- int len, cleanLength;
- TupleDesc tupType, cleanTupType;
- List *t;
- TargetEntry *tle;
- Resdom *resdom, *cleanResdom;
- int resjunk;
- AttrNumber cleanResno;
- AttrNumber *cleanMap;
- Size size;
- Node *expr;
-
- /* ---------------------
- * First find the "clean" target list, i.e. all the entries
- * in the original target list which have a zero 'resjunk'
- * NOTE: make copy of the Resdom nodes, because we have
- * to change the 'resno's...
- * ---------------------
- */
- cleanTargetList = NIL;
- cleanResno = 1;
-
- foreach (t, targetList) {
- TargetEntry *rtarget = lfirst(t);
- if (rtarget->resdom != NULL) {
- resdom = rtarget->resdom;
- expr = rtarget->expr;
- resjunk = resdom->resjunk;
- if (resjunk == 0) {
- /*
- * make a copy of the resdom node, changing its resno.
- */
- cleanResdom = (Resdom *) copyObject(resdom);
- cleanResdom->resno = cleanResno;
- cleanResno ++;
- /*
- * create a new target list entry
- */
- tle = makeNode(TargetEntry);
- tle->resdom = cleanResdom;
- tle->expr = expr;
- cleanTargetList = lappend(cleanTargetList, tle);
- }
- }
- else {
+ JunkFilter *junkfilter;
+ List *cleanTargetList;
+ int len,
+ cleanLength;
+ TupleDesc tupType,
+ cleanTupType;
+ List *t;
+ TargetEntry *tle;
+ Resdom *resdom,
+ *cleanResdom;
+ int resjunk;
+ AttrNumber cleanResno;
+ AttrNumber *cleanMap;
+ Size size;
+ Node *expr;
+
+ /* ---------------------
+ * First find the "clean" target list, i.e. all the entries
+ * in the original target list which have a zero 'resjunk'
+ * NOTE: make copy of the Resdom nodes, because we have
+ * to change the 'resno's...
+ * ---------------------
+ */
+ cleanTargetList = NIL;
+ cleanResno = 1;
+
+ foreach(t, targetList)
+ {
+ TargetEntry *rtarget = lfirst(t);
+
+ if (rtarget->resdom != NULL)
+ {
+ resdom = rtarget->resdom;
+ expr = rtarget->expr;
+ resjunk = resdom->resjunk;
+ if (resjunk == 0)
+ {
+
+ /*
+ * make a copy of the resdom node, changing its resno.
+ */
+ cleanResdom = (Resdom *) copyObject(resdom);
+ cleanResdom->resno = cleanResno;
+ cleanResno++;
+
+ /*
+ * create a new target list entry
+ */
+ tle = makeNode(TargetEntry);
+ tle->resdom = cleanResdom;
+ tle->expr = expr;
+ cleanTargetList = lappend(cleanTargetList, tle);
+ }
+ }
+ else
+ {
#ifdef SETS_FIXED
- List *fjListP;
- Fjoin *cleanFjoin;
- List *cleanFjList;
- List *fjList = lfirst(t);
- Fjoin *fjNode = (Fjoin *)tl_node(fjList);
-
- cleanFjoin = (Fjoin)copyObject((Node) fjNode);
- cleanFjList = lcons(cleanFjoin, NIL);
-
- resdom = (Resdom) lfirst(get_fj_innerNode(fjNode));
- expr = lsecond(get_fj_innerNode(fjNode));
- cleanResdom = (Resdom) copyObject((Node) resdom);
- set_resno(cleanResdom, cleanResno);
- cleanResno++;
- tle = (List) MakeTLE(cleanResdom, (Expr) expr);
- set_fj_innerNode(cleanFjoin, tle);
-
- foreach(fjListP, lnext(fjList)) {
- TargetEntry *tle = lfirst(fjListP);
-
- resdom = tle->resdom;
- expr = tle->expr;
- cleanResdom = (Resdom*) copyObject((Node) resdom);
- cleanResno++;
- cleanResdom->Resno = cleanResno;
- /*
- * create a new target list entry
- */
- tle = (List) MakeTLE(cleanResdom, (Expr) expr);
- cleanFjList = lappend(cleanFjList, tle);
- }
- lappend(cleanTargetList, cleanFjList);
+ List *fjListP;
+ Fjoin *cleanFjoin;
+ List *cleanFjList;
+ List *fjList = lfirst(t);
+ Fjoin *fjNode = (Fjoin *) tl_node(fjList);
+
+ cleanFjoin = (Fjoin) copyObject((Node) fjNode);
+ cleanFjList = lcons(cleanFjoin, NIL);
+
+ resdom = (Resdom) lfirst(get_fj_innerNode(fjNode));
+ expr = lsecond(get_fj_innerNode(fjNode));
+ cleanResdom = (Resdom) copyObject((Node) resdom);
+ set_resno(cleanResdom, cleanResno);
+ cleanResno++;
+ tle = (List) MakeTLE(cleanResdom, (Expr) expr);
+ set_fj_innerNode(cleanFjoin, tle);
+
+ foreach(fjListP, lnext(fjList))
+ {
+ TargetEntry *tle = lfirst(fjListP);
+
+ resdom = tle->resdom;
+ expr = tle->expr;
+ cleanResdom = (Resdom *) copyObject((Node) resdom);
+ cleanResno++;
+ cleanResdom->Resno = cleanResno;
+
+ /*
+ * create a new target list entry
+ */
+ tle = (List) MakeTLE(cleanResdom, (Expr) expr);
+ cleanFjList = lappend(cleanFjList, tle);
+ }
+ lappend(cleanTargetList, cleanFjList);
#endif
- }
- }
-
- /* ---------------------
- * Now calculate the tuple types for the original and the clean tuple
- *
- * XXX ExecTypeFromTL should be used sparingly. Don't we already
- * have the tupType corresponding to the targetlist we are passed?
- * -cim 5/31/91
- * ---------------------
- */
- tupType = (TupleDesc) ExecTypeFromTL(targetList);
- cleanTupType = (TupleDesc) ExecTypeFromTL(cleanTargetList);
-
- len = ExecTargetListLength(targetList);
- cleanLength = ExecTargetListLength(cleanTargetList);
-
- /* ---------------------
- * Now calculate the "map" between the original tuples attributes
- * and the "clean" tuple's attributes.
- *
- * The "map" is an array of "cleanLength" attribute numbers, i.e.
- * one entry for every attribute of the "clean" tuple.
- * The value of this entry is the attribute number of the corresponding
- * attribute of the "original" tuple.
- * ---------------------
- */
- if (cleanLength > 0) {
- size = cleanLength * sizeof(AttrNumber);
- cleanMap = (AttrNumber*) palloc(size);
- cleanResno = 1;
- foreach (t, targetList) {
- TargetEntry *tle = lfirst(t);
- if (tle->resdom != NULL) {
- resdom = tle->resdom;
- expr = tle->expr;
- resjunk = resdom->resjunk;
- if (resjunk == 0) {
- cleanMap[cleanResno-1] = resdom->resno;
- cleanResno ++;
}
- } else {
+ }
+
+ /* ---------------------
+ * Now calculate the tuple types for the original and the clean tuple
+ *
+ * XXX ExecTypeFromTL should be used sparingly. Don't we already
+ * have the tupType corresponding to the targetlist we are passed?
+ * -cim 5/31/91
+ * ---------------------
+ */
+ tupType = (TupleDesc) ExecTypeFromTL(targetList);
+ cleanTupType = (TupleDesc) ExecTypeFromTL(cleanTargetList);
+
+ len = ExecTargetListLength(targetList);
+ cleanLength = ExecTargetListLength(cleanTargetList);
+
+ /* ---------------------
+ * Now calculate the "map" between the original tuples attributes
+ * and the "clean" tuple's attributes.
+ *
+ * The "map" is an array of "cleanLength" attribute numbers, i.e.
+ * one entry for every attribute of the "clean" tuple.
+ * The value of this entry is the attribute number of the corresponding
+ * attribute of the "original" tuple.
+ * ---------------------
+ */
+ if (cleanLength > 0)
+ {
+ size = cleanLength * sizeof(AttrNumber);
+ cleanMap = (AttrNumber *) palloc(size);
+ cleanResno = 1;
+ foreach(t, targetList)
+ {
+ TargetEntry *tle = lfirst(t);
+
+ if (tle->resdom != NULL)
+ {
+ resdom = tle->resdom;
+ expr = tle->expr;
+ resjunk = resdom->resjunk;
+ if (resjunk == 0)
+ {
+ cleanMap[cleanResno - 1] = resdom->resno;
+ cleanResno++;
+ }
+ }
+ else
+ {
#ifdef SETS_FIXED
- List fjListP;
- List fjList = lfirst(t);
- Fjoin fjNode = (Fjoin)lfirst(fjList);
+ List fjListP;
+ List fjList = lfirst(t);
+ Fjoin fjNode = (Fjoin) lfirst(fjList);
- /* what the hell is this????? */
- resdom = (Resdom) lfirst(get_fj_innerNode(fjNode));
+ /* what the hell is this????? */
+ resdom = (Resdom) lfirst(get_fj_innerNode(fjNode));
#endif
- cleanMap[cleanResno-1] = tle->resdom->resno;
- cleanResno++;
+ cleanMap[cleanResno - 1] = tle->resdom->resno;
+ cleanResno++;
#ifdef SETS_FIXED
- foreach(fjListP, lnext(fjList)) {
- TargetEntry *tle = lfirst(fjListP);
+ foreach(fjListP, lnext(fjList))
+ {
+ TargetEntry *tle = lfirst(fjListP);
- resdom = tle->resdom;
- cleanMap[cleanResno-1] = resdom->resno;
- cleanResno++;
- }
+ resdom = tle->resdom;
+ cleanMap[cleanResno - 1] = resdom->resno;
+ cleanResno++;
+ }
#endif
- }
+ }
+ }
+ }
+ else
+ {
+ cleanMap = NULL;
}
- } else {
- cleanMap = NULL;
- }
-
- /* ---------------------
- * Finally create and initialize the JunkFilter.
- * ---------------------
- */
- junkfilter = makeNode(JunkFilter);
-
- junkfilter->jf_targetList = targetList;
- junkfilter->jf_length = len;
- junkfilter->jf_tupType = tupType;
- junkfilter->jf_cleanTargetList = cleanTargetList;
- junkfilter->jf_cleanLength = cleanLength;
- junkfilter->jf_cleanTupType = cleanTupType;
- junkfilter->jf_cleanMap = cleanMap;
-
- return(junkfilter);
-
+
+ /* ---------------------
+ * Finally create and initialize the JunkFilter.
+ * ---------------------
+ */
+ junkfilter = makeNode(JunkFilter);
+
+ junkfilter->jf_targetList = targetList;
+ junkfilter->jf_length = len;
+ junkfilter->jf_tupType = tupType;
+ junkfilter->jf_cleanTargetList = cleanTargetList;
+ junkfilter->jf_cleanLength = cleanLength;
+ junkfilter->jf_cleanTupType = cleanTupType;
+ junkfilter->jf_cleanMap = cleanMap;
+
+ return (junkfilter);
+
}
/*-------------------------------------------------------------------------
@@ -242,57 +264,61 @@ ExecInitJunkFilter(List *targetList)
*-------------------------------------------------------------------------
*/
bool
-ExecGetJunkAttribute(JunkFilter *junkfilter,
- TupleTableSlot *slot,
- char *attrName,
- Datum *value,
- bool *isNull)
+ExecGetJunkAttribute(JunkFilter * junkfilter,
+ TupleTableSlot * slot,
+ char *attrName,
+ Datum * value,
+ bool * isNull)
{
- List *targetList;
- List *t;
- Resdom *resdom;
- AttrNumber resno;
- char *resname;
- int resjunk;
- TupleDesc tupType;
- HeapTuple tuple;
-
- /* ---------------------
- * first look in the junkfilter's target list for
- * an attribute with the given name
- * ---------------------
- */
- resno = InvalidAttrNumber;
- targetList = junkfilter->jf_targetList;
-
- foreach (t, targetList) {
- TargetEntry *tle = lfirst(t);
- resdom = tle->resdom;
- resname = resdom->resname;
- resjunk = resdom->resjunk;
- if (resjunk != 0 && (strcmp(resname, attrName) == 0)) {
- /* We found it ! */
- resno = resdom->resno;
- break;
+ List *targetList;
+ List *t;
+ Resdom *resdom;
+ AttrNumber resno;
+ char *resname;
+ int resjunk;
+ TupleDesc tupType;
+ HeapTuple tuple;
+
+ /* ---------------------
+ * first look in the junkfilter's target list for
+ * an attribute with the given name
+ * ---------------------
+ */
+ resno = InvalidAttrNumber;
+ targetList = junkfilter->jf_targetList;
+
+ foreach(t, targetList)
+ {
+ TargetEntry *tle = lfirst(t);
+
+ resdom = tle->resdom;
+ resname = resdom->resname;
+ resjunk = resdom->resjunk;
+ if (resjunk != 0 && (strcmp(resname, attrName) == 0))
+ {
+ /* We found it ! */
+ resno = resdom->resno;
+ break;
+ }
+ }
+
+ if (resno == InvalidAttrNumber)
+ {
+ /* Ooops! We couldn't find this attribute... */
+ return (false);
}
- }
-
- if (resno == InvalidAttrNumber) {
- /* Ooops! We couldn't find this attribute... */
- return(false);
- }
-
- /* ---------------------
- * Now extract the attribute value from the tuple.
- * ---------------------
- */
- tuple = slot->val;
- tupType = (TupleDesc) junkfilter->jf_tupType;
-
- *value = (Datum)
- heap_getattr(tuple, InvalidBuffer, resno, tupType, isNull);
-
- return true;
+
+ /* ---------------------
+ * Now extract the attribute value from the tuple.
+ * ---------------------
+ */
+ tuple = slot->val;
+ tupType = (TupleDesc) junkfilter->jf_tupType;
+
+ *value = (Datum)
+ heap_getattr(tuple, InvalidBuffer, resno, tupType, isNull);
+
+ return true;
}
/*-------------------------------------------------------------------------
@@ -302,94 +328,98 @@ ExecGetJunkAttribute(JunkFilter *junkfilter,
*-------------------------------------------------------------------------
*/
HeapTuple
-ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
+ExecRemoveJunk(JunkFilter * junkfilter, TupleTableSlot * slot)
{
- HeapTuple tuple;
- HeapTuple cleanTuple;
- AttrNumber *cleanMap;
- TupleDesc cleanTupType;
- TupleDesc tupType;
- int cleanLength;
- bool isNull;
- int i;
- Size size;
- Datum *values;
- char *nulls;
- Datum values_array[64];
- char nulls_array[64];
-
- /* ----------------
- * get info from the slot and the junk filter
- * ----------------
- */
- tuple = slot->val;
-
- tupType = (TupleDesc) junkfilter->jf_tupType;
- cleanTupType = (TupleDesc) junkfilter->jf_cleanTupType;
- cleanLength = junkfilter->jf_cleanLength;
- cleanMap = junkfilter->jf_cleanMap;
-
- /* ---------------------
- * Handle the trivial case first.
- * ---------------------
- */
- if (cleanLength == 0)
- return (HeapTuple) NULL;
-
- /* ---------------------
- * Create the arrays that will hold the attribute values
- * and the null information for the new "clean" tuple.
- *
- * Note: we use memory on the stack to optimize things when
- * we are dealing with a small number of tuples.
- * for large tuples we just use palloc.
- * ---------------------
- */
- if (cleanLength > 64) {
- size = cleanLength * sizeof(Datum);
- values = (Datum *) palloc(size);
-
- size = cleanLength * sizeof(char);
- nulls = (char *) palloc(size);
- } else {
- values = values_array;
- nulls = nulls_array;
- }
-
- /* ---------------------
- * Exctract one by one all the values of the "clean" tuple.
- * ---------------------
- */
- for (i=0; i<cleanLength; i++) {
- Datum d = (Datum)
- heap_getattr(tuple, InvalidBuffer, cleanMap[i], tupType, &isNull);
-
- values[i] = d;
-
- if (isNull)
- nulls[i] = 'n';
+ HeapTuple tuple;
+ HeapTuple cleanTuple;
+ AttrNumber *cleanMap;
+ TupleDesc cleanTupType;
+ TupleDesc tupType;
+ int cleanLength;
+ bool isNull;
+ int i;
+ Size size;
+ Datum *values;
+ char *nulls;
+ Datum values_array[64];
+ char nulls_array[64];
+
+ /* ----------------
+ * get info from the slot and the junk filter
+ * ----------------
+ */
+ tuple = slot->val;
+
+ tupType = (TupleDesc) junkfilter->jf_tupType;
+ cleanTupType = (TupleDesc) junkfilter->jf_cleanTupType;
+ cleanLength = junkfilter->jf_cleanLength;
+ cleanMap = junkfilter->jf_cleanMap;
+
+ /* ---------------------
+ * Handle the trivial case first.
+ * ---------------------
+ */
+ if (cleanLength == 0)
+ return (HeapTuple) NULL;
+
+ /* ---------------------
+ * Create the arrays that will hold the attribute values
+ * and the null information for the new "clean" tuple.
+ *
+ * Note: we use memory on the stack to optimize things when
+ * we are dealing with a small number of tuples.
+ * for large tuples we just use palloc.
+ * ---------------------
+ */
+ if (cleanLength > 64)
+ {
+ size = cleanLength * sizeof(Datum);
+ values = (Datum *) palloc(size);
+
+ size = cleanLength * sizeof(char);
+ nulls = (char *) palloc(size);
+ }
else
- nulls[i] = ' ';
- }
-
- /* ---------------------
- * Now form the new tuple.
- * ---------------------
- */
- cleanTuple = heap_formtuple(cleanTupType,
- values,
- nulls);
-
- /* ---------------------
- * We are done. Free any space allocated for 'values' and 'nulls'
- * and return the new tuple.
- * ---------------------
- */
- if (cleanLength > 64) {
- pfree(values);
- pfree(nulls);
- }
-
- return(cleanTuple);
-}
+ {
+ values = values_array;
+ nulls = nulls_array;
+ }
+
+ /* ---------------------
+ * Exctract one by one all the values of the "clean" tuple.
+ * ---------------------
+ */
+ for (i = 0; i < cleanLength; i++)
+ {
+ Datum d = (Datum)
+ heap_getattr(tuple, InvalidBuffer, cleanMap[i], tupType, &isNull);
+ values[i] = d;
+
+ if (isNull)
+ nulls[i] = 'n';
+ else
+ nulls[i] = ' ';
+ }
+
+ /* ---------------------
+ * Now form the new tuple.
+ * ---------------------
+ */
+ cleanTuple = heap_formtuple(cleanTupType,
+ values,
+ nulls);
+
+ /* ---------------------
+ * We are done. Free any space allocated for 'values' and 'nulls'
+ * and return the new tuple.
+ * ---------------------
+ */
+ if (cleanLength > 64)
+ {
+ pfree(values);
+ pfree(nulls);
+ }
+
+ return (cleanTuple);
+}