diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index a5e27227cf2ca63321bd237f47ab5e98e256bd31..aac9f2599f52cecd69f71739af94bb848f0bcc9f 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -42,7 +42,7 @@ void		FreeTriggerDesc(Relation relation);
 
 static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger);
 static HeapTuple GetTupleForTrigger(EState *estate, ItemPointer tid,
-				   bool before);
+				   TupleTableSlot **newSlot);
 
 extern GlobalMemory CacheCxt;
 
@@ -664,9 +664,10 @@ ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid)
 	Trigger		  **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_DELETE];
 	HeapTuple		trigtuple;
 	HeapTuple		newtuple = NULL;
+	TupleTableSlot *newSlot;
 	int				i;
 
-	trigtuple = GetTupleForTrigger(estate, tupleid, true);
+	trigtuple = GetTupleForTrigger(estate, tupleid, &newSlot);
 	if (trigtuple == NULL)
 		return false;
 
@@ -701,7 +702,7 @@ ExecARDeleteTriggers(EState *estate, ItemPointer tupleid)
 	HeapTuple	trigtuple;
 	int			i;
 
-	trigtuple = GetTupleForTrigger(estate, tupleid, false);
+	trigtuple = GetTupleForTrigger(estate, tupleid, NULL);
 	Assert(trigtuple != NULL);
 
 	SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
@@ -732,12 +733,20 @@ ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
 	HeapTuple		trigtuple;
 	HeapTuple		oldtuple;
 	HeapTuple		intuple = newtuple;
+	TupleTableSlot *newSlot;
 	int				i;
 
-	trigtuple = GetTupleForTrigger(estate, tupleid, true);
+	trigtuple = GetTupleForTrigger(estate, tupleid, &newSlot);
 	if (trigtuple == NULL)
 		return NULL;
 
+	/*
+	 * In READ COMMITTED isolevel it's possible that newtuple
+	 * was changed due to concurrent update.
+	 */
+	if (newSlot != NULL)
+		intuple = newtuple = ExecRemoveJunk(estate->es_junkFilter, newSlot);
+
 	SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
 	SaveTriggerData->tg_event =
 		TRIGGER_EVENT_UPDATE | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE;
@@ -770,7 +779,7 @@ ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
 	HeapTuple	trigtuple;
 	int			i;
 
-	trigtuple = GetTupleForTrigger(estate, tupleid, false);
+	trigtuple = GetTupleForTrigger(estate, tupleid, NULL);
 	Assert(trigtuple != NULL);
 
 	SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
@@ -794,20 +803,21 @@ ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
 extern	TupleTableSlot *EvalPlanQual(EState *estate, Index rti, ItemPointer tid);
 
 static HeapTuple
-GetTupleForTrigger(EState *estate, ItemPointer tid, bool before)
+GetTupleForTrigger(EState *estate, ItemPointer tid, TupleTableSlot **newSlot)
 {
 	Relation		relation = estate->es_result_relation_info->ri_RelationDesc;
 	HeapTupleData	tuple;
 	HeapTuple		result;
 	Buffer			buffer;
 
-	if (before)
+	if (newSlot != NULL)
 	{
 		int		test;
 
 		/*
 		 *	mark tuple for update
 		 */
+		*newSlot = NULL;
 		tuple.t_self = *tid;
 ltrmark:;
 		test = heap_mark4update(relation, &tuple, &buffer);
@@ -826,13 +836,14 @@ ltrmark:;
 					elog(ERROR, "Can't serialize access due to concurrent update");
 				else if (!(ItemPointerEquals(&(tuple.t_self), tid)))
 				{
-					TupleTableSlot *slot = EvalPlanQual(estate, 
+					TupleTableSlot *epqslot = EvalPlanQual(estate, 
 						estate->es_result_relation_info->ri_RangeTableIndex, 
 						&(tuple.t_self));
 
-					if (!(TupIsNull(slot)))
+					if (!(TupIsNull(epqslot)))
 					{
 						*tid = tuple.t_self;
+						*newSlot = epqslot;
 						goto ltrmark;
 					}
 				}
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index ba4d09eaa38ff5439e9c6e0a93090aa29c70cb70..f074ce951fd7cf4e65496529a9b0e840764737a2 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -26,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.67 1999/01/29 10:15:09 vadim Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.68 1999/01/29 11:56:00 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -66,7 +66,7 @@ static void EndPlan(Plan *plan, EState *estate);
 static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan,
 			CmdType operation, int numberTuples, ScanDirection direction,
 			DestReceiver *destfunc);
-static void ExecRetrieve(TupleTableSlot *slot, 
+static void ExecRetrieve(TupleTableSlot *slot,
 						 DestReceiver *destfunc,
 						 EState *estate);
 static void ExecAppend(TupleTableSlot *slot, ItemPointer tupleid,
@@ -170,11 +170,11 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate)
 TupleTableSlot *
 ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
 {
-	CmdType		operation;
-	Plan	   *plan;
+	CmdType			operation;
+	Plan		   *plan;
 	TupleTableSlot *result;
-	CommandDest dest;
-	void		(*destination) ();
+	CommandDest		dest;
+	DestReceiver   *destfunc;
 
 	/******************
 	 *	sanity checks
@@ -190,10 +190,19 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
 	operation = queryDesc->operation;
 	plan = queryDesc->plantree;
 	dest = queryDesc->dest;
-	destination = (void (*) ()) DestToFunction(dest);
+	destfunc = DestToFunction(dest);
 	estate->es_processed = 0;
 	estate->es_lastoid = InvalidOid;
 
+	/******************
+	 *	FIXME: the dest setup function ought to be handed the tuple desc
+	 *  for the tuples to be output, but I'm not quite sure how to get that
+	 *  info at this point.  For now, passing NULL is OK because no existing
+	 *  dest setup function actually uses the pointer.
+	 ******************
+	 */
+	(*destfunc->setup) (destfunc, (TupleDesc) NULL);
+
 	switch (feature)
 	{
 
@@ -203,7 +212,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
 								 operation,
 								 ALL_TUPLES,
 								 ForwardScanDirection,
-								 destination);
+								 destfunc);
 			break;
 		case EXEC_FOR:
 			result = ExecutePlan(estate,
@@ -211,7 +220,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
 								 operation,
 								 count,
 								 ForwardScanDirection,
-								 destination);
+								 destfunc);
 			break;
 
 			/******************
@@ -224,7 +233,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
 								 operation,
 								 count,
 								 BackwardScanDirection,
-								 destination);
+								 destfunc);
 			break;
 
 			/******************
@@ -238,7 +247,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
 								 operation,
 								 ONE_TUPLE,
 								 ForwardScanDirection,
-								 destination);
+								 destfunc);
 			break;
 		default:
 			result = NULL;
@@ -246,6 +255,8 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
 			break;
 	}
 
+	(*destfunc->cleanup) (destfunc);
+
 	return result;
 }
 
@@ -756,7 +767,7 @@ ExecutePlan(EState *estate,
 			CmdType operation,
 			int numberTuples,
 			ScanDirection direction,
-			DestReceiver *destfunc)
+			DestReceiver* destfunc)
 {
 	JunkFilter *junkfilter;
 
@@ -941,7 +952,7 @@ lmark:;
 		{
 			case CMD_SELECT:
 				ExecRetrieve(slot,		/* slot containing tuple */
-							 destfunc,	/* print function */
+							 destfunc,	/* destination's tuple-receiver obj */
 							 estate);	/* */
 				result = slot;
 				break;
@@ -1024,7 +1035,7 @@ ExecRetrieve(TupleTableSlot *slot,
 	 *	send the tuple to the front end (or the screen)
 	 ******************
 	 */
-	(*printfunc) (tuple, attrtype);
+	(*destfunc->receiveTuple) (tuple, attrtype, destfunc);
 	IncrRetrieved();
 	(estate->es_processed)++;
 }
diff --git a/src/pl/plpgsql/src/gram.c b/src/pl/plpgsql/src/gram.c
index 2d4ef46a1b14382f66b533452f43a648f69b72e6..2ca9936c32e927c7522a72e484e16f90563b69f4 100644
--- a/src/pl/plpgsql/src/gram.c
+++ b/src/pl/plpgsql/src/gram.c
@@ -65,7 +65,7 @@
  *			  procedural language
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/pl/plpgsql/src/Attic/gram.c,v 1.3 1999/01/28 11:50:41 wieck Exp $
+ *    $Header: /cvsroot/pgsql/src/pl/plpgsql/src/Attic/gram.c,v 1.4 1999/01/29 11:56:01 vadim Exp $
  *
  *    This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -414,7 +414,7 @@ static const short yycheck[] = {    21,
    152,    62
 };
 /* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
-#line 3 "/usr/share/bison.simple"
+#line 3 "/usr/share/misc/bison.simple"
 
 /* Skeleton output parser for bison,
    Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
@@ -467,16 +467,6 @@ void *alloca ();
 #endif /* not GNU C.  */
 #endif /* alloca not defined.  */
 
-#ifdef __cplusplus
-extern "C" {
-  void yyerror(char *);
-  int yylex();
-};
-#else
-  extern void yyerror(char *);
-  extern int yylex();
-#endif
-
 /* This is the parser code that is written into each bison parser
   when the %semantic_parser declaration is not specified in the grammar.
   It was written by Richard Stallman by simplifying the hairy parser
@@ -573,13 +563,9 @@ int yydebug;			/*  nonzero means print parse trace	*/
 #define YYMAXDEPTH 10000
 #endif
 
-#ifndef YYPARSE_RETURN_TYPE
-#define YYPARSE_RETURN_TYPE int
-#endif
-
 /* Prevent warning if -Wstrict-prototypes.  */
 #ifdef __GNUC__
-YYPARSE_RETURN_TYPE yyparse (void);
+int yyparse (void);
 #endif
 
 #if __GNUC__ > 1		/* GNU C and GNU C++ define this.  */
@@ -621,7 +607,7 @@ __yy_memcpy (char *to, char *from, int count)
 #endif
 #endif
 
-#line 196 "/usr/share/bison.simple"
+#line 196 "/usr/share/misc/bison.simple"
 
 /* The user can define YYPARSE_PARAM as the name of an argument to be passed
    into yyparse.  The argument should have type void *.
@@ -642,7 +628,7 @@ __yy_memcpy (char *to, char *from, int count)
 #define YYPARSE_PARAM_DECL
 #endif /* not YYPARSE_PARAM */
 
-YYPARSE_RETURN_TYPE
+int
 yyparse(YYPARSE_PARAM_ARG)
      YYPARSE_PARAM_DECL
 {
@@ -1905,7 +1891,7 @@ case 105:
     break;}
 }
    /* the action file gets copied in in place of this dollarsign */
-#line 498 "/usr/share/bison.simple"
+#line 498 "/usr/share/misc/bison.simple"
 
   yyvsp -= yylen;
   yyssp -= yylen;