diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c
index 641fe3afc2d264ab8d3e47322cacd5b3d0588a93..34e1b2538fab778f270b61950639b565ee13cb64 100644
--- a/src/backend/executor/nodeMaterial.c
+++ b/src/backend/executor/nodeMaterial.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/nodeMaterial.c,v 1.52 2006/02/28 04:10:27 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/nodeMaterial.c,v 1.53 2006/02/28 05:48:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -58,9 +58,9 @@ ExecMaterial(MaterialState *node)
 	tuplestorestate = (Tuplestorestate *) node->tuplestorestate;
 
 	/*
-	 * If first time through, initialize the tuplestore.
+	 * If first time through, and we need a tuplestore, initialize it.
 	 */
-	if (tuplestorestate == NULL)
+	if (tuplestorestate == NULL && node->randomAccess)
 	{
 		tuplestorestate = tuplestore_begin_heap(true, false, work_mem);
 
@@ -71,7 +71,8 @@ ExecMaterial(MaterialState *node)
 	 * If we are not at the end of the tuplestore, or are going backwards, try
 	 * to fetch a tuple from tuplestore.
 	 */
-	eof_tuplestore = tuplestore_ateof(tuplestorestate);
+	eof_tuplestore = (tuplestorestate == NULL) ||
+		tuplestore_ateof(tuplestorestate);
 
 	if (!forward && eof_tuplestore)
 	{
@@ -135,7 +136,8 @@ ExecMaterial(MaterialState *node)
 		 * tuplestore is certainly in EOF state, its read position will move
 		 * forward over the added tuple.  This is what we want.
 		 */
-		tuplestore_puttuple(tuplestorestate, (void *) heapTuple);
+		if (tuplestorestate)
+			tuplestore_puttuple(tuplestorestate, (void *) heapTuple);
 	}
 
 	/*
@@ -165,8 +167,18 @@ ExecInitMaterial(Material *node, EState *estate, int eflags)
 	matstate->ss.ps.plan = (Plan *) node;
 	matstate->ss.ps.state = estate;
 
-	matstate->tuplestorestate = NULL;
+	/*
+	 * We must have random access to the subplan output to do backward scan
+	 * or mark/restore.  We also prefer to materialize the subplan output
+	 * if we might be called on to rewind and replay it many times.
+	 * However, if none of these cases apply, we can skip storing the data.
+	 */
+	matstate->randomAccess = (eflags & (EXEC_FLAG_REWIND |
+										EXEC_FLAG_BACKWARD |
+										EXEC_FLAG_MARK)) != 0;
+
 	matstate->eof_underlying = false;
+	matstate->tuplestorestate = NULL;
 
 	/*
 	 * Miscellaneous initialization
@@ -249,6 +261,8 @@ ExecEndMaterial(MaterialState *node)
 void
 ExecMaterialMarkPos(MaterialState *node)
 {
+	Assert(node->randomAccess);
+
 	/*
 	 * if we haven't materialized yet, just return.
 	 */
@@ -267,6 +281,8 @@ ExecMaterialMarkPos(MaterialState *node)
 void
 ExecMaterialRestrPos(MaterialState *node)
 {
+	Assert(node->randomAccess);
+
 	/*
 	 * if we haven't materialized yet, just return.
 	 */
@@ -288,29 +304,44 @@ ExecMaterialRestrPos(MaterialState *node)
 void
 ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt)
 {
-	/*
-	 * If we haven't materialized yet, just return. If outerplan' chgParam is
-	 * not NULL then it will be re-scanned by ExecProcNode, else - no reason
-	 * to re-scan it at all.
-	 */
-	if (!node->tuplestorestate)
-		return;
-
 	ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
 
-	/*
-	 * If subnode is to be rescanned then we forget previous stored results;
-	 * we have to re-read the subplan and re-store.
-	 *
-	 * Otherwise we can just rewind and rescan the stored output. The state of
-	 * the subnode does not change.
-	 */
-	if (((PlanState *) node)->lefttree->chgParam != NULL)
+	if (node->randomAccess)
 	{
-		tuplestore_end((Tuplestorestate *) node->tuplestorestate);
-		node->tuplestorestate = NULL;
-		node->eof_underlying = false;
+		/*
+		 * If we haven't materialized yet, just return. If outerplan' chgParam
+		 * is not NULL then it will be re-scanned by ExecProcNode, else - no
+		 * reason to re-scan it at all.
+		 */
+		if (!node->tuplestorestate)
+			return;
+
+		/*
+		 * If subnode is to be rescanned then we forget previous stored
+		 * results; we have to re-read the subplan and re-store.
+		 *
+		 * Otherwise we can just rewind and rescan the stored output. The
+		 * state of the subnode does not change.
+		 */
+		if (((PlanState *) node)->lefttree->chgParam != NULL)
+		{
+			tuplestore_end((Tuplestorestate *) node->tuplestorestate);
+			node->tuplestorestate = NULL;
+			node->eof_underlying = false;
+		}
+		else
+			tuplestore_rescan((Tuplestorestate *) node->tuplestorestate);
 	}
 	else
-		tuplestore_rescan((Tuplestorestate *) node->tuplestorestate);
+	{
+		/* In this case we are just passing on the subquery's output */
+
+		/*
+		 * if chgParam of subnode is not null then plan will be re-scanned by
+		 * first ExecProcNode.
+		 */
+		if (((PlanState *) node)->lefttree->chgParam == NULL)
+			ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
+		node->eof_underlying = false;
+	}
 }
diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c
index 367adbfbe20c2d073f5d8b066b01456a69c0d000..f799c78218a6c034576cd9312e13c06b84333185 100644
--- a/src/backend/executor/nodeSort.c
+++ b/src/backend/executor/nodeSort.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/nodeSort.c,v 1.54 2006/02/28 04:10:27 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/nodeSort.c,v 1.55 2006/02/28 05:48:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -89,7 +89,7 @@ ExecSort(SortState *node)
 											  plannode->sortOperators,
 											  plannode->sortColIdx,
 											  work_mem,
-											  true /* randomAccess */ );
+											  node->randomAccess);
 		node->tuplesortstate = (void *) tuplesortstate;
 
 		/*
@@ -164,6 +164,15 @@ ExecInitSort(Sort *node, EState *estate, int eflags)
 	sortstate->ss.ps.plan = (Plan *) node;
 	sortstate->ss.ps.state = estate;
 
+	/*
+	 * We must have random access to the sort output to do backward scan
+	 * or mark/restore.  We also prefer to materialize the sort output
+	 * if we might be called on to rewind and replay it many times.
+	 */
+	sortstate->randomAccess = (eflags & (EXEC_FLAG_REWIND |
+										 EXEC_FLAG_BACKWARD |
+										 EXEC_FLAG_MARK)) != 0;
+
 	sortstate->sort_Done = false;
 	sortstate->tuplesortstate = NULL;
 
@@ -308,11 +317,18 @@ ExecReScanSort(SortState *node, ExprContext *exprCtxt)
 	 *
 	 * Otherwise we can just rewind and rescan the sorted output.
 	 */
-	if (((PlanState *) node)->lefttree->chgParam != NULL)
+	if (((PlanState *) node)->lefttree->chgParam != NULL ||
+		!node->randomAccess)
 	{
 		node->sort_Done = false;
 		tuplesort_end((Tuplesortstate *) node->tuplesortstate);
 		node->tuplesortstate = NULL;
+		/*
+		 * if chgParam of subnode is not null then plan will be re-scanned by
+		 * first ExecProcNode.
+		 */
+		if (((PlanState *) node)->lefttree->chgParam == NULL)
+			ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
 	}
 	else
 		tuplesort_rescan((Tuplesortstate *) node->tuplesortstate);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index d07dc57297c3f7137602a5bc0f5342688bc260b9..f277672a1c471c9241e8d89a02cd265a303b184c 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.147 2005/12/28 01:30:01 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.148 2006/02/28 05:48:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1185,8 +1185,9 @@ typedef struct HashJoinState
 typedef struct MaterialState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	void	   *tuplestorestate;	/* private state of tuplestore.c */
+	bool		randomAccess;	/* need random access to subplan output? */
 	bool		eof_underlying; /* reached end of underlying plan? */
+	void	   *tuplestorestate;	/* private state of tuplestore.c */
 } MaterialState;
 
 /* ----------------
@@ -1196,6 +1197,7 @@ typedef struct MaterialState
 typedef struct SortState
 {
 	ScanState	ss;				/* its first field is NodeTag */
+	bool		randomAccess;	/* need random access to sort output? */
 	bool		sort_Done;		/* sort completed yet? */
 	void	   *tuplesortstate; /* private state of tuplesort.c */
 } SortState;