diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index f8a4017..4ce45e3 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -1189,7 +1189,7 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
  */
 bool
 ExecCheckIndexConstraints(TupleTableSlot *slot,
-						  EState *estate, ItemPointer conflictTid,
+						  EState *estate, HeapTuple conflictTid,
 						  Oid arbiterIdx)
 {
 	ResultRelInfo *resultRelInfo;
@@ -1339,7 +1339,7 @@ check_exclusion_or_unique_constraint(Relation heap, Relation index,
 									 Datum *values, bool *isnull,
 									 EState *estate, bool newIndex,
 									 bool violationOK, bool wait,
-									 ItemPointer conflictTid)
+									 HeapTuple conflictTid)
 {
 	Oid		   *constr_procs;
 	uint16	   *constr_strats;
@@ -1469,7 +1469,10 @@ retry:
 		{
 			conflict = true;
 			if (conflictTid)
-				*conflictTid = tup->t_self;
+			{
+				conflictTid->t_self = tup->t_self;
+				conflictTid->t_data = tup->t_data;
+			}
 			break;
 		}
 
@@ -1506,7 +1509,10 @@ retry:
 		{
 			conflict = true;
 			if (conflictTid)
-				*conflictTid = tup->t_self;
+			{
+				conflictTid->t_self = tup->t_self;
+				conflictTid->t_data = tup->t_data;
+			}
 			break;
 		}
 
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 69af2d1..a289ef4 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -56,7 +56,7 @@
 
 static bool ExecLockUpdateTuple(EState *estate,
 								ResultRelInfo *relinfo,
-								ItemPointer conflictTid,
+								HeapTuple 	conflictTid,
 								TupleTableSlot *planSlot,
 								TupleTableSlot *insertSlot,
 								bool			canSetTag,
@@ -292,7 +292,7 @@ ExecInsert(TupleTableSlot *slot,
 	else
 	{
 		bool				conflict;
-		ItemPointerData		conflictTid;
+		HeapTupleData conflictTid;
 
 		/*
 		 * Constraints might reference the tableoid column, so initialize
@@ -315,7 +315,7 @@ ExecInsert(TupleTableSlot *slot,
 		 */
 vlock:
 		conflict = false;
-		ItemPointerSetInvalid(&conflictTid);
+		ItemPointerSetInvalid(&conflictTid.t_self);
 
 		/*
 		 * XXX If we know or assume that there are few duplicates, it would be
@@ -432,7 +432,7 @@ vlock:
 															&returning))
 					goto vlock;
 			else if (spec == SPEC_IGNORE)
-				ExecCheckHeapTupleVisible(estate, resultRelInfo, &conflictTid);
+				ExecCheckHeapTupleVisible(estate, resultRelInfo, &conflictTid.t_self);
 
 			/*
 			 * RETURNING may have been processed already -- the target
@@ -976,7 +976,7 @@ lreplace:;
 static bool
 ExecLockUpdateTuple(EState *estate,
 					ResultRelInfo *relinfo,
-					ItemPointer conflictTid,
+					HeapTuple 	conflictTid,
 					TupleTableSlot *planSlot,
 					TupleTableSlot *insertSlot,
 					bool			canSetTag,
@@ -999,7 +999,7 @@ ExecLockUpdateTuple(EState *estate,
 	 * now, we just retry, and hopefully the new pre-check will fail on the
 	 * same tuple (or it's finished by now), and we'll get its TID that way.
 	 */
-	if (!ItemPointerIsValid(conflictTid))
+	if (!ItemPointerIsValid(&conflictTid->t_self))
 	{
 		elog(DEBUG1, "insertion conflicted after pre-check");
 		return false;
@@ -1013,15 +1013,15 @@ ExecLockUpdateTuple(EState *estate,
 	 * our previous conclusion that the tuple is the conclusively committed
 	 * conflicting tuple.
 	 */
-	tuple.t_self = *conflictTid;
+	tuple.t_self = conflictTid->t_self;
 	test = heap_lock_tuple(relation, &tuple,
 						   estate->es_output_cid,
-						   LockTupleExclusive, false, /* wait */
+						   LockTupleExclusive, LockWaitBlock,
 						   false, &buffer, &hufd);
 
 	/* Was tuple concurrently super-deleted? */
 	if (TransactionIdEquals(HeapTupleHeaderGetRawXmin(tuple.t_data),
-							 InvalidTransactionId))
+							InvalidTransactionId))
 	{
 		test = HeapTupleUpdated;
 		/* XXX Should be caught within tqual.c */
@@ -1157,6 +1157,16 @@ ExecLockUpdateTuple(EState *estate,
 
 			slot = EvalPlanQualNext(&onConflict->mt_epqstate);
 
+			if (copyTuple->t_data->t_choice.t_heap.t_xmin !=
+				conflictTid->t_data->t_choice.t_heap.t_xmin)
+			{
+				elog(ERROR, "mismatch in xmin for (%u,%u). Initially %u, then %u",
+					 ItemPointerGetBlockNumber(&copyTuple->t_data->t_ctid),
+					 ItemPointerGetOffsetNumber(&copyTuple->t_data->t_ctid),
+					 copyTuple->t_data->t_choice.t_heap.t_xmin,
+					 conflictTid->t_data->t_choice.t_heap.t_xmin);
+			}
+
 			if (!TupIsNull(slot))
 				*returning = ExecUpdate(&tuple.t_data->t_ctid, NULL, slot,
 										planSlot, &onConflict->mt_epqstate,
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index e7c16fb..abd7741 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -2288,12 +2288,14 @@ transformConflictClause(ParseState *pstate, ConflictClause *confClause,
 {
 	InferClause	   *infer = confClause->infer;
 
+#if 0
 	if (confClause->specclause == SPEC_INSERT && !infer)
 		ereport(ERROR,
 				(errcode(ERRCODE_SYNTAX_ERROR),
 				 errmsg("ON CONFLICT with UPDATE must contain columns or expressions to infer a unique index from"),
 				 parser_errposition(pstate,
 									exprLocation((Node *) confClause))));
+#endif
 
 	/* Raw grammar must ensure this invariant holds */
 	Assert(confClause->specclause != SPEC_INSERT ||
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 4cdf958..b668619 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -359,14 +359,14 @@ extern List *ExecLockIndexValues(TupleTableSlot *slot, EState *estate,
 extern List *ExecInsertIndexTuples(TupleTableSlot *slot, ItemPointer tupleid,
 					  EState *estate, bool noDupErr, Oid arbiterIdx);
 extern bool ExecCheckIndexConstraints(TupleTableSlot *slot, EState *estate,
-					  ItemPointer conflictTid, Oid arbiterIdx);
+					  HeapTuple conflictTid, Oid arbiterIdx);
 extern bool check_exclusion_or_unique_constraint(Relation heap, Relation index,
 									   IndexInfo *indexInfo,
 									   ItemPointer tupleid,
 									   Datum *values, bool *isnull,
 									   EState *estate,
 									   bool newIndex, bool errorOK,
-									   bool wait, ItemPointer conflictTid);
+									   bool wait, HeapTuple conflictTid);
 
 extern void RegisterExprContextCallback(ExprContext *econtext,
 							ExprContextCallbackFunction function,
