*** a/contrib/postgres_fdw/postgres_fdw.c
--- b/contrib/postgres_fdw/postgres_fdw.c
***************
*** 4502,4519 **** make_tuple_from_result_row(PGresult *res,
  	if (ctid)
  		tuple->t_self = tuple->t_data->t_ctid = *ctid;
  
- 	/*
- 	 * Stomp on the xmin, xmax, and cmin fields from the tuple created by
- 	 * heap_form_tuple.  heap_form_tuple actually creates the tuple with
- 	 * DatumTupleFields, not HeapTupleFields, but the executor expects
- 	 * HeapTupleFields and will happily extract system columns on that
- 	 * assumption.  If we don't do this then, for example, the tuple length
- 	 * ends up in the xmin field, which isn't what we want.
- 	 */
- 	HeapTupleHeaderSetXmax(tuple->t_data, InvalidTransactionId);
- 	HeapTupleHeaderSetXmin(tuple->t_data, InvalidTransactionId);
- 	HeapTupleHeaderSetCmin(tuple->t_data, InvalidTransactionId);
- 
  	/* Clean up */
  	MemoryContextReset(temp_context);
  
--- 4502,4507 ----
*** a/src/backend/executor/execMain.c
--- b/src/backend/executor/execMain.c
***************
*** 2555,2560 **** EvalPlanQualFetchRowMarks(EPQState *epqstate)
--- 2555,2561 ----
  		Datum		datum;
  		bool		isNull;
  		HeapTupleData tuple;
+ 		HeapTuple	copyTuple;
  
  		if (RowMarkRequiresRowShareLock(erm->markType))
  			elog(ERROR, "EvalPlanQual doesn't support locking rowmarks");
***************
*** 2585,2592 **** EvalPlanQualFetchRowMarks(EPQState *epqstate)
  
  		if (erm->markType == ROW_MARK_REFERENCE)
  		{
- 			HeapTuple	copyTuple;
- 
  			Assert(erm->relation != NULL);
  
  			/* fetch the tuple's ctid */
--- 2586,2591 ----
***************
*** 2664,2672 **** EvalPlanQualFetchRowMarks(EPQState *epqstate)
  			/* also copy t_ctid in case there's valid data there */
  			tuple.t_self = td->t_ctid;
  
! 			/* copy and store tuple */
! 			EvalPlanQualSetTuple(epqstate, erm->rti,
! 								 heap_copytuple(&tuple));
  		}
  	}
  }
--- 2663,2677 ----
  			/* also copy t_ctid in case there's valid data there */
  			tuple.t_self = td->t_ctid;
  
! 			/* copy tuple */
! 			copyTuple = heap_copytuple(&tuple);
! 			/* then zero xmin, xmax, and cid, as described above */
! 			HeapTupleHeaderSetXmin(copyTuple->t_data, InvalidTransactionId);
! 			HeapTupleHeaderSetXmax(copyTuple->t_data, InvalidTransactionId);
! 			HeapTupleHeaderSetCmin(copyTuple->t_data, InvalidTransactionId);
! 
! 			/* store tuple */
! 			EvalPlanQualSetTuple(epqstate, erm->rti, copyTuple);
  		}
  	}
  }
*** a/src/backend/executor/nodeForeignscan.c
--- b/src/backend/executor/nodeForeignscan.c
***************
*** 22,27 ****
--- 22,28 ----
   */
  #include "postgres.h"
  
+ #include "access/htup_details.h"
  #include "executor/executor.h"
  #include "executor/nodeForeignscan.h"
  #include "foreign/fdwapi.h"
***************
*** 58,70 **** ForeignNext(ForeignScanState *node)
  	 * If any system columns are requested, we have to force the tuple into
  	 * physical-tuple form to avoid "cannot extract system attribute from
  	 * virtual tuple" errors later.  We also insert a valid value for
! 	 * tableoid, which is the only actually-useful system column.
  	 */
  	if (plan->fsSystemCol && !TupIsNull(slot))
  	{
  		HeapTuple	tup = ExecMaterializeSlot(slot);
  
  		tup->t_tableOid = RelationGetRelid(node->ss.ss_currentRelation);
  	}
  
  	return slot;
--- 59,76 ----
  	 * If any system columns are requested, we have to force the tuple into
  	 * physical-tuple form to avoid "cannot extract system attribute from
  	 * virtual tuple" errors later.  We also insert a valid value for
! 	 * tableoid, which is the only actually-useful system column, and zero
! 	 * the xmin, xmax, and cid of the tuple.
  	 */
  	if (plan->fsSystemCol && !TupIsNull(slot))
  	{
  		HeapTuple	tup = ExecMaterializeSlot(slot);
  
  		tup->t_tableOid = RelationGetRelid(node->ss.ss_currentRelation);
+ 
+ 		HeapTupleHeaderSetXmin(tup->t_data, InvalidTransactionId);
+ 		HeapTupleHeaderSetXmax(tup->t_data, InvalidTransactionId);
+ 		HeapTupleHeaderSetCmin(tup->t_data, InvalidTransactionId);
  	}
  
  	return slot;
