head	1.23;
access;
symbols;
locks; strict;
comment	@ * @;


1.23
date	92.08.26.23.18.06;	author mer;	state Exp;
branches;
next	1.22;

1.22
date	92.08.25.17.45.43;	author mer;	state Exp;
branches;
next	1.21;

1.21
date	92.08.16.21.06.15;	author clarsen;	state Exp;
branches;
next	1.20;

1.20
date	92.08.04.17.37.42;	author mer;	state Exp;
branches;
next	1.19;

1.19
date	92.07.13.17.36.25;	author hong;	state Exp;
branches;
next	1.18;

1.18
date	92.07.13.16.25.29;	author hong;	state Exp;
branches;
next	1.17;

1.17
date	92.07.04.04.29.28;	author mer;	state Exp;
branches;
next	1.16;

1.16
date	92.06.22.22.49.25;	author mer;	state Exp;
branches;
next	1.15;

1.15
date	92.06.22.17.20.35;	author mer;	state Exp;
branches;
next	1.14;

1.14
date	92.05.06.06.00.34;	author mer;	state Exp;
branches;
next	1.13;

1.13
date	92.05.05.18.54.08;	author mer;	state Exp;
branches;
next	1.12;

1.12
date	92.03.07.19.10.57;	author hong;	state Exp;
branches;
next	1.11;

1.11
date	92.03.05.00.39.14;	author hong;	state Exp;
branches;
next	1.10;

1.10
date	92.02.27.05.26.22;	author mer;	state Exp;
branches;
next	1.9;

1.9
date	92.02.25.15.26.38;	author clarsen;	state Exp;
branches;
next	1.8;

1.8
date	91.12.12.02.18.42;	author mer;	state Exp;
branches;
next	1.7;

1.7
date	91.11.17.21.10.46;	author mer;	state Exp;
branches;
next	1.6;

1.6
date	91.11.14.10.57.55;	author glass;	state Exp;
branches;
next	1.5;

1.5
date	91.08.25.13.28.37;	author hong;	state Exp;
branches;
next	1.4;

1.4
date	91.07.24.16.08.25;	author hong;	state Exp;
branches;
next	1.3;

1.3
date	91.07.22.22.20.21;	author mao;	state Exp;
branches;
next	1.2;

1.2
date	91.07.17.23.52.20;	author hong;	state Exp;
branches;
next	1.1;

1.1
date	91.06.18.23.31.31;	author cimarron;	state Exp;
branches;
next	;


desc
@ reorganized executor to use tuple table properly for nested dot stuff

@


1.23
log
@initialize rawTupleBuffer to InvalidBuffer
@
text
@/* ----------------------------------------------------------------
 *   FILE
 *	ex_main.c
 *	
 *   DESCRIPTION
 *	top level executor interface routines
 *
 *   INTERFACE ROUTINES
 *   	ExecMain	- main interface to executor
 *
 *   NOTES
 *	
 *   IDENTIFICATION
 *	$Header: /users/mer/pg/src/executor/RCS/ex_main.c,v 1.22 1992/08/25 17:45:43 mer Exp mer $
 * ----------------------------------------------------------------
 */

#define EXEC_RULEMANAGER 1

#include "tcop/slaves.h"
#include "executor/executor.h"

 RcsId("$Header: /users/mer/pg/src/executor/RCS/ex_main.c,v 1.22 1992/08/25 17:45:43 mer Exp mer $");

/* ----------------------------------------------------------------
 *	random junk
 * ----------------------------------------------------------------
 */
bool  ExecIsInitialized = false;
Const ConstTrue;
Const ConstFalse;

extern int Quiet;

extern 	List rule;

/* ----------------------------------------------------------------
 *	InitializeExecutor
 *
 *	This is only called once - by ExecMain, the first time
 *	the user executes a query.
 * ----------------------------------------------------------------
 */
void
InitializeExecutor()
{
    MemoryContext oldContext;
    ObjectId    boolType = 16;	/* see local.bki */
    Size	boolLen = 1;	/* these should come from lookups */
    Datum	datumTrue;
    Datum	datumFalse;

    /* ----------------
     *	make certain we are in the top memory context
     *  or else this stuff will go away after the first transaction.
     * ----------------
     */
    oldContext = MemoryContextSwitchTo(TopMemoryContext);

    /* ----------------
     *	initialize ConstTrue and ConstFalse
     * ----------------
     */
    datumTrue  = Int32GetDatum((int32) true);
    datumFalse = Int32GetDatum((int32) false);
    
    ConstTrue =  MakeConst(boolType, boolLen, datumTrue,  false, true);
    ConstFalse = MakeConst(boolType, boolLen, datumFalse, false, true);
    
#ifdef EXEC_DEBUGVARIABLEFILE
    /* ----------------
     *	initialize debugging variables
     * ----------------
     */
    if (! Quiet)
	printf("==== using %s\n", EXEC_DEBUGVARIABLEFILE);
    
    DebugVariableFileSet(EXEC_DEBUGVARIABLEFILE);
#endif EXEC_DEBUGVARIABLEFILE
    
    /* ----------------
     *	return to old memory context
     * ----------------
     */
    (void) MemoryContextSwitchTo(oldContext);

    ExecIsInitialized = true;
}
 

/* ----------------------------------------------------------------
 *   	ExecMain
 *   
 *   	This is the main routine of the executor module. It accepts
 *   	the query descriptor from the traffic cop and executes the
 *   	query plan.
 *   
 *   	Parameter:
 *   	   argList --(commandType parseTree queryPlan queryState queryFeature)
 * ----------------------------------------------------------------
 */
 
List
ExecMain(queryDesc, estate, feature)
    List 	queryDesc;
    EState 	estate;
    List 	feature;
{
    int		operation;
    List 	parseTree;
    Plan	plan;
    List 	result;
    CommandDest dest;
    void	(*destination)();
    
    /* ----------------
     *	sanity checks
     * ----------------
     */
    Assert(!lispNullp(queryDesc));
    
    /* ----------------
     *	initialize if necessary
     * ----------------
     */
    if (!ExecIsInitialized)
	InitializeExecutor();
    
    /* ----------------
     *	extract information from the query descriptor
     *  and the query feature.
     * ----------------
     */
    operation =   CAtom(GetOperation(queryDesc));
    parseTree =   QdGetParseTree(queryDesc);
    plan =	  QdGetPlan(queryDesc);
    dest =	  QdGetDest(queryDesc);
    destination = (void (*)()) DestToFunction(dest);
	
    /* ----------------
     *	ExecMain is typically called from the tcop three
     *   times:
     *
     *	first time,   command = EXEC_START		initialize
     *   second time, command = EXEC_RUN		run the plan
     *   last time,   command = EXEC_END		cleanup
     * ----------------
     */
    result =    LispNil;
    
    switch(CInteger(FeatureGetCommand(feature))) {
	/* ----------------
	 *	EXEC_START, EXEC_RUN, EXEC_END are the
	 *	most general cases..
	 * ----------------
	 */
    case EXEC_START:
	/* result is a tuple descriptor */
	result = InitPlan(operation,
			  parseTree,
			  plan,
			  estate);
	/* reset buffer refcount.  the current refcounts
	 * are saved and will be restored at the end of
	 * this ExecMain cycle.
	 *
	 * this makes sure that when ExecMain's are
	 * called recursively as for tuple level rules
	 * or postquel functions, the buffers pinned
	 * by one ExecMain will not be unpinned by another
	 * ExecMain.
	 */
	BufferRefCountReset(get_es_refcount(estate));
	break;
		
    case EXEC_RUN:
	/* result is a tuple or LispNil */
	result = (List) ExecutePlan(estate,
				    plan,
				    parseTree,
				    operation,
				    ALL_TUPLES,
				    EXEC_FRWD,
				    destination);
	break;
	
    case EXEC_END:
	/* result is a tuple or LispNil */
	result = EndPlan(plan, estate);
	/* restore saved refcounts. */
	BufferRefCountRestore(get_es_refcount(estate));
	break;

	/* ----------------
	 *	retrieve next n "forward" tuples
	 * ----------------
	 */
    case EXEC_FOR:
	/* result is a tuple or LispNil */
	result = (List) ExecutePlan(estate,
				    plan,
				    parseTree,
				    operation,
				    CInteger(FeatureGetCount(feature)),
				    EXEC_FRWD,
				    destination);
	break;

	/* ----------------
	 *	retrieve next n "backward" tuples
	 * ----------------
	 */
    case EXEC_BACK:
	/* result is a tuple or LispNil */
	result = (List) ExecutePlan(estate,
				    plan,
				    parseTree,
				    operation,
				    CInteger(FeatureGetCount(feature)),
				    EXEC_BKWD,
				    destination);
	break;
	
	/* ----------------
	 *	return one tuple but don't "retrieve" it.
	 *	(this is used by the rule manager..) -cim 9/14/89
	 * ----------------
	 */
    case EXEC_RETONE:
	/* result is a tuple or LispNil */
	result = (List) ExecutePlan(estate,
				    plan,
				    parseTree,
				    operation,
				    ONE_TUPLE,
				    EXEC_FRWD,
				    destination);
	break;
    default:
	elog(DEBUG, "ExecMain: Unknown command.");
	break;
    }
    
    return result;
}
 
/* ----------------------------------------------------------------
 *   	InitPlan
 *   
 *   	Initialises the query plan: open files, allocate storage
 *   	and start up the rule manager
 * ----------------------------------------------------------------
 */
extern Relation    CopyRelDescUsing();

List
InitPlan(operation, parseTree, plan, estate)
    int			operation;
    EState 		estate;
    List 		parseTree;
    Plan	 	plan;
{	
    List		parseRoot;
    List 		rangeTable;
    List		resultRelation;
    Relation 		relationRelationDesc;
    Relation            intoRelationDesc;
    
    TupleDescriptor 	tupType;
    List	 	targetList;
    int		 	len;
    List	 	attinfo;
    extern List		MakeList();
    
#ifdef PALLOC_DEBUG
    {
	extern int query_tuple_count;
	query_tuple_count = 0;
    }
#endif PALLOC_DEBUG    
    
    /* ----------------
     *  get information from query descriptor
     * ----------------
     */
    parseRoot =   	parse_root(parseTree);
    rangeTable =	parse_tree_range_table(parseTree);
    resultRelation = 	parse_tree_result_relation(parseTree);
    
    /* ----------------
     *  initialize the node's execution state
     * ----------------
     */
    set_es_range_table(estate, rangeTable);
    set_es_error_message(estate, (Name) "Foo bar");
    
    /* ----------------
     *	initialize the BaseId counter so node base_id's
     *  are assigned correctly.  Someday baseid's will have to
     *  be stored someplace other than estate because they
     *  should be unique per query planned.
     * ----------------
     */
    set_es_BaseId(estate, 1);
    
    /* ----------------
     *	initialize result relation stuff
     * ----------------
     */
    set_es_result_rel_scanstate(estate, NULL);

    if (resultRelation != NULL && operation != RETRIEVE) {
	/* ----------------
	 *    if we have a result relation, open the it and
	 *    initialize the result relation info stuff.
	 * ----------------
	 */
	RelationInfo	resultRelationInfo;
	Index 		resultRelationIndex;
	List		rtentry;
	ObjectId	resultRelationOid;
	Relation 	resultRelationDesc;
	RelationRuleInfo resRelRuleInfo;
	
	resultRelationIndex = CInteger(resultRelation);
	rtentry =	      rt_fetch(resultRelationIndex, rangeTable);
	resultRelationOid =   CInteger(rt_relid(rtentry));
	resultRelationDesc =  heap_open(resultRelationOid);
	resultRelationInfo = MakeRelationInfo(resultRelationIndex,
					      resultRelationDesc,
					      0,      /* num indices */
					      NULL,   /* index descs */
					      NULL);  /* index key info */
	/* ----------------
	 *  open indices on result relation and save descriptors
	 *  in the result relation information..
	 * ----------------
	 */
	ExecOpenIndices(resultRelationOid, resultRelationInfo);
	
	set_es_result_relation_info(estate, resultRelationInfo);

	/* ----------------
	 *  Initialize the result relation rule info.
	 * ----------------
	 */
	resRelRuleInfo = prs2MakeRelationRuleInfo(resultRelationDesc,
						  operation);
	
	set_es_result_rel_ruleinfo(estate, resRelRuleInfo);
    } else {
	/* ----------------
	 * 	if no result relation, then set state appropriately
	 * ----------------
	 */
	set_es_result_relation_info(estate, NULL);
    }
    
    relationRelationDesc = heap_openr(RelationRelationName);
    set_es_relation_relation_descriptor(estate, relationRelationDesc);
    
    /* ----------------
     *    initialize the executor "tuple" table.
     * ----------------
     */
    {
	int        nSlots     = ExecCountSlotsNode(plan);
	TupleTable tupleTable = ExecCreateTupleTable(nSlots+10);

	set_es_tupleTable(estate, tupleTable);
    }

    /* ----------------
     *     initialize the private state information for
     *	   all the nodes in the query tree.  This opens
     *	   files, allocates storage and leaves us ready
     *     to start processing tuples..
     * ----------------
     */
    ExecInitNode(plan, estate, NULL);
    
    /* ----------------
     *     get the tuple descriptor describing the type
     *	   of tuples to return.. (this is especially important
     *	   if we are creating a relation with "retrieve into")
     * ----------------
     */
    tupType =    ExecGetTupType(plan);             /* tuple descriptor */
    targetList = get_qptargetlist(plan);
    len = 	 ExecTargetListLength(targetList); /* number of attributes */

    /* ----------------
     *    now that we have the target list, initialize the junk filter
     *    if this is a REPLACE or a DELETE query.
     *    We also init the junk filter if this is an append query
     *    (there might be some rule lock info there...)
     *    NOTE: in the future we might want to initialize the junk
     *	  filter for all queries.
     * ----------------
     */
    if (operation == REPLACE || operation == DELETE || operation == APPEND) {
	JunkFilter j = (JunkFilter) ExecInitJunkFilter(targetList);
	set_es_junkFilter(estate, j);
    } else
	set_es_junkFilter(estate, NULL);
    
    /* ----------------
     *	initialize the "into" relation
     * ----------------
     */
    intoRelationDesc = (Relation) NULL;
    
    if (operation == RETRIEVE) {
	List 	    resultDesc;
	int  	    dest;
	String 	    intoName;
	char	    archiveMode;
	ObjectId    intoRelationId;
	
	resultDesc = root_result_relation(parseRoot);
	if (! lispNullp(resultDesc)) {
	    dest = CAtom(CAR(resultDesc));
	    if (dest == INTO) {
		/* ----------------
		 *  create the "into" relation
		 *
		 *  note: there is currently no way for the user to
		 *	  specify the desired archive mode of the
		 *	  "into" relation...
		 * ----------------
		 */
		intoName = CString(CADR(resultDesc));
		archiveMode = 'n';
		
		intoRelationId = heap_create(intoName,
					     archiveMode,
					     len,
					     DEFAULT_SMGR,
					     (struct attribute **)tupType);
		
		/* ----------------
		 *  XXX rather than having to call setheapoverride(true)
		 *	and then back to false, we should change the
		 *	arguments to heap_open() instead..
		 * ----------------
		 */
		setheapoverride(true);
		
		intoRelationDesc = heap_open(intoRelationId);
		local_heap_open(intoRelationDesc);
		
		setheapoverride(false);
		
	    } else if (dest == INTOTEMP) {
		/* ----------------
		 *  this is only for the parallel backends to save results in
		 *  temporary relations and collect them later
		 * ----------------
		 */

		intoRelationDesc = ExecCreatR(len, tupType, -1);
		if (! IsMaster) {
		    SlaveTmpRelDescInit();
		    SlaveInfoP[MyPid].resultTmpRelDesc =
		       CopyRelDescUsing(intoRelationDesc, SlaveTmpRelDescAlloc);
		}
	    }
	}
    }

    set_es_into_relation_descriptor(estate, intoRelationDesc);
    
    /* ----------------
     *	return the type information..
     * ----------------
     */
    attinfo = MakeList(lispInteger(len), tupType, -1);
    
    return
	attinfo;
}
 
/* ----------------------------------------------------------------
 *   	EndPlan
 *   
 *   	Cleans up the query plan -- closes files and free up storages
 * ----------------------------------------------------------------
 */
 
List
EndPlan(plan, estate)
    Plan		plan;
    EState		estate;
{
    RelationInfo 	resultRelationInfo;
    List		resultRelationInfoList;
    Relation		intoRelationDesc;
   
    /* ----------------
     *	get information from state
     * ----------------
     */
    resultRelationInfo =  get_es_result_relation_info(estate);
    resultRelationInfoList = get_es_result_relation_info_list(estate);
    intoRelationDesc =	  get_es_into_relation_descriptor(estate);
   
    /* ----------------
     *   shut down the query
     * ----------------
     */
    ExecEndNode(plan);
      
    /* ----------------
     *    destroy the executor "tuple" table.
     * ----------------
     */
    {
	TupleTable tupleTable = (TupleTable) get_es_tupleTable(estate);
	ExecDestroyTupleTable(tupleTable,true);	/* was missing last arg */
	set_es_tupleTable(estate, NULL);
    }
        
    /* ----------------
     *   close the result relations if necessary
     * ----------------
     */
    if (resultRelationInfo != NULL) {
	Relation resultRelationDesc;
	
	resultRelationDesc = get_ri_RelationDesc(resultRelationInfo);
	heap_close(resultRelationDesc);
	
	/* ----------------
	 *  close indices on the result relation
	 * ----------------
	 */
	ExecCloseIndices(resultRelationInfo);
    }

    while (resultRelationInfoList != LispNil) {
	Relation resultRelationDesc;

	resultRelationInfo = (RelationInfo) CAR(resultRelationInfoList);
	resultRelationDesc = get_ri_RelationDesc(resultRelationInfo);
	heap_close(resultRelationDesc);
	resultRelationInfoList = CDR(resultRelationInfoList);
    }
         
    /* ----------------
     *   close the "into" relation if necessary
     * ----------------
     */
    if (intoRelationDesc != NULL)
	if (ParallelExecutorEnabled())
	    /* have to use shared buffer pool for paralle backends */
	    heap_close(intoRelationDesc);
	else
	    local_heap_close(intoRelationDesc);
    
    /* ----------------
     *	return successfully
     * ----------------
     */
    return
	LispTrue;
}
 
/* ----------------------------------------------------------------
 *   	ExecutePlan
 *   
 *   	processes the query plan to retrieve 'tupleCount' tuples in the
 *   	direction specified.
 *   	Retrieves all tuples if tupleCount is 0
 *
 *|	XXX direction seems not to be used (I hope this isn't
 *|         another example of lisp global scoping) -cim 8/7/89
 * ----------------------------------------------------------------
 */

TupleTableSlot
ExecutePlan(estate, plan, parseTree, operation, numberTuples,
	    direction, printfunc)
    EState 	estate;
    Plan	plan;
    LispValue	parseTree;
    int		operation;
    int 	numberTuples;
    int 	direction;
    void 	(*printfunc)();
{
    Relation		intoRelationDesc;
    JunkFilter		junkfilter;
    
    TupleTableSlot	slot;
    ItemPointer		tupleid = NULL;
    ItemPointerData	tuple_ctid;
    int	 		current_tuple_count;
    TupleTableSlot	result;	/* result to return to ExecMain */
    RuleLock		locks;
    
    /* ----------------
     *  get information
     * ----------------
     */
    intoRelationDesc =	get_es_into_relation_descriptor(estate);
    
    /* ----------------
     *	initialize local variables
     * ----------------
     */
    slot 		= NULL;
    current_tuple_count = 0;
    result 		= NULL;

    /* ----------------
     *	Set the direction.
     * ----------------
     */
    set_es_direction(estate, direction);

    /* ----------------
     *	Loop until we've processed the proper number
     *  of tuples from the plan..
     * ----------------
     */
    
    for(;;) {
	/* ----------------
	 *	Execute the plan and obtain a tuple
	 * ----------------
	 */
	 if (operation != NOTIFY)
		slot = ExecProcNode(plan);
	
	/* ----------------
	 *	if the tuple is null, then we assume
	 *	there is nothing more to process so
	 *	we just return null...
	 * ----------------
	 */
	if (TupIsNull((Pointer) slot) && operation != NOTIFY) {
	    result = NULL;
	    break;
	}
	
	/* ----------------
	 *	if we have a junk filter, then project a new
	 *	tuple with the junk removed.
	 *
	 *	Store this new "clean" tuple in the place of the 
	 *	original tuple.
	 *
	 *      Also, extract all the junk ifnormation we need.
	 * ----------------
	 */
	if ((junkfilter = get_es_junkFilter(estate)) != (JunkFilter)NULL) {
	    Datum 	datum;
	    NameData 	attrName;
	    HeapTuple 	newTuple;
	    Boolean 	isNull;

	    /* ---------------
	     * extract the 'ctid' junk attribute.
	     * ---------------
	     */
	    if (operation == REPLACE || operation == DELETE) {
		strcpy(&(attrName), "ctid");
		if (! ExecGetJunkAttribute(junkfilter,
					   slot,
					   &attrName,
					   &datum,
					   &isNull))
		    elog(WARN,"ExecutePlan: NO (junk) `ctid' was found!");
		
		if (isNull) 
		    elog(WARN,"ExecutePlan: (junk) `ctid' is NULL!");
		
		tupleid = (ItemPointer) DatumGetPointer(datum);
		tuple_ctid = *tupleid; /* make sure we don't free the ctid!! */
		tupleid = &tuple_ctid;
	    }

	    /* ---------------
	     * Find the "rule lock" info. (if it is there!)
	     * ---------------
	     */
	    strcpy(&(attrName), "lock");
	    if (! ExecGetJunkAttribute(junkfilter,
				       slot,
				       &attrName,
				       &datum,
				       &isNull))
		locks = InvalidRuleLock;
	    else {
		if (isNull) {
		    /*
		     * this is an error (I think...)
		     * If we have a "lock" junk attribute, then it better
		     * have a value!
		     * NOTE: an empty lock i.e. "(numOfLocks: 0)"::lock
		     * is a good non-null value, i.e. still 'isNull' must
		     * be false
		     */
		    elog(WARN, "ExecutePlan: (junk) rule lock is NULL!");
		}
		
		locks = (RuleLock) DatumGetPointer(datum);
		
		/*
		 * Make a copy of the lock, because when we call
		 * amreplace, we will (probably?) free it and the
		 * "locks" as returned by "ExecGetJunkAttribute" is
		 * something that -for some reason- causes problems when
		 * you try to pfree it! (believe me, I've tried it!).
		 */
		locks = prs2CopyLocks(locks);
	    }

	    /* ---------------
	     * Finally create a new "clean" tuple with all junk attributes
	     * removed and with the new "rule lock" info.
	     * ---------------
	     */
	    newTuple = ExecRemoveJunk(junkfilter, slot);
	    
	    slot = (TupleTableSlot)
		ExecStoreTuple((Pointer) newTuple, /* tuple to store */
			       (Pointer) slot,     /* destination slot */
			       InvalidBuffer, 	/* this tuple has no buffer */
			       true); 		/* tuple should be pfreed */
	} else {
	    locks = InvalidRuleLock;
	}

#ifdef PALLOC_DEBUG	
	/* ----------------
	 *	if debugging memory allocations, print memory dump
	 *	every so often
	 * ----------------
	 */
	{
	    extern int query_tuple_count, query_tuple_max;
	    if (query_tuple_max && query_tuple_max == ++query_tuple_count) {
		query_tuple_count = 0;
		dump_palloc_list("ExecutePlan", true);
	    }
	}
#endif PALLOC_DEBUG
	
	/* ----------------
	 *	now that we have a tuple, do the appropriate thing
	 *	with it.. either return it to the user, add
	 *	it to a relation someplace, delete it from a
	 *	relation, or modify some of it's attributes.
	 * ----------------
	 */
	
	switch(operation) {
	case RETRIEVE:
	    result = ExecRetrieve(slot, 	  /* slot containing tuple */
				  printfunc,	  /* print function */
				  intoRelationDesc); /* "into" relation */
	    break;
	    
	case APPEND:
	    result = ExecAppend(slot, tupleid, estate, locks);
	    break;
	    
	case DELETE:
	    result = ExecDelete(slot, tupleid, estate);
	    break;
	    
	case REPLACE:
	    result = ExecReplace(slot, tupleid, estate, parseTree, locks);
	    break;

	    /* Total hack. I'm ignoring any accessor functions for
	       Relation, RelationTupleForm, NameData.
	       Assuming that NameData.data has offset 0.
	       */
	case NOTIFY: {
	    RelationInfo rInfo = get_es_result_relation_info(estate);
	    Relation rDesc = get_ri_RelationDesc(rInfo);
	    Async_Notify(&rDesc->rd_rel->relname);
	    result = NULL;
	    current_tuple_count = 0;
	    numberTuples = 1;
	    elog(DEBUG, "ExecNotify %s",&rDesc->rd_rel->relname);
	}
	    break;
	    
	default:
	    elog(DEBUG, "ExecutePlan: unknown operation in queryDesc");
	    result = NULL;
	    break;
	}
	/* ----------------
	 *	check our tuple count.. if we've returned the
	 *	proper number then return, else loop again and
	 *	process more tuples..
	 * ----------------
	 */
	current_tuple_count += 1;
	if (numberTuples == current_tuple_count)
	    break;
    }

    /* ----------------
     *	here, result is either a slot containing a tuple in the case
     *  of a RETRIEVE or NULL otherwise.
     * ----------------
     */
    return result;	    
}
 
/* ----------------------------------------------------------------
 *	ExecRetrieve
 *
 *	RETRIEVEs are easy.. we just pass the tuple to the appropriate
 *	print function.  The only complexity is when we do a
 *	"retrieve into", in which case we insert the tuple into
 *	the appropriate relation (note: this is a newly created relation
 *	so we don't need to worry about indices or locks.)
 * ----------------------------------------------------------------
 */
 
TupleTableSlot
ExecRetrieve(slot, printfunc, intoRelationDesc)
    TupleTableSlot	slot;
    void	 	(*printfunc)();
    Relation	 	intoRelationDesc;
{
    HeapTuple	 	tuple;
    TupleDescriptor 	attrtype;

    /* ----------------
     *	get the heap tuple out of the tuple table slot
     * ----------------
     */
    tuple = (HeapTuple) ExecFetchTuple((Pointer) slot);
    attrtype =		ExecSlotDescriptor((Pointer) slot);
    
    /* ----------------
     *	insert the tuple into the "into relation"
     * ----------------
     */
    if (intoRelationDesc != NULL) {
	if (ParallelExecutorEnabled())
	    /* for parallel executor, has to insert through shared buffer */
	    (void) heap_insert(intoRelationDesc, tuple, NULL);
	else
	    (void) local_heap_insert(intoRelationDesc, tuple);
	IncrAppended();
    }
    
    /* ----------------
     *	send the tuple to the front end (or the screen)
     * ----------------
     */
    (*printfunc)(tuple, attrtype);
    IncrRetrieved();
    
    /* ----------------
     *	return the tuple slot back to ExecutePlan
     * ----------------
     */
    return
	slot;
}
 
/* ----------------------------------------------------------------
 *	ExecAppend
 *
 *	APPENDs are trickier.. we have to insert the tuple into
 *	the base relation, insert appropriate tuples into the
 *	index relations and if we step on some locks along the way,
 *	run the rule manager..
 * ----------------------------------------------------------------
 */
 
TupleTableSlot
ExecAppend(slot, tupleid, estate, newlocks)
    TupleTableSlot	slot;
    ItemPointer		tupleid;
    EState		estate;
    RuleLock		newlocks;
{
    HeapTuple	 tuple;
    RelationInfo resultRelationInfo;
    Relation	 resultRelationDesc;
    int		 numIndices;
    RuleLock 	 locks;
    RuleLock	 indexLocks;
    HeapTuple	 returnedTuple;
    Buffer	 returnedBuffer;
    Prs2Status   status;
    Prs2Stub	 ruleStubs;
    RuleLock 	 stubLocks;
    HeapTuple	 tempTuple;
    ObjectId	 newId;

    /* ----------------
     *	get the heap tuple out of the tuple table slot
     * ----------------
     */
    tuple = (HeapTuple) ExecFetchTuple((Pointer) slot);
    
    /* ----------------
     *	get information on the result relation
     * ----------------
     */
    resultRelationInfo = get_es_result_relation_info(estate);
    resultRelationDesc = get_ri_RelationDesc(resultRelationInfo);
    
    /* ----------------
     *	process rules
     * ----------------
     */
#ifdef EXEC_RULEMANAGER
    /*
     * NOTE: the check for rule stubs etc. is done by the rule manager.
     */

    /*
     * Now call the rule manager, but only if necessary.
     */
    if (prs2MustCallRuleManager(get_es_result_rel_ruleinfo(estate),
				(HeapTuple) NULL,
				InvalidBuffer,
				APPEND))
    {
	status = prs2Main(estate,
			  (RelationRuleInfo) NULL,/*only aplies to retrieves*/
			  APPEND,
			  0,
			  resultRelationDesc,
			  (HeapTuple) NULL,
			  InvalidBuffer,
			  tuple,
			  InvalidBuffer,
			  (HeapTuple) NULL,
			  InvalidBuffer,
			  (AttributeNumberPtr) NULL,
			  0,
			  &returnedTuple,
			  &returnedBuffer);
	if (status == PRS2_STATUS_INSTEAD) {
	    /*
	     * do not append the tuple
	     */
	    return NULL;
	    
	} else if (status == PRS2_STATUS_TUPLE_CHANGED) {
	    /* ----------------
	     *  store the returnedTuple in the slot and free the old
	     *  copy of the tuple.
	     * ----------------
	     */
	    ExecStoreTuple((Pointer) returnedTuple, /* tuple to store */
			   (Pointer) slot,           /* destination slot */
			   returnedBuffer,
			   true);		/* tuple should be pfreed */
	    
	    tuple = returnedTuple;
	}
    } /*if prs2MustCallRuleManager*/

#endif EXEC_RULEMANAGER
    
    /* ----------------
     *	have to add code to preform unique checking here.
     *  cim -12/1/89
     * ----------------
     */
    
    /* ----------------
     * If the user has explicitly specified some locks in the "replace"
     * statement, ignore all rule stubs & stuff and just put these
     * locks in the tuple. Obviously this is guaranteed to mess things
     * up if the user does not *really* know what he is doing,
     * i.e. if it is not me!  _sp.
     * ----------------
     */
    if (newlocks != InvalidRuleLock)
	HeapTupleSetRuleLock(tuple, InvalidBuffer, newlocks);
    
    /* ----------------
     *	insert the tuple
     * ----------------
     */
    newId = heap_insert(resultRelationDesc, /* relation desc */
			tuple,		    /* heap tuple */
			0);		    /* return: offset */
    IncrAppended();
    UpdateAppendOid(newId);
    
    /* ----------------
     *	process indices
     * 
     *	Note: heap_insert adds a new tuple to a relation.  As a side
     *  effect, the tupleid of the new tuple is placed in the new
     *  tuple's t_ctid field.
     * ----------------
     */
    numIndices = get_ri_NumIndices(resultRelationInfo);
    if (numIndices > 0) {
	indexLocks = ExecInsertIndexTuples(tuple,
					   &(tuple->t_ctid),
					   estate);
    }

    /* ----------------
     *	XXX will we ever return anything meaningful?
     * ----------------
     */
    return NULL;
}
 
/* ----------------------------------------------------------------
 *	ExecDelete
 *
 *	DELETE is like append, we delete the tuple and its
 *	index tuples and then run the rule manager if necessary.
 * ----------------------------------------------------------------
 */
 
TupleTableSlot
ExecDelete(slot, tupleid, estate)
    TupleTableSlot	slot;
    ItemPointer		tupleid;
    EState		estate;
{
    HeapTuple	 tuple;
    RelationInfo resultRelationInfo;
    Relation	 resultRelationDesc;
    
    RuleLock	 locks;
    RuleLock	 indexLocks;
    Prs2Status   status;
    HeapTuple    oldTuple;
    Buffer       oldTupleBuffer;
    HeapTuple    rawTuple;
    Buffer	 rawTupleBuffer;
    HeapTuple    dummyTuple;
    Buffer       dummyBuffer;

    /* ----------------
     *	get the heap tuple out of the tuple table slot
     * ----------------
     */
    tuple = (HeapTuple) ExecFetchTuple((Pointer) slot);

    /* ----------------
     *	get the result relation information
     * ----------------
     */
    resultRelationInfo = get_es_result_relation_info(estate);
    resultRelationDesc = get_ri_RelationDesc(resultRelationInfo);

#ifdef EXEC_RULEMANAGER
    /* ----------------
     *        process rules
     * ----------------
     */
    
    /* ----------------
     * find the old & raw tuples
     *
     * NOTE: currently we do not store them anywhere!
     * therefore we will use the 'tupleid' to find the original
     * tuple (the "raw" tuple") and we will assume that "old" tuple
     * is the same as the "raw" tuple.
     * The only problem is the extra time spent to reactivate
     * backward chaining rules already activated but... what
     * else can we do ?
     */
    rawTuple = heap_fetch(resultRelationDesc,
			  NowTimeQual,
			  tupleid,
			  &rawTupleBuffer);
    
    oldTuple = rawTuple;
    oldTupleBuffer = rawTupleBuffer;

    /* ----------------
     * XXX!!
     * NOTE: in the current implementation where only RelationLevel
     * locks are used, the rule manager must look in pg_relation
     * to find the locks of "oldTuple".
     */
    if (prs2MustCallRuleManager(get_es_result_rel_ruleinfo(estate),
				oldTuple, oldTupleBuffer, DELETE))
    {
	status = prs2Main(estate,
			  (RelationRuleInfo) NULL,/*only aplies to retrieves*/
			  DELETE,
			  0,      /* userid */
			  resultRelationDesc,
			  oldTuple,
			  oldTupleBuffer,
			  (HeapTuple) NULL,
			  InvalidBuffer,
			  rawTuple,
			  rawTupleBuffer,
			  (AttributeNumberPtr) NULL,
			  0,
			  &dummyTuple,
			  &dummyBuffer);
	
	if (status == PRS2_STATUS_INSTEAD) {
	  /*
	   * there was an instead rule, do not do the delete...
	   */
	  return NULL;
	}
    } /*if prs2MustCallRuleManager*/
    if (BufferIsValid(rawTupleBuffer)) ReleaseBuffer(rawTupleBuffer);

#endif EXEC_RULEMANAGER
    
    /* ----------------
     *	delete the tuple
     * ----------------
     */
    locks = heap_delete(resultRelationDesc, /* relation desc */
			tupleid);	    /* item pointer to tuple */
    
    IncrDeleted();
    
    /* ----------------
     *	Note: Normally one would think that we have to
     *	      delete index tuples associated with the
     *	      heap tuple now..
     *
     *	      ... but in POSTGRES, we have no need to do this
     *        because the vaccuum daemon automatically
     *	      opens an index scan and deletes index tuples
     *	      when it finds deleted heap tuples. -cim 9/27/89
     * ----------------
     */
    
    /* ----------------
     *	XXX will we ever return anything meaningful?
     * ----------------
     */
    return NULL;
}
 
/* ----------------------------------------------------------------
 *	ExecReplace
 *
 *	note: we can't run replace queries with transactions
 *  	off because replaces are actually appends and our
 *  	scan will mistakenly loop forever, replacing the tuple
 *  	it just appended..  This should be fixed but until it
 *  	is, we don't want to get stuck in an infinite loop
 *  	which corrupts your database..
 * ----------------------------------------------------------------
 */
 
TupleTableSlot
ExecReplace(slot, tupleid, estate, parseTree, newlocks)
    TupleTableSlot	slot;
    ItemPointer		tupleid;
    EState		estate;
    LispValue		parseTree;
    RuleLock		newlocks;
{
    HeapTuple		tuple;
    RelationInfo 	resultRelationInfo;
    Relation	 	resultRelationDesc;
    RuleLock	 	locks;
    RuleLock	 	indexLocks;
    int		 	numIndices;
    HeapTuple	 	rawTuple;
    Buffer		rawTupleBuffer = InvalidBuffer;
    HeapTuple 		oldTuple;
    Buffer 		oldTupleBuffer;
    HeapTuple 		changedTuple;
    Buffer    		changedTupleBuffer;
    AttributeNumberPtr 	attributeArray;
    AttributeNumber    	numberOfReplacedAttributes;
    LispValue 		targetList;
    LispValue		t;
    Resdom    		resdom;
    Prs2Status        	status;
    Prs2Stub     	ruleStubs;
    RuleLock     	stubLocks;
    HeapTuple    	tempTuple;


    /* ----------------
     *	abort the operation if not running transactions
     * ----------------
     */
    if (IsBootstrapProcessingMode()) {
	elog(DEBUG, "ExecReplace: replace can't run without transactions");
	return NULL;
    }
    
    /* ----------------
     *	get the heap tuple out of the tuple table slot
     * ----------------
     */
    tuple = (HeapTuple) ExecFetchTuple((Pointer) slot);

    /* ----------------
     *	get the result relation information
     * ----------------
     */
    resultRelationInfo = get_es_result_relation_info(estate);
    resultRelationDesc = get_ri_RelationDesc(resultRelationInfo);

    /* ----------------
     *  process rules
     * ----------------
     */
#ifdef EXEC_RULEMANAGER    


    /* ----------------
     * find the old & raw tuples
     *
     * NOTE: currently we do not store them anywhere!
     * therefore we will use the 'tupleid' to find the original
     * tuple (the "raw" tuple") and we will assume that "old" tuple
     * is the same as the "raw" tuple.
     * The only problem is the extra time spent to reactivate
     * backward chaining rules already activated but... what
     * else can we do ?
     */
    rawTuple = heap_fetch(resultRelationDesc,
			  NowTimeQual,
			  tupleid,
			  &rawTupleBuffer);
    
    oldTuple = rawTuple;
    oldTupleBuffer = rawTupleBuffer;


    if (prs2MustCallRuleManager(get_es_result_rel_ruleinfo(estate),
				oldTuple, oldTupleBuffer, REPLACE))
    {
				    
	/* ----------------
	 * find the attributes replaced...
	 */
	attributeArray = (AttributeNumberPtr)
	    palloc( sizeof(AttributeNumber)	*
		    RelationGetNumberOfAttributes(resultRelationDesc));
	
	numberOfReplacedAttributes = 0;
	targetList = parse_targetlist(parseTree);
	foreach (t, targetList) {
	    resdom = (Resdom) CAR(CAR(t));
	    attributeArray[numberOfReplacedAttributes] = get_resno(resdom);
	    numberOfReplacedAttributes += 1;
	}

	status = prs2Main(estate,
			  (RelationRuleInfo) NULL,/*only aplies to retrieves*/
			  REPLACE,
			  0,      /* user id */
			  resultRelationDesc,
			  oldTuple,
			  oldTupleBuffer,
			  tuple,
			  InvalidBuffer,
			  rawTuple,
			  oldTupleBuffer,
			  attributeArray,
			  numberOfReplacedAttributes,
			  &changedTuple,
			  &changedTupleBuffer);
	
	if (status == PRS2_STATUS_INSTEAD) {
	    /*
	     * An instead rule has been found, do not do the replace...
	     */
	    return NULL;
	}	
	

	if (status == PRS2_STATUS_TUPLE_CHANGED) {
	    ExecStoreTuple((Pointer) changedTuple, /* tuple to store */
			   (Pointer) slot,	/* destination slot */
			   InvalidBuffer, 	/* this tuple has no buffer */
			   true);		/* tuple should be pfreed */
	    
	    tuple = changedTuple;
	}
    } /*if prs2MustCallRuleManager */
    if (BufferIsValid(oldTupleBuffer)) ReleaseBuffer(oldTupleBuffer);
	
#endif EXEC_RULEMANAGER
    
    /* ----------------
     *	have to add code to preform unique checking here.
     *  in the event of unique tuples, this becomes a deletion
     *  of the original tuple affected by the replace.
     *  cim -12/1/89
     * ----------------
     */
    
    /* ----------------
     * If the user has explicitly specified some locks in the "replace"
     * statement, ignore all rule stubs & stuff and just put these
     * locks in the tuple. Obviously this is guaranteed to mess things
     * up if the user does not *really* know what he is doing,
     * i.e. if it is not me!  _sp.
     * ----------------
     */
    if (newlocks != InvalidRuleLock)
	HeapTupleSetRuleLock(tuple, InvalidBuffer, newlocks);

    /* ----------------
     *	replace the heap tuple
     * ----------------
     */
    locks = heap_replace(resultRelationDesc, /* relation desc */
			 tupleid,	     /* item ptr of tuple to replace */
			 tuple);	     /* replacement heap tuple */
    
    IncrReplaced();
    
    /* ----------------
     *	Note: instead of having to update the old index tuples
     *        associated with the heap tuple, all we do is form
     *	      and insert new index tuples..  This is because
     *        replaces are actually deletes and inserts and
     *	      index tuple deletion is done automagically by
     *	      the vaccuum deamon.. All we do is insert new
     *	      index tuples.  -cim 9/27/89
     * ----------------
     */
    
    /* ----------------
     *	process indices
     *
     *	heap_replace updates a tuple in the base relation by invalidating
     *  it and then appending a new tuple to the relation.  As a side
     *  effect, the tupleid of the new tuple is placed in the new
     *  tuple's t_ctid field.  So we now insert index tuples using
     *  the new tupleid stored there.
     * ----------------
     */
    numIndices = get_ri_NumIndices(resultRelationInfo);
    if (numIndices > 0) {
	indexLocks = ExecInsertIndexTuples(tuple,
					   &(tuple->t_ctid),
					   estate);
    }
    
    /* ----------------
     *	XXX will we ever return anything meaningful?
     * ----------------
     */
    return NULL;
}
@


1.22
log
@handle append / retrieve into with inheritance correctlyl
@
text
@d14 1
a14 1
 *	$Header: /private/mer/pg/src/executor/RCS/ex_main.c,v 1.21 1992/08/16 21:06:15 clarsen Exp mer $
d23 1
a23 1
 RcsId("$Header: /private/mer/pg/src/executor/RCS/ex_main.c,v 1.21 1992/08/16 21:06:15 clarsen Exp mer $");
d1176 1
a1176 1
    Buffer		rawTupleBuffer;
@


1.21
log
@notify fix
@
text
@d14 1
a14 1
 *	$Header: /home/postgres/clarsen/local/postgres/src/executor/RCS/ex_main.c,v 1.20 1992/08/04 17:37:42 mer Exp clarsen $
d23 1
a23 1
 RcsId("$Header: /home/postgres/clarsen/local/postgres/src/executor/RCS/ex_main.c,v 1.20 1992/08/04 17:37:42 mer Exp clarsen $");
a621 6
     *	get the junk filter
     * ----------------
     */
    junkfilter = (JunkFilter) get_es_junkFilter(estate);
    
    /* ----------------
a635 21
	 *	For append nodes the plan can change during ExecProcNode()
	 *	If this has occured we need to update the current result-
	 *	relationInfo and the current Junkfilter.
	 * ----------------
	 */
	if (slot && operation != RETRIEVE &&
	    get_ttc_whichplan(slot) != get_es_whichplan(estate)) {

	    set_es_junkFilter(estate, 
		  (JunkFilter) nth(get_ttc_whichplan(slot),
				   get_es_junkFilter_list(estate)));
	    set_es_result_relation_info(estate,
		  (RelationInfo) nth(get_ttc_whichplan(slot),
				     get_es_result_relation_info_list(estate)));

	    junkfilter = get_es_junkFilter(estate);
	    set_es_whichplan(estate, get_ttc_whichplan(slot));
	}
	    

	/* ----------------
d656 1
a656 1
	if (junkfilter != NULL) {
@


1.20
log
@must recursively count needed slots for plans for table allocation
@
text
@d14 1
a14 1
 *	$Header: /users/mer/pg/src/executor/RCS/ex_main.c,v 1.19 1992/07/13 17:36:25 hong Exp mer $
d23 1
a23 1
 RcsId("$Header: /users/mer/pg/src/executor/RCS/ex_main.c,v 1.19 1992/07/13 17:36:25 hong Exp mer $");
d470 1
a470 1
    
d638 2
a639 1
	slot = ExecProcNode(plan);
d668 1
a668 1
	if (TupIsNull((Pointer) slot)) {
d813 2
@


1.19
log
@finally got buffer refcounts for nested ExecMains right
@
text
@d14 1
a14 1
 *	$Header: RCS/ex_main.c,v 1.18 92/07/13 16:25:29 hong Exp Locker: hong $
d23 1
a23 1
 RcsId("$Header: RCS/ex_main.c,v 1.18 92/07/13 16:25:29 hong Exp Locker: hong $");
d367 3
a369 1
	TupleTable tupleTable = ExecCreateTupleTable(40);
@


1.18
log
@to prevent ExecMain's from unpinning each other's buffer
@
text
@d14 1
a14 1
 *	$Header: /home/postgres/hong/postgres/src/executor/RCS/ex_main.c,v 1.17 1992/07/04 04:29:28 mer Exp hong $
d23 1
a23 1
 RcsId("$Header: /home/postgres/hong/postgres/src/executor/RCS/ex_main.c,v 1.17 1992/07/04 04:29:28 mer Exp hong $");
a114 1
    extern int	ExecMainLevel;  /* defined in storage/buffer/bufmgr.c */
d163 11
a173 14
	ExecMainLevel++; /* increment ExecMain nesting level */
	if (ExecMainLevel > 1)
	    /* if this is not the first time ExecMain is called
	     * reset buffer refcount.  the current refcounts
	     * are saved and will be restored at the end of
	     * this ExecMain cycle.
	     *
	     * this makes sure that when ExecMain's are
	     * called recursively as for tuple level rules
	     * or postquel functions, the buffers pinned
	     * by one ExecMain will not be unpinned by another
	     * ExecMain.
	     */
	    BufferRefCountReset(get_es_refcount(estate));
d190 2
a191 6
	if (ExecMainLevel > 1)
	    /* if this is not the first time ExecMain is called,
	     * restore saved refcounts.
	     */
	    BufferRefCountRestore(get_es_refcount(estate));
	ExecMainLevel--; /* decrement ExecMain nesting level */
@


1.17
log
@compute tlist length correctly
@
text
@d14 1
a14 1
 *	$Header: /private/mer/pg/src/executor/RCS/ex_main.c,v 1.16 1992/06/22 22:49:25 mer Exp mer $
d23 1
a23 1
 RcsId("$Header: /private/mer/pg/src/executor/RCS/ex_main.c,v 1.16 1992/06/22 22:49:25 mer Exp mer $");
d115 1
d164 14
d194 6
@


1.16
log
@oops, forgot to close heap relations after replace / delete w/inheritance
@
text
@d14 1
a14 1
 *	$Header: /private/mer/pg2/src/executor/RCS/ex_main.c,v 1.15 1992/06/22 17:20:35 mer Exp mer $
d23 1
a23 1
 RcsId("$Header: /private/mer/pg2/src/executor/RCS/ex_main.c,v 1.15 1992/06/22 17:20:35 mer Exp mer $");
d373 1
a373 1
    tupType =    ExecGetTupType(plan); 		/* tuple descriptor */
d375 1
a375 1
    len = 	 length(targetList); 		/* number of attributes */
@


1.15
log
@changes to support delete / replace with inheritance (append plans)
@
text
@d14 1
a14 1
 *	$Header: /private/mer/pg2/src/executor/RCS/ex_main.c,v 1.14 1992/05/06 06:00:34 mer Exp mer $
d23 1
a23 1
 RcsId("$Header: /private/mer/pg2/src/executor/RCS/ex_main.c,v 1.14 1992/05/06 06:00:34 mer Exp mer $");
d481 1
d489 1
d509 1
a509 1
     *   close the result relation if necessary
d523 9
@


1.14
log
@semantic function name change
@
text
@d14 1
a14 1
 *	$Header: /users/mer/pg/src/executor/RCS/ex_main.c,v 1.13 1992/05/05 18:54:08 mer Exp mer $
d23 1
a23 1
 RcsId("$Header: /users/mer/pg/src/executor/RCS/ex_main.c,v 1.13 1992/05/05 18:54:08 mer Exp mer $");
d614 21
@


1.13
log
@add trivial functionality to return the last oid of newly appended tuples
@
text
@d14 1
a14 1
 *	$Header: /users/mer/pg/src/executor/RCS/ex_main.c,v 1.12 1992/03/07 19:10:57 hong Exp mer $
d23 1
a23 1
 RcsId("$Header: /users/mer/pg/src/executor/RCS/ex_main.c,v 1.12 1992/03/07 19:10:57 hong Exp mer $");
d972 1
a972 1
    UpdateLastOid(newId);
@


1.12
log
@fixed a bug in releasing buffers
@
text
@d14 1
a14 1
 *	$Header: RCS/ex_main.c,v 1.11 92/03/05 00:39:14 hong Exp Locker: hong $
d23 1
a23 1
 RcsId("$Header: RCS/ex_main.c,v 1.11 92/03/05 00:39:14 hong Exp Locker: hong $");
d877 1
d968 1
a968 1
    locks = heap_insert(resultRelationDesc, /* relation desc */
d972 1
@


1.11
log
@whacking out buffer leaks
@
text
@d14 1
a14 1
 *	$Header: RCS/ex_main.c,v 1.10 92/02/27 05:26:22 mer Exp $
d23 1
a23 1
 RcsId("$Header: RCS/ex_main.c,v 1.10 92/02/27 05:26:22 mer Exp $");
d1092 1
a1092 1
    ReleaseBuffer(rawTupleBuffer);
d1268 1
a1268 1
    ReleaseBuffer(oldTupleBuffer);
@


1.10
log
@init pointer so purify won't complain.
@
text
@d14 1
a14 1
 *	$Header: /users/mer/pg/src/executor/RCS/ex_main.c,v 1.9 1992/02/25 15:26:38 clarsen Exp mer $
d23 1
a23 1
 RcsId("$Header: /users/mer/pg/src/executor/RCS/ex_main.c,v 1.9 1992/02/25 15:26:38 clarsen Exp mer $");
d1092 1
d1268 1
@


1.9
log
@notification
@
text
@d14 1
a14 1
 *	$Header: RCS/ex_main.c,v 1.8 91/12/12 02:18:42 mer Exp Locker: clarsen $
d23 1
a23 1
 RcsId("$Header: RCS/ex_main.c,v 1.8 91/12/12 02:18:42 mer Exp Locker: clarsen $");
d569 1
a569 1
    ItemPointer		tupleid;
@


1.8
log
@make name string less than 16 characters.  It was 18 and was making me
paranoid!!
@
text
@d14 1
a14 1
 *	$Header: /users/mer/postgres/src/executor/RCS/ex_main.c,v 1.7 1991/11/17 21:10:46 mer Exp mer $
d23 1
a23 1
 RcsId("$Header: /users/mer/postgres/src/executor/RCS/ex_main.c,v 1.7 1991/11/17 21:10:46 mer Exp mer $");
d754 13
@


1.7
log
@prototyping
@
text
@d14 1
a14 1
 *	$Header: /users/mer/postgres/src/executor/RCS/ex_main.c,v 1.6 1991/11/14 10:57:55 glass Exp mer $
d23 1
a23 1
 RcsId("$Header: /users/mer/postgres/src/executor/RCS/ex_main.c,v 1.6 1991/11/14 10:57:55 glass Exp mer $");
d282 1
a282 1
    set_es_error_message(estate, (Name) "Foo bar and grill");
@


1.6
log
@fixes due to prototypes
@
text
@d14 1
a14 1
 *	$Header: RCS/ex_main.c,v 1.5 91/08/25 13:28:37 hong Exp Locker: glass $
d23 1
a23 1
 RcsId("$Header: RCS/ex_main.c,v 1.5 91/08/25 13:28:37 hong Exp Locker: glass $");
d424 1
a424 1
					     tupType);
@


1.5
log
@bug fix, return value type of a function screwed up
@
text
@d14 1
a14 1
 *	$Header: RCS/ex_main.c,v 1.4 91/07/24 16:08:25 hong Exp $
d18 1
a18 1
#include "tmp/postgres.h"
a19 15
 RcsId("$Header: RCS/ex_main.c,v 1.4 91/07/24 16:08:25 hong Exp $");

/* ----------------
 *	FILE INCLUDE ORDER GUIDELINES
 *
 *	1) execdebug.h
 *	2) various support files ("everything else")
 *	3) node files
 *	4) catalog/ files
 *	5) execdefs.h and execmisc.h
 *	6) externs.h comes last
 * ----------------
 */
#include "executor/execdebug.h"
#include "tcop/dest.h"
d21 1
d23 1
a23 2
#define EXEC_RULEMANAGER 1
#include "executor/execdebug.h"
a24 25
#include "tmp/align.h"
#include "access/printtup.h"
#include "parser/parse.h"
#include "parser/parsetree.h"
#include "utils/log.h"
#include "utils/mcxt.h"

#include "nodes/pg_lisp.h"
#include "nodes/primnodes.h"
#include "nodes/primnodes.a.h"
#include "nodes/plannodes.h"
#include "nodes/plannodes.a.h"
#include "nodes/execnodes.h"
#include "nodes/execnodes.a.h"
#include "nodes/mnodes.h"

#include "catalog/catname.h"

#include "storage/smgr.h"

#include "executor/execdefs.h"
#include "executor/execmisc.h"

#include "executor/externs.h"

d67 2
a68 2
    ConstTrue =  MakeConst(boolType, boolLen, datumTrue,  false);
    ConstFalse = MakeConst(boolType, boolLen, datumFalse, false);
d282 1
a282 1
    set_es_error_message(estate, "Foo bar and grill");
d365 1
a365 1
    ExecInitNode(plan, estate, 0, NULL);
d502 1
a502 1
	ExecDestroyTupleTable(tupleTable);
d620 1
a620 1
	if (TupIsNull(slot)) {
d706 2
a707 2
		ExecStoreTuple(newTuple, 	/* tuple to store */
			       slot, 		/* destination slot */
d804 2
a805 2
    tuple = (HeapTuple) ExecFetchTuple(slot);
    attrtype =		ExecSlotDescriptor(slot);
d869 1
a869 1
    tuple = (HeapTuple) ExecFetchTuple(slot);
d922 2
a923 2
	    ExecStoreTuple(returnedTuple,	/* tuple to store */
			   slot,		/* destination slot */
d1013 1
a1013 1
    tuple = (HeapTuple) ExecFetchTuple(slot);
d1166 1
a1166 1
    tuple = (HeapTuple) ExecFetchTuple(slot);
d1246 2
a1247 2
	    ExecStoreTuple(changedTuple,	/* tuple to store */
			   slot,		/* destination slot */
@


1.4
log
@use new shared memory manager for parallel executor
@
text
@d14 1
a14 1
 *	$Header: RCS/ex_main.c,v 1.3 91/07/22 22:20:21 mao Exp Locker: hong $
d20 1
a20 1
 RcsId("$Header: RCS/ex_main.c,v 1.3 91/07/22 22:20:21 mao Exp Locker: hong $");
d489 1
a489 1
		    SlaveInfoP[MyPid].resultTmpRelDesc = (Relation)
@


1.3
log
@jukebox storage manager installation
@
text
@d14 1
a14 1
 *	$Header: /users/mao/postgres/src/executor/RCS/ex_main.c,v 1.2 1991/07/17 23:52:20 hong Exp mao $
d20 1
a20 1
 RcsId("$Header: /users/mao/postgres/src/executor/RCS/ex_main.c,v 1.2 1991/07/17 23:52:20 hong Exp mao $");
d488 1
d490 1
a490 1
			CopyRelDescUsing(intoRelationDesc, ExecSMAlloc);
@


1.2
log
@changes to support inter-fragment and inter-query parallelism
fixed a bug that uses local buffers for parallel backends
@
text
@d14 1
a14 1
 *	$Header: RCS/ex_main.c,v 1.1 91/06/18 23:31:31 cimarron Exp Locker: hong $
d20 1
a20 1
 RcsId("$Header: RCS/ex_main.c,v 1.1 91/06/18 23:31:31 cimarron Exp Locker: hong $");
d58 2
d463 1
@


1.1
log
@Initial revision
@
text
@d14 1
a14 1
 *	$Header: RCS/execmain.c,v 1.45 91/05/27 01:01:36 kemnitz Exp Locker: cimarron $
d20 1
a20 1
 RcsId("$Header: RCS/execmain.c,v 1.45 91/05/27 01:01:36 kemnitz Exp Locker: cimarron $");
a278 2
extern ReturnState MakeReturnState();
extern ReturnState CopyReturnStateUsing();
a279 1
extern Pointer	   *SlaveRetStateP;
d292 1
a292 1
    Relation		intoRelationDesc;
d298 1
a298 1
    ReturnState		retstate;
d485 1
a485 1
		    intoRelationDesc = (Relation)
a487 6
                retstate = MakeReturnState();
		if (! IsMaster) {
                    retstate = CopyReturnStateUsing(retstate, ExecSMAlloc);
		}
		set_resultTmpRelDesc(retstate, intoRelationDesc);
		SlaveRetStateP[MyPid] = (Pointer)retstate;
d564 5
a568 1
	local_heap_close(intoRelationDesc);
d848 5
a852 1
	(void) local_heap_insert(intoRelationDesc, tuple);
@
