Skip to content
Snippets Groups Projects
Select Git revision
  • benchmark-tools
  • postgres-lambda
  • master default
  • REL9_4_25
  • REL9_5_20
  • REL9_6_16
  • REL_10_11
  • REL_11_6
  • REL_12_1
  • REL_12_0
  • REL_12_RC1
  • REL_12_BETA4
  • REL9_4_24
  • REL9_5_19
  • REL9_6_15
  • REL_10_10
  • REL_11_5
  • REL_12_BETA3
  • REL9_4_23
  • REL9_5_18
  • REL9_6_14
  • REL_10_9
  • REL_11_4
23 results

execJunk.c

Blame
    • Tom Lane's avatar
      e64c7feb
      Tweak default memory context allocation policy so that a context is not · e64c7feb
      Tom Lane authored
      given any malloc block until something is first allocated in it; but
      thereafter, MemoryContextReset won't release that first malloc block.
      This preserves the quick-reset property of the original policy, without
      forcing 8K to be allocated to every context whether any of it is ever
      used or not.  Also, remove some more no-longer-needed explicit freeing
      during ExecEndPlan.
      e64c7feb
      History
      Tweak default memory context allocation policy so that a context is not
      Tom Lane authored
      given any malloc block until something is first allocated in it; but
      thereafter, MemoryContextReset won't release that first malloc block.
      This preserves the quick-reset property of the original policy, without
      forcing 8K to be allocated to every context whether any of it is ever
      used or not.  Also, remove some more no-longer-needed explicit freeing
      during ExecEndPlan.
    execJunk.c 8.32 KiB
    /*-------------------------------------------------------------------------
     *
     * junk.c
     *	  Junk attribute support stuff....
     *
     * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
     * Portions Copyright (c) 1994, Regents of the University of California
     *
     *
     * IDENTIFICATION
     *	  $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.34 2002/12/15 21:01:34 tgl Exp $
     *
     *-------------------------------------------------------------------------
     */
    #include "postgres.h"
    
    #include "access/heapam.h"
    #include "executor/executor.h"
    #include "nodes/makefuncs.h"
    
    /*-------------------------------------------------------------------------
     *		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 true 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.
     *
     *-------------------------------------------------------------------------
     */
    
    /*-------------------------------------------------------------------------
     * ExecInitJunkFilter
     *
     * Initialize the Junk filter.
     *
     * The initial targetlist and associated tuple descriptor are passed in.
     * An optional resultSlot can be passed as well.
     *-------------------------------------------------------------------------
     */
    JunkFilter *
    ExecInitJunkFilter(List *targetList, TupleDesc tupType,
    				   TupleTableSlot *slot)
    {
    	JunkFilter *junkfilter;
    	List	   *cleanTargetList;
    	int			len,
    				cleanLength;
    	TupleDesc	cleanTupType;
    	List	   *t;
    	TargetEntry *tle;
    	Resdom	   *resdom,
    			   *cleanResdom;
    	bool		resjunk;
    	AttrNumber	cleanResno;
    	AttrNumber *cleanMap;
    	Expr	   *expr;
    
    	/*
    	 * First find the "clean" target list, i.e. all the entries in the
    	 * original target list which have a false '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);
    
    		resdom = rtarget->resdom;
    		expr = rtarget->expr;
    		resjunk = resdom->resjunk;
    		if (!resjunk)
    		{
    			/*
    			 * 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 = makeTargetEntry(cleanResdom, expr);
    			cleanTargetList = lappend(cleanTargetList, tle);
    		}
    	}
    
    	/*
    	 * Now calculate the tuple type for the cleaned tuple (we were already
    	 * given the type for the original targetlist).
    	 */
    	cleanTupType = ExecTypeFromTL(cleanTargetList, tupType->tdhasoid);
    
    	len = ExecTargetListLength(targetList);
    	cleanLength = ExecTargetListLength(cleanTargetList);
    
    	/*
    	 * Now calculate the "map" between the original tuple's 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)
    	{
    		cleanMap = (AttrNumber *) palloc(cleanLength * sizeof(AttrNumber));
    		cleanResno = 1;
    		foreach(t, targetList)
    		{
    			TargetEntry *tle = lfirst(t);
    
    			resdom = tle->resdom;
    			resjunk = resdom->resjunk;
    			if (!resjunk)
    			{
    				cleanMap[cleanResno - 1] = resdom->resno;
    				cleanResno++;
    			}
    		}
    	}
    	else
    		cleanMap = NULL;
    
    	/*
    	 * Finally create and initialize the JunkFilter struct.
    	 */
    	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;
    	junkfilter->jf_resultSlot = slot;
    
    	if (slot)
    		ExecSetSlotDescriptor(slot, cleanTupType, false);
    
    	return junkfilter;
    }
    
    /*-------------------------------------------------------------------------
     * ExecGetJunkAttribute
     *
     * Given a tuple (slot), the junk filter and a junk attribute's name,
     * extract & return the value and isNull flag of this attribute.
     *
     * It returns false iff no junk attribute with such name was found.
     *-------------------------------------------------------------------------
     */
    bool
    ExecGetJunkAttribute(JunkFilter *junkfilter,
    					 TupleTableSlot *slot,
    					 char *attrName,
    					 Datum *value,
    					 bool *isNull)
    {
    	List	   *targetList;
    	List	   *t;
    	Resdom	   *resdom;
    	AttrNumber	resno;
    	char	   *resname;
    	bool		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 && (strcmp(resname, attrName) == 0))
    		{
    			/* We found it ! */
    			resno = resdom->resno;
    			break;
    		}
    	}
    
    	if (resno == InvalidAttrNumber)
    	{
    		/* Ooops! We couldn't find this attribute... */
    		return false;
    	}
    
    	/*
    	 * Now extract the attribute value from the tuple.
    	 */
    	tuple = slot->val;
    	tupType = junkfilter->jf_tupType;
    
    	*value = heap_getattr(tuple, resno, tupType, isNull);
    
    	return true;
    }
    
    /*-------------------------------------------------------------------------
     * ExecRemoveJunk
     *
     * Construct and return a tuple with all the junk attributes removed.
     *
     * Note: for historical reasons, this does not store the constructed
     * tuple into the junkfilter's resultSlot.  The caller should do that
     * if it wants to.
     *-------------------------------------------------------------------------
     */
    HeapTuple
    ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
    {
    	HeapTuple	tuple;
    	HeapTuple	cleanTuple;
    	AttrNumber *cleanMap;
    	TupleDesc	cleanTupType;
    	TupleDesc	tupType;
    	int			cleanLength;
    	bool		isNull;
    	int			i;
    	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 = junkfilter->jf_tupType;
    	cleanTupType = 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 attributes. for large tuples we just
    	 * use palloc.
    	 */
    	if (cleanLength > 64)
    	{
    		values = (Datum *) palloc(cleanLength * sizeof(Datum));
    		nulls = (char *) palloc(cleanLength * sizeof(char));
    	}
    	else
    	{
    		values = values_array;
    		nulls = nulls_array;
    	}
    
    	/*
    	 * Exctract one by one all the values of the "clean" tuple.
    	 */
    	for (i = 0; i < cleanLength; i++)
    	{
    		values[i] = heap_getattr(tuple, cleanMap[i], tupType, &isNull);
    
    		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;
    }