diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index c4d3ee50148efd0455bbf1e9edc1f340264645da..3cc687bdb70eb3607793569274745183057ce0a4 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -2645,8 +2645,7 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
 				InferenceElem *ie = (InferenceElem *) node;
 
 				APP_JUMB(ie->infercollid);
-				APP_JUMB(ie->inferopfamily);
-				APP_JUMB(ie->inferopcinputtype);
+				APP_JUMB(ie->inferopclass);
 				JumbleExpr(jstate, ie->expr);
 			}
 			break;
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index d36be3c80685ab698be8ffe724eecd64611ee6af..2d9bf419bdb57844e25d07b900f4eee5573f94c2 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -1839,8 +1839,7 @@ _copyInferenceElem(const InferenceElem *from)
 
 	COPY_NODE_FIELD(expr);
 	COPY_SCALAR_FIELD(infercollid);
-	COPY_SCALAR_FIELD(inferopfamily);
-	COPY_SCALAR_FIELD(inferopcinputtype);
+	COPY_SCALAR_FIELD(inferopclass);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index d7928a99176609ae83c5da20f695492576721055..f19251e7c415fb3a92b83a2f1e086fb1ea29a8f7 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -702,8 +702,7 @@ _equalInferenceElem(const InferenceElem *a, const InferenceElem *b)
 {
 	COMPARE_NODE_FIELD(expr);
 	COMPARE_SCALAR_FIELD(infercollid);
-	COMPARE_SCALAR_FIELD(inferopfamily);
-	COMPARE_SCALAR_FIELD(inferopcinputtype);
+	COMPARE_SCALAR_FIELD(inferopclass);
 
 	return true;
 }
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index fdd6032b4cb227b39d6fbb04e170671352962d48..54464f8c656096175f1c3e89f9dd0535d6d5c9b5 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -1474,8 +1474,7 @@ _outInferenceElem(StringInfo str, const InferenceElem *node)
 
 	WRITE_NODE_FIELD(expr);
 	WRITE_OID_FIELD(infercollid);
-	WRITE_OID_FIELD(inferopfamily);
-	WRITE_OID_FIELD(inferopcinputtype);
+	WRITE_OID_FIELD(inferopclass);
 }
 
 static void
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 6fd9d46ee7963f72d9b49b3f9a857aa013e7a8db..f5a40fbfb44b8d648a9aa32c1089055c4d3c70a6 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -1214,8 +1214,7 @@ _readInferenceElem(void)
 
 	READ_NODE_FIELD(expr);
 	READ_OID_FIELD(infercollid);
-	READ_OID_FIELD(inferopfamily);
-	READ_OID_FIELD(inferopcinputtype);
+	READ_OID_FIELD(inferopclass);
 
 	READ_DONE();
 }
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index b425680f47647f19eaa89da02cfac8d3c8d9f765..a857ba3526484f675ed9b165b5d53ff2ee9a9e81 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -438,8 +438,8 @@ infer_arbiter_indexes(PlannerInfo *root)
 	Bitmapset  *inferAttrs = NULL;
 	List	   *inferElems = NIL;
 
-	/* Result */
-	List	   *candidates = NIL;
+	/* Results */
+	List	   *results = NIL;
 
 	/*
 	 * Quickly return NIL for ON CONFLICT DO NOTHING without an inference
@@ -565,11 +565,11 @@ infer_arbiter_indexes(PlannerInfo *root)
 						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 						 errmsg("ON CONFLICT DO UPDATE not supported with exclusion constraints")));
 
-			candidates = lappend_oid(candidates, idxForm->indexrelid);
+			results = lappend_oid(results, idxForm->indexrelid);
 			list_free(indexList);
 			index_close(idxRel, NoLock);
 			heap_close(relation, NoLock);
-			return candidates;
+			return results;
 		}
 		else if (indexOidFromConstraint != InvalidOid)
 		{
@@ -633,7 +633,7 @@ infer_arbiter_indexes(PlannerInfo *root)
 			 * index definition.
 			 */
 			if (elem->infercollid != InvalidOid ||
-				elem->inferopfamily != InvalidOid ||
+				elem->inferopclass != InvalidOid ||
 				list_member(idxExprs, elem->expr))
 				continue;
 
@@ -660,7 +660,7 @@ infer_arbiter_indexes(PlannerInfo *root)
 		if (!predicate_implied_by(predExprs, whereExplicit))
 			goto next;
 
-		candidates = lappend_oid(candidates, idxForm->indexrelid);
+		results = lappend_oid(results, idxForm->indexrelid);
 next:
 		index_close(idxRel, NoLock);
 	}
@@ -668,12 +668,12 @@ next:
 	list_free(indexList);
 	heap_close(relation, NoLock);
 
-	if (candidates == NIL)
+	if (results == NIL)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
 				 errmsg("there is no unique or exclusion constraint matching the ON CONFLICT specification")));
 
-	return candidates;
+	return results;
 }
 
 /*
@@ -709,23 +709,33 @@ infer_collation_opclass_match(InferenceElem *elem, Relation idxRel,
 							  Bitmapset *inferAttrs, List *idxExprs)
 {
 	AttrNumber	natt;
+	Oid			inferopfamily = InvalidOid;		/* OID of att opfamily */
+	Oid			inferopcinputtype = InvalidOid;		/* OID of att opfamily */
 
 	/*
 	 * If inference specification element lacks collation/opclass, then no
 	 * need to check for exact match.
 	 */
-	if (elem->infercollid == InvalidOid && elem->inferopfamily == InvalidOid)
+	if (elem->infercollid == InvalidOid && elem->inferopclass == InvalidOid)
 		return true;
 
+	/*
+	 * Lookup opfamily and input type, for matching indexes
+	 */
+	if (elem->inferopclass)
+	{
+		inferopfamily = get_opclass_family(elem->inferopclass);
+		inferopcinputtype = get_opclass_input_type(elem->inferopclass);
+	}
+
 	for (natt = 1; natt <= idxRel->rd_att->natts; natt++)
 	{
 		Oid		opfamily = idxRel->rd_opfamily[natt - 1];
 		Oid		opcinputtype = idxRel->rd_opcintype[natt - 1];
 		Oid		collation = idxRel->rd_indcollation[natt - 1];
 
-		if (elem->inferopfamily != InvalidOid &&
-			(elem->inferopfamily != opfamily ||
-			 elem->inferopcinputtype != opcinputtype))
+		if (elem->inferopclass != InvalidOid &&
+			(inferopfamily != opfamily || inferopcinputtype != opcinputtype))
 		{
 			/* Attribute needed to match opclass, but didn't */
 			continue;
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index a90bcf40c9d948f8cad385672fda9e459d0035b2..c8af5ab1d050d40002bebf4643926cd776d86fce 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -2730,18 +2730,10 @@ resolve_unique_index_expr(ParseState *pstate, InferClause *infer,
 												  exprLocation(pInfer->expr));
 
 		if (!ielem->opclass)
-		{
-			pInfer->inferopfamily = InvalidOid;
-			pInfer->inferopcinputtype = InvalidOid;
-		}
+			pInfer->inferopclass = InvalidOid;
 		else
-		{
-			Oid		opclass = get_opclass_oid(BTREE_AM_OID, ielem->opclass,
-											  false);
-
-			pInfer->inferopfamily = get_opclass_family(opclass);
-			pInfer->inferopcinputtype = get_opclass_input_type(opclass);
-		}
+			pInfer->inferopclass = get_opclass_oid(BTREE_AM_OID,
+												   ielem->opclass, false);
 
 		result = lappend(result, pInfer);
 	}
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index a5467c5379918b3eb5abc01c5a1c13a4395e8d11..9f3a7267a27c486989813aea9fab870c328c99ef 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -1198,8 +1198,7 @@ typedef struct InferenceElem
 	Expr		xpr;
 	Node	   *expr;				/* expression to infer from, or NULL */
 	Oid			infercollid;		/* OID of collation, or InvalidOid */
-	Oid			inferopfamily;		/* OID of att opfamily, or InvalidOid */
-	Oid			inferopcinputtype;	/* OID of att input type, or InvalidOid */
+	Oid			inferopclass;		/* OID of att opclass, or InvalidOid */
 } InferenceElem;
 
 /*--------------------