diff options
Diffstat (limited to 'src/backend/executor/execJunk.c')
-rw-r--r-- | src/backend/executor/execJunk.c | 638 |
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); +} |