diff --git a/contrib/btree_gin/btree_gin.c b/contrib/btree_gin/btree_gin.c
index 144f6db18466ae02c097bf84d2002104c3b666de..7ca153e0928930199154977deb8a29b8cfdc3da3 100644
--- a/contrib/btree_gin/btree_gin.c
+++ b/contrib/btree_gin/btree_gin.c
@@ -121,7 +121,7 @@ gin_compare_prefix_##type(PG_FUNCTION_ARGS)									\
 	int32		res,														\
 				cmp;														\
 																			\
-	cmp = DatumGetInt32(DirectFunctionCall2WithCollation(					\
+	cmp = DatumGetInt32(DirectFunctionCall2Coll(							\
 				TypeInfo_##type.typecmp,									\
 				DEFAULT_COLLATION_OID,										\
 				(data->strategy == BTLessStrategyNumber ||					\
diff --git a/contrib/btree_gist/btree_text.c b/contrib/btree_gist/btree_text.c
index 665dfe78b449eb340e85817eff8640db5bbb5a5b..c6b57f82de9875776bd39e731a6a06a296486d03 100644
--- a/contrib/btree_gist/btree_text.c
+++ b/contrib/btree_gist/btree_text.c
@@ -33,37 +33,55 @@ Datum		gbt_text_same(PG_FUNCTION_ARGS);
 static bool
 gbt_textgt(const void *a, const void *b)
 {
-	return (DatumGetBool(DirectFunctionCall2WithCollation(text_gt, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b))));
+	return DatumGetBool(DirectFunctionCall2Coll(text_gt,
+												DEFAULT_COLLATION_OID,
+												PointerGetDatum(a),
+												PointerGetDatum(b)));
 }
 
 static bool
 gbt_textge(const void *a, const void *b)
 {
-	return (DatumGetBool(DirectFunctionCall2WithCollation(text_ge, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b))));
+	return DatumGetBool(DirectFunctionCall2Coll(text_ge,
+												DEFAULT_COLLATION_OID,
+												PointerGetDatum(a),
+												PointerGetDatum(b)));
 }
 
 static bool
 gbt_texteq(const void *a, const void *b)
 {
-	return (DatumGetBool(DirectFunctionCall2WithCollation(texteq, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b))));
+	return DatumGetBool(DirectFunctionCall2Coll(texteq,
+												DEFAULT_COLLATION_OID,
+												PointerGetDatum(a),
+												PointerGetDatum(b)));
 }
 
 static bool
 gbt_textle(const void *a, const void *b)
 {
-	return (DatumGetBool(DirectFunctionCall2WithCollation(text_le, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b))));
+	return DatumGetBool(DirectFunctionCall2Coll(text_le,
+												DEFAULT_COLLATION_OID,
+												PointerGetDatum(a),
+												PointerGetDatum(b)));
 }
 
 static bool
 gbt_textlt(const void *a, const void *b)
 {
-	return (DatumGetBool(DirectFunctionCall2WithCollation(text_lt, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b))));
+	return DatumGetBool(DirectFunctionCall2Coll(text_lt,
+												DEFAULT_COLLATION_OID,
+												PointerGetDatum(a),
+												PointerGetDatum(b)));
 }
 
 static int32
 gbt_textcmp(const bytea *a, const bytea *b)
 {
-	return DatumGetInt32(DirectFunctionCall2WithCollation(bttextcmp, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b)));
+	return DatumGetInt32(DirectFunctionCall2Coll(bttextcmp,
+												 DEFAULT_COLLATION_OID,
+												 PointerGetDatum(a),
+												 PointerGetDatum(b)));
 }
 
 static gbtree_vinfo tinfo =
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index d2e0531e3548c5811ea898c6c5e8dee7987f0837..465742556f5b990b9bff095e757802477c01d299 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -1206,7 +1206,7 @@ index_reloptions(RegProcedure amoptions, Datum reloptions, bool validate)
 	/* Can't use OidFunctionCallN because we might get a NULL result */
 	fmgr_info(amoptions, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 2, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, &flinfo, 2, InvalidOid, NULL, NULL);
 
 	fcinfo.arg[0] = reloptions;
 	fcinfo.arg[1] = BoolGetDatum(validate);
diff --git a/src/backend/access/common/scankey.c b/src/backend/access/common/scankey.c
index b632408da4732eaeba661bbd525e898971c44f60..c879b8aaa44f861a37535db085347b46b88fa7ea 100644
--- a/src/backend/access/common/scankey.c
+++ b/src/backend/access/common/scankey.c
@@ -42,11 +42,11 @@ ScanKeyEntryInitialize(ScanKey entry,
 	entry->sk_attno = attributeNumber;
 	entry->sk_strategy = strategy;
 	entry->sk_subtype = subtype;
+	entry->sk_collation = collation;
 	entry->sk_argument = argument;
 	if (RegProcedureIsValid(procedure))
 	{
 		fmgr_info(procedure, &entry->sk_func);
-		entry->sk_func.fn_collation = collation;
 	}
 	else
 	{
@@ -83,9 +83,9 @@ ScanKeyInit(ScanKey entry,
 	entry->sk_attno = attributeNumber;
 	entry->sk_strategy = strategy;
 	entry->sk_subtype = InvalidOid;
+	entry->sk_collation = DEFAULT_COLLATION_OID;
 	entry->sk_argument = argument;
 	fmgr_info(procedure, &entry->sk_func);
-	entry->sk_func.fn_collation = DEFAULT_COLLATION_OID;
 }
 
 /*
@@ -111,7 +111,7 @@ ScanKeyEntryInitializeWithInfo(ScanKey entry,
 	entry->sk_attno = attributeNumber;
 	entry->sk_strategy = strategy;
 	entry->sk_subtype = subtype;
+	entry->sk_collation = collation;
 	entry->sk_argument = argument;
 	fmgr_info_copy(&entry->sk_func, finfo, CurrentMemoryContext);
-	entry->sk_func.fn_collation = collation;
 }
diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index a4771654a6d129439f2bf2a9842de30b7cfbae85..227f84d9881b6cf7ddd02c2d3eb7354adc130bd0 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -55,15 +55,16 @@ callConsistentFn(GinState *ginstate, GinScanKey key)
 	 */
 	key->recheckCurItem = true;
 
-	return DatumGetBool(FunctionCall8(&ginstate->consistentFn[key->attnum - 1],
-									  PointerGetDatum(key->entryRes),
-									  UInt16GetDatum(key->strategy),
-									  key->query,
-									  UInt32GetDatum(key->nuserentries),
-									  PointerGetDatum(key->extra_data),
-									  PointerGetDatum(&key->recheckCurItem),
-									  PointerGetDatum(key->queryValues),
-									  PointerGetDatum(key->queryCategories)));
+	return DatumGetBool(FunctionCall8Coll(&ginstate->consistentFn[key->attnum - 1],
+										  ginstate->compareCollation[key->attnum - 1],
+										  PointerGetDatum(key->entryRes),
+										  UInt16GetDatum(key->strategy),
+										  key->query,
+										  UInt32GetDatum(key->nuserentries),
+										  PointerGetDatum(key->extra_data),
+										  PointerGetDatum(&key->recheckCurItem),
+										  PointerGetDatum(key->queryValues),
+										  PointerGetDatum(key->queryCategories)));
 }
 
 /*
@@ -250,9 +251,10 @@ collectMatchBitmap(GinBtreeData *btree, GinBtreeStack *stack,
 			 * case cmp < 0 => not match and continue scan
 			 *----------
 			 */
-			cmp = DatumGetInt32(FunctionCall4(&btree->ginstate->comparePartialFn[attnum - 1],
-											  scanEntry->queryKey,
-											  idatum,
+			cmp = DatumGetInt32(FunctionCall4Coll(&btree->ginstate->comparePartialFn[attnum - 1],
+												  btree->ginstate->compareCollation[attnum - 1],
+												  scanEntry->queryKey,
+												  idatum,
 										 UInt16GetDatum(scanEntry->strategy),
 									PointerGetDatum(scanEntry->extra_data)));
 
@@ -1175,9 +1177,10 @@ matchPartialInPendingList(GinState *ginstate, Page page,
 		 * case cmp < 0 => not match and continue scan
 		 *----------
 		 */
-		cmp = DatumGetInt32(FunctionCall4(&ginstate->comparePartialFn[entry->attnum - 1],
-										  entry->queryKey,
-										  datum[off - 1],
+		cmp = DatumGetInt32(FunctionCall4Coll(&ginstate->comparePartialFn[entry->attnum - 1],
+											  ginstate->compareCollation[entry->attnum - 1],
+											  entry->queryKey,
+											  datum[off - 1],
 										  UInt16GetDatum(entry->strategy),
 										PointerGetDatum(entry->extra_data)));
 		if (cmp == 0)
diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c
index 716cf3a734865d7ee3502f6377c12a5f50c9c1c3..a712331cf475fbe54f1761ef7a23780aeae9a54c 100644
--- a/src/backend/access/gin/ginutil.c
+++ b/src/backend/access/gin/ginutil.c
@@ -63,23 +63,6 @@ initGinState(GinState *state, Relation index)
 		fmgr_info_copy(&(state->compareFn[i]),
 					   index_getprocinfo(index, i + 1, GIN_COMPARE_PROC),
 					   CurrentMemoryContext);
-
-		/*
-		 * If the index column has a specified collation, index_getprocinfo
-		 * will have installed it into the fmgr info, and we should honor it.
-		 * However, we may have a collatable storage type for a noncollatable
-		 * indexed data type (for instance, hstore uses text index entries).
-		 * If there's no index collation then specify default collation in
-		 * case the comparison function needs one.	This is harmless if the
-		 * comparison function doesn't care about collation, so we just do it
-		 * unconditionally.  (We could alternatively call get_typcollation,
-		 * but that seems like expensive overkill --- there aren't going to be
-		 * any cases where a GIN storage type has a nondefault collation.)
-		 */
-		if (!OidIsValid(state->compareFn[i].fn_collation))
-			fmgr_info_set_collation(DEFAULT_COLLATION_OID,
-									&(state->compareFn[i]));
-
 		fmgr_info_copy(&(state->extractValueFn[i]),
 					   index_getprocinfo(index, i + 1, GIN_EXTRACTVALUE_PROC),
 					   CurrentMemoryContext);
@@ -98,18 +81,29 @@ initGinState(GinState *state, Relation index)
 			fmgr_info_copy(&(state->comparePartialFn[i]),
 				   index_getprocinfo(index, i + 1, GIN_COMPARE_PARTIAL_PROC),
 						   CurrentMemoryContext);
-
-			/* As above, install collation spec in case compare fn needs it */
-			if (!OidIsValid(state->comparePartialFn[i].fn_collation))
-				fmgr_info_set_collation(DEFAULT_COLLATION_OID,
-										&(state->comparePartialFn[i]));
-
 			state->canPartialMatch[i] = true;
 		}
 		else
 		{
 			state->canPartialMatch[i] = false;
 		}
+
+		/*
+		 * If the index column has a specified collation, we should honor that
+		 * while doing comparisons.  However, we may have a collatable storage
+		 * type for a noncollatable indexed data type (for instance, hstore
+		 * uses text index entries).  If there's no index collation then
+		 * specify default collation in case the comparison function needs
+		 * collation.  This is harmless if the comparison function doesn't
+		 * care about collation, so we just do it unconditionally.  (We could
+		 * alternatively call get_typcollation, but that seems like expensive
+		 * overkill --- there aren't going to be any cases where a GIN storage
+		 * type has a nondefault collation.)
+		 */
+		if (OidIsValid(index->rd_indcollation[i]))
+			state->compareCollation[i] = index->rd_indcollation[i];
+		else
+			state->compareCollation[i] = DEFAULT_COLLATION_OID;
 	}
 }
 
@@ -298,8 +292,9 @@ ginCompareEntries(GinState *ginstate, OffsetNumber attnum,
 		return 0;
 
 	/* both not null, so safe to call the compareFn */
-	return DatumGetInt32(FunctionCall2(&ginstate->compareFn[attnum - 1],
-									   a, b));
+	return DatumGetInt32(FunctionCall2Coll(&ginstate->compareFn[attnum - 1],
+										   ginstate->compareCollation[attnum - 1],
+										   a, b));
 }
 
 /*
@@ -334,6 +329,7 @@ typedef struct
 typedef struct
 {
 	FmgrInfo   *cmpDatumFunc;
+	Oid			collation;
 	bool		haveDups;
 } cmpEntriesArg;
 
@@ -355,8 +351,9 @@ cmpEntries(const void *a, const void *b, void *arg)
 	else if (bb->isnull)
 		res = -1;				/* not-NULL "<" NULL */
 	else
-		res = DatumGetInt32(FunctionCall2(data->cmpDatumFunc,
-										  aa->datum, bb->datum));
+		res = DatumGetInt32(FunctionCall2Coll(data->cmpDatumFunc,
+											  data->collation,
+											  aa->datum, bb->datum));
 
 	/*
 	 * Detect if we have any duplicates.  If there are equal keys, qsort must
@@ -456,6 +453,7 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
 		}
 
 		arg.cmpDatumFunc = &ginstate->compareFn[attnum - 1];
+		arg.collation = ginstate->compareCollation[attnum - 1];
 		arg.haveDups = false;
 		qsort_arg(keydata, *nentries, sizeof(keyEntryData),
 				  cmpEntries, (void *) &arg);
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index e4488a925de687e153677be332fd217d522c3415..4eb31318ffd3e99d3d7a5e583940862403634e72 100644
--- a/src/backend/access/gist/gistget.c
+++ b/src/backend/access/gist/gistget.c
@@ -137,12 +137,13 @@ gistindex_keytest(IndexScanDesc scan,
 			 */
 			recheck = true;
 
-			test = FunctionCall5(&key->sk_func,
-								 PointerGetDatum(&de),
-								 key->sk_argument,
-								 Int32GetDatum(key->sk_strategy),
-								 ObjectIdGetDatum(key->sk_subtype),
-								 PointerGetDatum(&recheck));
+			test = FunctionCall5Coll(&key->sk_func,
+									 key->sk_collation,
+									 PointerGetDatum(&de),
+									 key->sk_argument,
+									 Int32GetDatum(key->sk_strategy),
+									 ObjectIdGetDatum(key->sk_subtype),
+									 PointerGetDatum(&recheck));
 
 			if (!DatumGetBool(test))
 				return false;
@@ -195,11 +196,12 @@ gistindex_keytest(IndexScanDesc scan,
 			 * can't tolerate lossy distance calculations on leaf tuples;
 			 * there is no opportunity to re-sort the tuples afterwards.
 			 */
-			dist = FunctionCall4(&key->sk_func,
-								 PointerGetDatum(&de),
-								 key->sk_argument,
-								 Int32GetDatum(key->sk_strategy),
-								 ObjectIdGetDatum(key->sk_subtype));
+			dist = FunctionCall4Coll(&key->sk_func,
+									 key->sk_collation,
+									 PointerGetDatum(&de),
+									 key->sk_argument,
+									 Int32GetDatum(key->sk_strategy),
+									 ObjectIdGetDatum(key->sk_subtype));
 
 			*distance_p = DatumGetFloat8(dist);
 		}
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
index 67308ed37e5cb3370da15a89b001c7e032f35bfb..5662a3a4aab08bbc4841b3acb5961975dc6ef0b6 100644
--- a/src/backend/access/gist/gistscan.c
+++ b/src/backend/access/gist/gistscan.c
@@ -169,8 +169,7 @@ gistrescan(PG_FUNCTION_ARGS)
 		 * comparisons. The original operator is passed to the Consistent
 		 * function in the form of its strategy number, which is available
 		 * from the sk_strategy field, and its subtype from the sk_subtype
-		 * field.  Also, preserve sk_func.fn_collation which is the input
-		 * collation for the operator.
+		 * field.
 		 *
 		 * Next, if any of keys is a NULL and that key is not marked with
 		 * SK_SEARCHNULL/SK_SEARCHNOTNULL then nothing can be found (ie, we
@@ -181,10 +180,8 @@ gistrescan(PG_FUNCTION_ARGS)
 		for (i = 0; i < scan->numberOfKeys; i++)
 		{
 			ScanKey		skey = scan->keyData + i;
-			Oid			collation = skey->sk_func.fn_collation;
 
 			skey->sk_func = so->giststate->consistentFn[skey->sk_attno - 1];
-			skey->sk_func.fn_collation = collation;
 
 			if (skey->sk_flags & SK_ISNULL)
 			{
@@ -205,16 +202,13 @@ gistrescan(PG_FUNCTION_ARGS)
 		 * all comparisons. The original operator is passed to the Distance
 		 * function in the form of its strategy number, which is available
 		 * from the sk_strategy field, and its subtype from the sk_subtype
-		 * field.  Also, preserve sk_func.fn_collation which is the input
-		 * collation for the operator.
+		 * field.
 		 */
 		for (i = 0; i < scan->numberOfOrderBys; i++)
 		{
 			ScanKey		skey = scan->orderByData + i;
-			Oid			collation = skey->sk_func.fn_collation;
 
 			skey->sk_func = so->giststate->distanceFn[skey->sk_attno - 1];
-			skey->sk_func.fn_collation = collation;
 
 			/* Check we actually have a distance function ... */
 			if (!OidIsValid(skey->sk_func.fn_oid))
diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c
index b00b32d69fc8396a7dd013196ee928b1e27df2c8..ac238d9f7d803b54dce99c6f8b502ef357297d81 100644
--- a/src/backend/access/hash/hashutil.c
+++ b/src/backend/access/hash/hashutil.c
@@ -56,7 +56,8 @@ _hash_checkqual(IndexScanDesc scan, IndexTuple itup)
 		if (key->sk_flags & SK_ISNULL)
 			return false;
 
-		test = FunctionCall2(&key->sk_func, datum, key->sk_argument);
+		test = FunctionCall2Coll(&key->sk_func, key->sk_collation,
+								 datum, key->sk_argument);
 
 		if (!DatumGetBool(test))
 			return false;
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 66af2c37c54f8f0d33145db2d5b84bb67e17b4a8..6e0db79517615a1dc13f6287fecbc17bc1e587da 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -872,7 +872,6 @@ index_getprocinfo(Relation irel,
 				 procnum, attnum, RelationGetRelationName(irel));
 
 		fmgr_info_cxt(procId, locinfo, irel->rd_indexcxt);
-		fmgr_info_set_collation(irel->rd_indcollation[attnum - 1], locinfo);
 	}
 
 	return locinfo;
diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index 219f94fd0dd92c43a48b255da8deeb915000506d..d758659c314b6894149ac7a60d9742bf5f9c0ecf 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -2043,9 +2043,10 @@ _bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum,
 		if (isNull || (scankey->sk_flags & SK_ISNULL))
 			return false;
 
-		result = DatumGetInt32(FunctionCall2(&scankey->sk_func,
-											 datum,
-											 scankey->sk_argument));
+		result = DatumGetInt32(FunctionCall2Coll(&scankey->sk_func,
+												 scankey->sk_collation,
+												 datum,
+												 scankey->sk_argument));
 
 		if (result != 0)
 			return false;
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index 91f8cadea52b1bca1474a05f02f17655bb1685a9..2ce2bc2f00f519d24bddde0070abaf22df57613b 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -410,9 +410,10 @@ _bt_compare(Relation rel,
 			 * to flip the sign of the comparison result.  (Unless it's a DESC
 			 * column, in which case we *don't* flip the sign.)
 			 */
-			result = DatumGetInt32(FunctionCall2(&scankey->sk_func,
-												 datum,
-												 scankey->sk_argument));
+			result = DatumGetInt32(FunctionCall2Coll(&scankey->sk_func,
+													 scankey->sk_collation,
+													 datum,
+													 scankey->sk_argument));
 
 			if (!(scankey->sk_flags & SK_BT_DESC))
 				result = -result;
@@ -721,7 +722,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 											   cur->sk_attno,
 											   InvalidStrategy,
 											   cur->sk_subtype,
-											   cur->sk_func.fn_collation,
+											   cur->sk_collation,
 											   procinfo,
 											   cur->sk_argument);
 			}
@@ -742,7 +743,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 									   cur->sk_attno,
 									   InvalidStrategy,
 									   cur->sk_subtype,
-									   cur->sk_func.fn_collation,
+									   cur->sk_collation,
 									   cmp_proc,
 									   cur->sk_argument);
 			}
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index 256a7f9f98f9aae57b69b61c717ca4e404af788b..55136e9cc4c067322b771abdc4e88166d799ef76 100644
--- a/src/backend/access/nbtree/nbtsort.c
+++ b/src/backend/access/nbtree/nbtsort.c
@@ -736,9 +736,11 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
 					}
 					else
 					{
-						compare = DatumGetInt32(FunctionCall2(&entry->sk_func,
-															  attrDatum1,
-															  attrDatum2));
+						compare =
+							DatumGetInt32(FunctionCall2Coll(&entry->sk_func,
+															entry->sk_collation,
+															attrDatum1,
+															attrDatum2));
 
 						if (entry->sk_flags & SK_BT_DESC)
 							compare = -compare;
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index d448ba6a502845e1f9d4d9ff75e1f0eb86768781..71bcb42c1908e85abddd73631666573dec2c2387 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -70,8 +70,7 @@ _bt_mkscankey(Relation rel, IndexTuple itup)
 
 		/*
 		 * We can use the cached (default) support procs since no cross-type
-		 * comparison can be needed.  The cached support proc entries have the
-		 * right collation for the index, too.
+		 * comparison can be needed.
 		 */
 		procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
 		arg = index_getattr(itup, i + 1, itupdesc, &null);
@@ -81,7 +80,7 @@ _bt_mkscankey(Relation rel, IndexTuple itup)
 									   (AttrNumber) (i + 1),
 									   InvalidStrategy,
 									   InvalidOid,
-									   procinfo->fn_collation,
+									   rel->rd_indcollation[i],
 									   procinfo,
 									   arg);
 	}
@@ -120,8 +119,7 @@ _bt_mkscankey_nodata(Relation rel)
 
 		/*
 		 * We can use the cached (default) support procs since no cross-type
-		 * comparison can be needed.  The cached support proc entries have the
-		 * right collation for the index, too.
+		 * comparison can be needed.
 		 */
 		procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
 		flags = SK_ISNULL | (indoption[i] << SK_BT_INDOPTION_SHIFT);
@@ -130,7 +128,7 @@ _bt_mkscankey_nodata(Relation rel)
 									   (AttrNumber) (i + 1),
 									   InvalidStrategy,
 									   InvalidOid,
-									   procinfo->fn_collation,
+									   rel->rd_indcollation[i],
 									   procinfo,
 									   (Datum) 0);
 	}
@@ -604,9 +602,10 @@ _bt_compare_scankey_args(IndexScanDesc scan, ScanKey op,
 	 */
 	if (lefttype == opcintype && righttype == optype)
 	{
-		*result = DatumGetBool(FunctionCall2(&op->sk_func,
-											 leftarg->sk_argument,
-											 rightarg->sk_argument));
+		*result = DatumGetBool(FunctionCall2Coll(&op->sk_func,
+												 op->sk_collation,
+												 leftarg->sk_argument,
+												 rightarg->sk_argument));
 		return true;
 	}
 
@@ -633,9 +632,10 @@ _bt_compare_scankey_args(IndexScanDesc scan, ScanKey op,
 
 		if (RegProcedureIsValid(cmp_proc))
 		{
-			*result = DatumGetBool(OidFunctionCall2(cmp_proc,
-													leftarg->sk_argument,
-													rightarg->sk_argument));
+			*result = DatumGetBool(OidFunctionCall2Coll(cmp_proc,
+														op->sk_collation,
+														leftarg->sk_argument,
+														rightarg->sk_argument));
 			return true;
 		}
 	}
@@ -689,6 +689,10 @@ _bt_fix_scankey_strategy(ScanKey skey, int16 *indoption)
 	 * Likewise, "x IS NOT NULL" is supported.	We treat that as either "less
 	 * than NULL" in a NULLS LAST index, or "greater than NULL" in a NULLS
 	 * FIRST index.
+	 *
+	 * Note: someday we might have to fill in sk_collation from the index
+	 * column's collation.  At the moment this is a non-issue because we'll
+	 * never actually call the comparison operator on a NULL.
 	 */
 	if (skey->sk_flags & SK_ISNULL)
 	{
@@ -703,6 +707,7 @@ _bt_fix_scankey_strategy(ScanKey skey, int16 *indoption)
 		{
 			skey->sk_strategy = BTEqualStrategyNumber;
 			skey->sk_subtype = InvalidOid;
+			skey->sk_collation = InvalidOid;
 		}
 		else if (skey->sk_flags & SK_SEARCHNOTNULL)
 		{
@@ -711,6 +716,7 @@ _bt_fix_scankey_strategy(ScanKey skey, int16 *indoption)
 			else
 				skey->sk_strategy = BTLessStrategyNumber;
 			skey->sk_subtype = InvalidOid;
+			skey->sk_collation = InvalidOid;
 		}
 		else
 		{
@@ -976,7 +982,8 @@ _bt_checkkeys(IndexScanDesc scan,
 			return false;
 		}
 
-		test = FunctionCall2(&key->sk_func, datum, key->sk_argument);
+		test = FunctionCall2Coll(&key->sk_func, key->sk_collation,
+								 datum, key->sk_argument);
 
 		if (!DatumGetBool(test))
 		{
@@ -1099,9 +1106,10 @@ _bt_check_rowcompare(ScanKey skey, IndexTuple tuple, TupleDesc tupdesc,
 		}
 
 		/* Perform the test --- three-way comparison not bool operator */
-		cmpresult = DatumGetInt32(FunctionCall2(&subkey->sk_func,
-												datum,
-												subkey->sk_argument));
+		cmpresult = DatumGetInt32(FunctionCall2Coll(&subkey->sk_func,
+													subkey->sk_collation,
+													datum,
+													subkey->sk_argument));
 
 		if (subkey->sk_flags & SK_BT_DESC)
 			cmpresult = -cmpresult;
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index dde301b89aa2b73254dde0a9dc4dc3c81819799d..0568a1bcf86281a9b1086d343e7027557295065c 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -1930,8 +1930,6 @@ compute_minimal_stats(VacAttrStatsP stats,
 	track_cnt = 0;
 
 	fmgr_info(mystats->eqfunc, &f_cmpeq);
-	/* We always use the default collation for statistics */
-	fmgr_info_set_collation(DEFAULT_COLLATION_OID, &f_cmpeq);
 
 	for (i = 0; i < samplerows; i++)
 	{
@@ -1990,7 +1988,10 @@ compute_minimal_stats(VacAttrStatsP stats,
 		firstcount1 = track_cnt;
 		for (j = 0; j < track_cnt; j++)
 		{
-			if (DatumGetBool(FunctionCall2(&f_cmpeq, value, track[j].value)))
+			/* We always use the default collation for statistics */
+			if (DatumGetBool(FunctionCall2Coll(&f_cmpeq,
+											   DEFAULT_COLLATION_OID,
+											   value, track[j].value)))
 			{
 				match = true;
 				break;
@@ -2253,8 +2254,6 @@ compute_scalar_stats(VacAttrStatsP stats,
 
 	SelectSortFunction(mystats->ltopr, false, &cmpFn, &cmpFlags);
 	fmgr_info(cmpFn, &f_cmpfn);
-	/* We always use the default collation for statistics */
-	fmgr_info_set_collation(DEFAULT_COLLATION_OID, &f_cmpfn);
 
 	/* Initial scan to find sortable values */
 	for (i = 0; i < samplerows; i++)
@@ -2729,7 +2728,9 @@ compare_scalars(const void *a, const void *b, void *arg)
 	CompareScalarsContext *cxt = (CompareScalarsContext *) arg;
 	int32		compare;
 
+	/* We always use the default collation for statistics */
 	compare = ApplySortFunction(cxt->cmpFn, cxt->cmpFlags,
+								DEFAULT_COLLATION_OID,
 								da, false, db, false);
 	if (compare != 0)
 		return compare;
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 6b1ade899032f001f02de50194b74e49e8e3b3ef..ce36ea8be45c0d4f997a49305fd7215e1730af20 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -1822,7 +1822,8 @@ ExecCallTriggerFunc(TriggerData *trigdata,
 	/*
 	 * Call the function, passing no arguments but setting a context.
 	 */
-	InitFunctionCallInfoData(fcinfo, finfo, 0, (Node *) trigdata, NULL);
+	InitFunctionCallInfoData(fcinfo, finfo, 0,
+							 InvalidOid, (Node *) trigdata, NULL);
 
 	pgstat_init_function_usage(&fcinfo, &fcusage);
 
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index ce0086ffa17c3ec85c50270e7a199d76f470017e..d08c9bbbc5ce4699d7437639dc2154a781850ca8 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -96,6 +96,11 @@ get_ts_parser_func(DefElem *defel, int attnum)
 			break;
 		case Anum_pg_ts_parser_prslextype:
 			nargs = 1;
+			/*
+			 * Note: because the lextype method returns type internal, it must
+			 * have an internal-type argument for security reasons.  The
+			 * argument is not actually used, but is just passed as a zero.
+			 */
 			break;
 		default:
 			/* should not be here */
@@ -1947,7 +1952,7 @@ getTokenTypes(Oid prsId, List *tokennames)
 		elog(ERROR, "method lextype isn't defined for text search parser %u",
 			 prsId);
 
-	/* OidFunctionCall0 is absent */
+	/* lextype takes one dummy argument */
 	list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
 														 (Datum) 0));
 
diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index 1f02428a5b3680eb0c8a2926f8a2448e3dbd2b25..bfb8cbb303c6cb3635e7f925c0eefb4f9a8d570d 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -3,6 +3,10 @@
  * execGrouping.c
  *	  executor utility routines for grouping, hashing, and aggregation
  *
+ * Note: we currently assume that equality and hashing functions are not
+ * collation-sensitive, so the code in this file has no support for passing
+ * collation settings through from callers.  That may have to change someday.
+ *
  * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 5f0b58f43b79ae138f49c6198fcb6c1d333c523e..80f08d8b92e8dcfb9a5635297afd2358fef0610d 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -1202,12 +1202,12 @@ init_fcache(Oid foid, Oid input_collation, FuncExprState *fcache,
 
 	/* Set up the primary fmgr lookup information */
 	fmgr_info_cxt(foid, &(fcache->func), fcacheCxt);
-	fmgr_info_set_collation(input_collation, &(fcache->func));
 	fmgr_info_set_expr((Node *) fcache->xprstate.expr, &(fcache->func));
 
 	/* Initialize the function call parameter struct as well */
 	InitFunctionCallInfoData(fcache->fcinfo_data, &(fcache->func),
-							 list_length(fcache->args), NULL, NULL);
+							 list_length(fcache->args),
+							 input_collation, NULL, NULL);
 
 	/* If function returns set, prepare expected tuple descriptor */
 	if (fcache->func.fn_retset && needDescForSets)
@@ -1980,6 +1980,7 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
 		returnsSet = fcache->func.fn_retset;
 		InitFunctionCallInfoData(fcinfo, &(fcache->func),
 								 list_length(fcache->args),
+								 fcache->fcinfo_data.fncollation,
 								 NULL, (Node *) &rsinfo);
 
 		/*
@@ -2017,7 +2018,7 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
 	{
 		/* Treat funcexpr as a generic expression */
 		direct_function_call = false;
-		InitFunctionCallInfoData(fcinfo, NULL, 0, NULL, NULL);
+		InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
 	}
 
 	/*
@@ -3154,6 +3155,7 @@ ExecEvalRowCompare(RowCompareExprState *rstate,
 		FunctionCallInfoData locfcinfo;
 
 		InitFunctionCallInfoData(locfcinfo, &(rstate->funcs[i]), 2,
+								 rstate->collations[i],
 								 NULL, NULL);
 		locfcinfo.arg[0] = ExecEvalExpr(le, econtext,
 										&locfcinfo.argnull[0], NULL);
@@ -3234,7 +3236,9 @@ ExecEvalMinMax(MinMaxExprState *minmaxExpr, ExprContext *econtext,
 			   bool *isNull, ExprDoneCond *isDone)
 {
 	Datum		result = (Datum) 0;
-	MinMaxOp	op = ((MinMaxExpr *) minmaxExpr->xprstate.expr)->op;
+	MinMaxExpr *minmax = (MinMaxExpr *) minmaxExpr->xprstate.expr;
+	Oid			collation = minmax->inputcollid;
+	MinMaxOp	op = minmax->op;
 	FunctionCallInfoData locfcinfo;
 	ListCell   *arg;
 
@@ -3242,7 +3246,8 @@ ExecEvalMinMax(MinMaxExprState *minmaxExpr, ExprContext *econtext,
 		*isDone = ExprSingleResult;
 	*isNull = true;				/* until we get a result */
 
-	InitFunctionCallInfoData(locfcinfo, &minmaxExpr->cfunc, 2, NULL, NULL);
+	InitFunctionCallInfoData(locfcinfo, &minmaxExpr->cfunc, 2,
+							 collation, NULL, NULL);
 	locfcinfo.argnull[0] = false;
 	locfcinfo.argnull[1] = false;
 
@@ -4115,7 +4120,6 @@ ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate,
 		/* Set up the primary fmgr lookup information */
 		fmgr_info_cxt(acoerce->elemfuncid, &(astate->elemfunc),
 					  econtext->ecxt_per_query_memory);
-		/* Note: coercion functions are assumed to not use collation */
 		fmgr_info_set_expr((Node *) acoerce, &(astate->elemfunc));
 	}
 
@@ -4124,9 +4128,11 @@ ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate,
 	 *
 	 * We pass on the desttypmod and isExplicit flags whether or not the
 	 * function wants them.
+	 *
+	 * Note: coercion functions are assumed to not use collation.
 	 */
 	InitFunctionCallInfoData(locfcinfo, &(astate->elemfunc), 3,
-							 NULL, NULL);
+							 InvalidOid, NULL, NULL);
 	locfcinfo.arg[0] = PointerGetDatum(array);
 	locfcinfo.arg[1] = Int32GetDatum(acoerce->resulttypmod);
 	locfcinfo.arg[2] = BoolGetDatum(acoerce->isExplicit);
@@ -4699,6 +4705,7 @@ ExecInitExpr(Expr *node, PlanState *parent)
 				rstate->rargs = outlist;
 				Assert(list_length(rcexpr->opfamilies) == nopers);
 				rstate->funcs = (FmgrInfo *) palloc(nopers * sizeof(FmgrInfo));
+				rstate->collations = (Oid *) palloc(nopers * sizeof(Oid));
 				i = 0;
 				forthree(l, rcexpr->opnos, l2, rcexpr->opfamilies, l3, rcexpr->inputcollids)
 				{
@@ -4726,7 +4733,7 @@ ExecInitExpr(Expr *node, PlanState *parent)
 					 * does this code.
 					 */
 					fmgr_info(proc, &(rstate->funcs[i]));
-					fmgr_info_set_collation(inputcollid, &(rstate->funcs[i]));
+					rstate->collations[i] = inputcollid;
 					i++;
 				}
 				state = (ExprState *) rstate;
@@ -4786,8 +4793,6 @@ ExecInitExpr(Expr *node, PlanState *parent)
 				 * code.
 				 */
 				fmgr_info(typentry->cmp_proc, &(mstate->cfunc));
-				fmgr_info_set_collation(minmaxexpr->inputcollid,
-										&(mstate->cfunc));
 				state = (ExprState *) mstate;
 			}
 			break;
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 0cbbe04d3bda1bd5511c16e36c96bd42cf63a7a9..073ef8d23b3688e3e1f2034c5badc6a51f183c01 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -1349,9 +1349,10 @@ index_recheck_constraint(Relation index, Oid *constr_procs,
 		if (existing_isnull[i])
 			return false;
 
-		if (!DatumGetBool(OidFunctionCall2(constr_procs[i],
-										   existing_values[i],
-										   new_values[i])))
+		if (!DatumGetBool(OidFunctionCall2Coll(constr_procs[i],
+											   index->rd_indcollation[i],
+											   existing_values[i],
+											   new_values[i])))
 			return false;
 	}
 
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 9c867bbae200b7354d0d15d980a9b9c102ec3bfd..13946cab23d88d557e103bb7490738f26ff73c0d 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -127,7 +127,7 @@ static Node *sql_fn_param_ref(ParseState *pstate, ParamRef *pref);
 static List *init_execution_state(List *queryTree_list,
 					 SQLFunctionCachePtr fcache,
 					 bool lazyEvalOK);
-static void init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK);
+static void init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK);
 static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache);
 static bool postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache);
 static void postquel_end(execution_state *es);
@@ -363,7 +363,7 @@ init_execution_state(List *queryTree_list,
  * Initialize the SQLFunctionCache for a SQL function
  */
 static void
-init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK)
+init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK)
 {
 	Oid			foid = finfo->fn_oid;
 	Oid			rettype;
@@ -428,7 +428,7 @@ init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK)
 	 */
 	fcache->pinfo = prepare_sql_fn_parse_info(procedureTuple,
 											  finfo->fn_expr,
-											  finfo->fn_collation);
+											  collation);
 
 	/*
 	 * And of course we need the function body text.
@@ -798,7 +798,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
 	fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra;
 	if (fcache == NULL)
 	{
-		init_sql_fcache(fcinfo->flinfo, lazyEvalOK);
+		init_sql_fcache(fcinfo->flinfo, PG_GET_COLLATION(), lazyEvalOK);
 		fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra;
 	}
 	eslist = fcache->func_state;
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 47555bab55bdc0d8bb6ce42683fb037a7dd6e5ed..13d7723480144575103dc2efb42c10296dd565f8 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -130,6 +130,9 @@ typedef struct AggStatePerAggData
 	FmgrInfo	transfn;
 	FmgrInfo	finalfn;
 
+	/* Input collation derived for aggregate */
+	Oid			aggCollation;
+
 	/* number of sorting columns */
 	int			numSortCols;
 
@@ -430,6 +433,7 @@ advance_transition_function(AggState *aggstate,
 	 */
 	InitFunctionCallInfoData(*fcinfo, &(peraggstate->transfn),
 							 numArguments + 1,
+							 peraggstate->aggCollation,
 							 (void *) aggstate, NULL);
 	fcinfo->arg[0] = pergroupstate->transValue;
 	fcinfo->argnull[0] = pergroupstate->transValueIsNull;
@@ -597,6 +601,8 @@ process_ordered_aggregate_single(AggState *aggstate,
 
 		/*
 		 * If DISTINCT mode, and not distinct from prior, skip it.
+		 *
+		 * Note: we assume equality functions don't care about collation.
 		 */
 		if (isDistinct &&
 			haveOldVal &&
@@ -737,6 +743,7 @@ finalize_aggregate(AggState *aggstate,
 		FunctionCallInfoData fcinfo;
 
 		InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn), 1,
+								 peraggstate->aggCollation,
 								 (void *) aggstate, NULL);
 		fcinfo.arg[0] = pergroupstate->transValue;
 		fcinfo.argnull[0] = pergroupstate->transValueIsNull;
@@ -1676,16 +1683,16 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 								&finalfnexpr);
 
 		fmgr_info(transfn_oid, &peraggstate->transfn);
-		fmgr_info_set_collation(aggref->inputcollid, &peraggstate->transfn);
 		fmgr_info_set_expr((Node *) transfnexpr, &peraggstate->transfn);
 
 		if (OidIsValid(finalfn_oid))
 		{
 			fmgr_info(finalfn_oid, &peraggstate->finalfn);
-			fmgr_info_set_collation(aggref->inputcollid, &peraggstate->finalfn);
 			fmgr_info_set_expr((Node *) finalfnexpr, &peraggstate->finalfn);
 		}
 
+		peraggstate->aggCollation = aggref->inputcollid;
+
 		get_typlenbyval(aggref->aggtype,
 						&peraggstate->resulttypeLen,
 						&peraggstate->resulttypeByVal);
@@ -1833,8 +1840,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 				SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
 
 				fmgr_info(get_opcode(sortcl->eqop), &peraggstate->equalfns[i]);
-				fmgr_info_set_collation(aggref->inputcollid,
-										&peraggstate->equalfns[i]);
 				i++;
 			}
 			Assert(i == numDistinctCols);
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index d8e59ca39e5e08a195421171c66d8b24428e14a6..dbc1467d5be26367218ff0592a36839b9fb9658a 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -973,7 +973,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
 			this_scan_key->sk_flags = SK_ROW_HEADER;
 			this_scan_key->sk_attno = first_sub_key->sk_attno;
 			this_scan_key->sk_strategy = rc->rctype;
-			/* sk_subtype, sk_func not used in a header */
+			/* sk_subtype, sk_collation, sk_func not used in a header */
 			this_scan_key->sk_argument = PointerGetDatum(first_sub_key);
 		}
 		else if (IsA(clause, ScalarArrayOpExpr))
diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c
index 4ebe0cbe033372d6016c58d2aee7f2863ef3ba77..43059664b9348ae462dcb6b1166124f4f0fde2ee 100644
--- a/src/backend/executor/nodeMergeAppend.c
+++ b/src/backend/executor/nodeMergeAppend.c
@@ -327,8 +327,9 @@ heap_compare_slots(MergeAppendState *node, SlotNumber slot1, SlotNumber slot2)
 		}
 		else
 		{
-			compare = DatumGetInt32(FunctionCall2(&scankey->sk_func,
-												  datum1, datum2));
+			compare = DatumGetInt32(FunctionCall2Coll(&scankey->sk_func,
+													  scankey->sk_collation,
+													  datum1, datum2));
 			if (compare != 0)
 			{
 				if (scankey->sk_flags & SK_BT_DESC)
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index d6245e61874a4e2cf44f61d41a25e9ba42e1b523..208c0fb76ac11941dc583e89e31bf6a6e92d1d9b 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -138,11 +138,12 @@ typedef struct MergeJoinClauseData
 
 	/*
 	 * The comparison strategy in use, and the lookup info to let us call the
-	 * btree comparison support function.
+	 * btree comparison support function, and the collation to use.
 	 */
 	bool		reverse;		/* if true, negate the cmpfn's output */
 	bool		nulls_first;	/* if true, nulls sort low */
 	FmgrInfo	cmpfinfo;
+	Oid			collation;
 }	MergeJoinClauseData;
 
 /* Result type for MJEvalOuterValues and MJEvalInnerValues */
@@ -242,7 +243,6 @@ MJExamineQuals(List *mergeclauses,
 
 		/* Set up the fmgr lookup information */
 		fmgr_info(cmpproc, &(clause->cmpfinfo));
-		fmgr_info_set_collation(collation, &(clause->cmpfinfo));
 
 		/* Fill the additional comparison-strategy flags */
 		if (opstrategy == BTLessStrategyNumber)
@@ -254,6 +254,9 @@ MJExamineQuals(List *mergeclauses,
 
 		clause->nulls_first = nulls_first;
 
+		/* ... and the collation too */
+		clause->collation = collation;
+
 		iClause++;
 	}
 
@@ -429,7 +432,7 @@ MJCompare(MergeJoinState *mergestate)
 		 * OK to call the comparison function.
 		 */
 		InitFunctionCallInfoData(fcinfo, &(clause->cmpfinfo), 2,
-								 NULL, NULL);
+								 clause->collation, NULL, NULL);
 		fcinfo.arg[0] = clause->ldatum;
 		fcinfo.arg[1] = clause->rdatum;
 		fcinfo.argnull[0] = false;
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 08a3017e6145e13e630c2bb88efd5f5c76b8d357..4fcb66bbb03b86d6f67a4c1bc8a21d8b90231796 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -831,8 +831,6 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
 
 			/* Lookup the equality function (potentially cross-type) */
 			fmgr_info(opexpr->opfuncid, &sstate->cur_eq_funcs[i - 1]);
-			fmgr_info_set_collation(opexpr->inputcollid,
-									&sstate->cur_eq_funcs[i - 1]);
 			fmgr_info_set_expr((Node *) opexpr, &sstate->cur_eq_funcs[i - 1]);
 
 			/* Look up the equality function for the RHS type */
@@ -841,8 +839,6 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
 				elog(ERROR, "could not find compatible hash operator for operator %u",
 					 opexpr->opno);
 			fmgr_info(get_opcode(rhs_eq_oper), &sstate->tab_eq_funcs[i - 1]);
-			fmgr_info_set_collation(opexpr->inputcollid,
-									&sstate->tab_eq_funcs[i - 1]);
 
 			/* Lookup the associated hash functions */
 			if (!get_op_hash_functions(opexpr->opno,
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 25d9298cefc2460e706309d1a1972c124c555a28..c90d40506f93e1304ddcd10173ff2aeba0fc86ea 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -81,6 +81,8 @@ typedef struct WindowStatePerFuncData
 
 	FmgrInfo	flinfo;			/* fmgr lookup data for window function */
 
+	Oid			winCollation;	/* collation derived for window function */
+
 	/*
 	 * We need the len and byval info for the result of each function in order
 	 * to know how to copy/delete values.
@@ -289,6 +291,7 @@ advance_windowaggregate(WindowAggState *winstate,
 	 */
 	InitFunctionCallInfoData(*fcinfo, &(peraggstate->transfn),
 							 numArguments + 1,
+							 perfuncstate->winCollation,
 							 (void *) winstate, NULL);
 	fcinfo->arg[0] = peraggstate->transValue;
 	fcinfo->argnull[0] = peraggstate->transValueIsNull;
@@ -340,6 +343,7 @@ finalize_windowaggregate(WindowAggState *winstate,
 		FunctionCallInfoData fcinfo;
 
 		InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn), 1,
+								 perfuncstate->winCollation,
 								 (void *) winstate, NULL);
 		fcinfo.arg[0] = peraggstate->transValue;
 		fcinfo.argnull[0] = peraggstate->transValueIsNull;
@@ -627,6 +631,7 @@ eval_windowfunction(WindowAggState *winstate, WindowStatePerFunc perfuncstate,
 	 */
 	InitFunctionCallInfoData(fcinfo, &(perfuncstate->flinfo),
 							 perfuncstate->numArguments,
+							 perfuncstate->winCollation,
 							 (void *) perfuncstate->winobj, NULL);
 	/* Just in case, make all the regular argument slots be null */
 	memset(fcinfo.argnull, true, perfuncstate->numArguments);
@@ -1561,9 +1566,10 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
 
 		fmgr_info_cxt(wfunc->winfnoid, &perfuncstate->flinfo,
 					  econtext->ecxt_per_query_memory);
-		fmgr_info_set_collation(wfunc->inputcollid, &perfuncstate->flinfo);
 		fmgr_info_set_expr((Node *) wfunc, &perfuncstate->flinfo);
 
+		perfuncstate->winCollation = wfunc->inputcollid;
+
 		get_typlenbyval(wfunc->wintype,
 						&perfuncstate->resulttypeLen,
 						&perfuncstate->resulttypeByVal);
@@ -1801,13 +1807,11 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
 							&finalfnexpr);
 
 	fmgr_info(transfn_oid, &peraggstate->transfn);
-	fmgr_info_set_collation(wfunc->inputcollid, &peraggstate->transfn);
 	fmgr_info_set_expr((Node *) transfnexpr, &peraggstate->transfn);
 
 	if (OidIsValid(finalfn_oid))
 	{
 		fmgr_info(finalfn_oid, &peraggstate->finalfn);
-		fmgr_info_set_collation(wfunc->inputcollid, &peraggstate->finalfn);
 		fmgr_info_set_expr((Node *) finalfnexpr, &peraggstate->finalfn);
 	}
 
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index c7ed1b6ee9d67848cfc997e830fea7cd6cf27e87..1cace6d5960eb5a15b90df67e95f2fc36b28ea3d 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -3189,8 +3189,7 @@ prefix_quals(Node *leftop, Oid opfamily, Oid collation,
 	if (oproid == InvalidOid)
 		elog(ERROR, "no < operator for opfamily %u", opfamily);
 	fmgr_info(get_opcode(oproid), &ltproc);
-	fmgr_info_set_collation(collation, &ltproc);
-	greaterstr = make_greater_string(prefix_const, &ltproc);
+	greaterstr = make_greater_string(prefix_const, &ltproc, collation);
 	if (greaterstr)
 	{
 		expr = make_opclause(oproid, BOOLOID, false,
diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c
index d0a23d007aafd32afa2070fb1720c73ade297bfc..30863bb7b960cc8741fa04b148eba325ac6b4aee 100644
--- a/src/backend/tcop/fastpath.c
+++ b/src/backend/tcop/fastpath.c
@@ -349,8 +349,12 @@ HandleFunctionRequest(StringInfo msgBuf)
 
 	/*
 	 * Prepare function call info block and insert arguments.
+	 *
+	 * Note: for now we pass collation = InvalidOid, so collation-sensitive
+	 * functions can't be called this way.  Perhaps we should pass
+	 * DEFAULT_COLLATION_OID, instead?
 	 */
-	InitFunctionCallInfoData(fcinfo, &fip->flinfo, 0, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, &fip->flinfo, 0, InvalidOid, NULL, NULL);
 
 	if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
 		rformat = parse_fcall_arguments(msgBuf, fip, &fcinfo);
diff --git a/src/backend/tsearch/wparser.c b/src/backend/tsearch/wparser.c
index f636c2d23b22477eb8209c69b4e804c68ded1c1b..bda8d2632d91ecab033c7b73df4d73a2527b20f1 100644
--- a/src/backend/tsearch/wparser.c
+++ b/src/backend/tsearch/wparser.c
@@ -54,7 +54,7 @@ tt_setup_firstcall(FuncCallContext *funcctx, Oid prsid)
 
 	st = (TSTokenTypeStorage *) palloc(sizeof(TSTokenTypeStorage));
 	st->cur = 0;
-	/* OidFunctionCall0 is absent */
+	/* lextype takes one dummy argument */
 	st->list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
 															 (Datum) 0));
 	funcctx->user_fctx = (void *) st;
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 0869de66cef1e381eea189404cf7ed9a1869eebf..a234f35eb8f561650add8cfd3fa4a44a36c550f7 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -3127,6 +3127,7 @@ array_eq(PG_FUNCTION_ARGS)
 {
 	ArrayType  *array1 = PG_GETARG_ARRAYTYPE_P(0);
 	ArrayType  *array2 = PG_GETARG_ARRAYTYPE_P(1);
+	Oid			collation = PG_GET_COLLATION();
 	int			ndims1 = ARR_NDIM(array1);
 	int			ndims2 = ARR_NDIM(array2);
 	int		   *dims1 = ARR_DIMS(array1);
@@ -3184,7 +3185,7 @@ array_eq(PG_FUNCTION_ARGS)
 		 * apply the operator to each pair of array elements.
 		 */
 		InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
-								 NULL, NULL);
+								 collation, NULL, NULL);
 
 		/* Loop over source data */
 		nitems = ArrayGetNItems(ndims1, dims1);
@@ -3367,8 +3368,7 @@ array_cmp(FunctionCallInfo fcinfo)
 	 */
 	typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
 	if (typentry == NULL ||
-		typentry->type_id != element_type ||
-		typentry->cmp_proc_finfo.fn_collation != collation)
+		typentry->type_id != element_type)
 	{
 		typentry = lookup_type_cache(element_type,
 									 TYPECACHE_CMP_PROC_FINFO);
@@ -3378,7 +3378,6 @@ array_cmp(FunctionCallInfo fcinfo)
 			   errmsg("could not identify a comparison function for type %s",
 					  format_type_be(element_type))));
 		fcinfo->flinfo->fn_extra = (void *) typentry;
-		typentry->cmp_proc_finfo.fn_collation = collation;
 	}
 	typlen = typentry->typlen;
 	typbyval = typentry->typbyval;
@@ -3388,7 +3387,7 @@ array_cmp(FunctionCallInfo fcinfo)
 	 * apply the operator to each pair of array elements.
 	 */
 	InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2,
-							 NULL, NULL);
+							 collation, NULL, NULL);
 
 	/* Loop over source data */
 	min_nitems = Min(nitems1, nitems2);
@@ -3573,7 +3572,7 @@ hash_array(PG_FUNCTION_ARGS)
 	 * apply the hash function to each array element.
 	 */
 	InitFunctionCallInfoData(locfcinfo, &typentry->hash_proc_finfo, 1,
-							 NULL, NULL);
+							 InvalidOid, NULL, NULL);
 
 	/* Loop over source data */
 	nitems = ArrayGetNItems(ndims, dims);
@@ -3647,8 +3646,8 @@ hash_array(PG_FUNCTION_ARGS)
  * When matchall is false, return true if any members of array1 are in array2.
  */
 static bool
-array_contain_compare(ArrayType *array1, ArrayType *array2, bool matchall,
-					  void **fn_extra)
+array_contain_compare(ArrayType *array1, ArrayType *array2, Oid collation,
+					  bool matchall, void **fn_extra)
 {
 	bool		result = matchall;
 	Oid			element_type = ARR_ELEMTYPE(array1);
@@ -3707,7 +3706,7 @@ array_contain_compare(ArrayType *array1, ArrayType *array2, bool matchall,
 	 * Apply the comparison operator to each pair of array elements.
 	 */
 	InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
-							 NULL, NULL);
+							 collation, NULL, NULL);
 
 	/* Loop over source data */
 	nelems1 = ArrayGetNItems(ARR_NDIM(array1), ARR_DIMS(array1));
@@ -3811,9 +3810,10 @@ arrayoverlap(PG_FUNCTION_ARGS)
 {
 	ArrayType  *array1 = PG_GETARG_ARRAYTYPE_P(0);
 	ArrayType  *array2 = PG_GETARG_ARRAYTYPE_P(1);
+	Oid			collation = PG_GET_COLLATION();
 	bool		result;
 
-	result = array_contain_compare(array1, array2, false,
+	result = array_contain_compare(array1, array2, collation, false,
 								   &fcinfo->flinfo->fn_extra);
 
 	/* Avoid leaking memory when handed toasted input. */
@@ -3828,9 +3828,10 @@ arraycontains(PG_FUNCTION_ARGS)
 {
 	ArrayType  *array1 = PG_GETARG_ARRAYTYPE_P(0);
 	ArrayType  *array2 = PG_GETARG_ARRAYTYPE_P(1);
+	Oid			collation = PG_GET_COLLATION();
 	bool		result;
 
-	result = array_contain_compare(array2, array1, true,
+	result = array_contain_compare(array2, array1, collation, true,
 								   &fcinfo->flinfo->fn_extra);
 
 	/* Avoid leaking memory when handed toasted input. */
@@ -3845,9 +3846,10 @@ arraycontained(PG_FUNCTION_ARGS)
 {
 	ArrayType  *array1 = PG_GETARG_ARRAYTYPE_P(0);
 	ArrayType  *array2 = PG_GETARG_ARRAYTYPE_P(1);
+	Oid			collation = PG_GET_COLLATION();
 	bool		result;
 
-	result = array_contain_compare(array1, array2, true,
+	result = array_contain_compare(array1, array2, collation, true,
 								   &fcinfo->flinfo->fn_extra);
 
 	/* Avoid leaking memory when handed toasted input. */
diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index dcb31586b2b3e21aa817fac856d5349befadcb24..019fcaaa36f23296e9ca1482f00cf839574e238a 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -213,7 +213,8 @@ int2vectorrecv(PG_FUNCTION_ARGS)
 	 * fcinfo->flinfo->fn_extra.  So we need to pass it our own flinfo
 	 * parameter.
 	 */
-	InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3, NULL, NULL);
+	InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3,
+							 InvalidOid, NULL, NULL);
 
 	locfcinfo.arg[0] = PointerGetDatum(buf);
 	locfcinfo.arg[1] = ObjectIdGetDatum(INT2OID);
diff --git a/src/backend/utils/adt/like.c b/src/backend/utils/adt/like.c
index 0934c69ebe5682102a59554b750c865599c8f79b..09e8698af2cb88a0e29da0e92e2f25b375cb7b99 100644
--- a/src/backend/utils/adt/like.c
+++ b/src/backend/utils/adt/like.c
@@ -174,10 +174,12 @@ Generic_Text_IC_like(text *str, text *pat, Oid collation)
 	if (pg_database_encoding_max_length() > 1)
 	{
 		/* lower's result is never packed, so OK to use old macros here */
-		pat = DatumGetTextP(DirectFunctionCall1WithCollation(lower, collation, PointerGetDatum(pat)));
+		pat = DatumGetTextP(DirectFunctionCall1Coll(lower, collation,
+													PointerGetDatum(pat)));
 		p = VARDATA(pat);
 		plen = (VARSIZE(pat) - VARHDRSZ);
-		str = DatumGetTextP(DirectFunctionCall1WithCollation(lower, collation, PointerGetDatum(str)));
+		str = DatumGetTextP(DirectFunctionCall1Coll(lower, collation,
+													PointerGetDatum(str)));
 		s = VARDATA(str);
 		slen = (VARSIZE(str) - VARHDRSZ);
 		if (GetDatabaseEncoding() == PG_UTF8)
diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c
index b2152a2491cf5d11f12c23316840501e7e68ba67..495b6261e62050b3e02dc918ac2fa3981b9f1e32 100644
--- a/src/backend/utils/adt/oid.c
+++ b/src/backend/utils/adt/oid.c
@@ -263,7 +263,8 @@ oidvectorrecv(PG_FUNCTION_ARGS)
 	 * fcinfo->flinfo->fn_extra.  So we need to pass it our own flinfo
 	 * parameter.
 	 */
-	InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3, NULL, NULL);
+	InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3,
+							 InvalidOid, NULL, NULL);
 
 	locfcinfo.arg[0] = PointerGetDatum(buf);
 	locfcinfo.arg[1] = ObjectIdGetDatum(OIDOID);
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index 4e5dd4b772d7b101cebc5b4cea7ba38dc9510a4b..fde01a0f5719aa8e3fbd90997a2e803523d80591 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -3963,7 +3963,10 @@ ri_AttributesEqual(Oid eq_opr, Oid typeid,
 								 BoolGetDatum(false));	/* implicit coercion */
 	}
 
-	/* Apply the comparison operator */
+	/*
+	 * Apply the comparison operator.  We assume it doesn't
+	 * care about collations.
+	 */
 	return DatumGetBool(FunctionCall2(&entry->eq_opr_finfo,
 									  oldvalue, newvalue));
 }
diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c
index 2c552e173bb1747898fd3046c253dcda5f3783a3..919ed9582a70a9b1d9696150c3e0116048d86afa 100644
--- a/src/backend/utils/adt/rowtypes.c
+++ b/src/backend/utils/adt/rowtypes.c
@@ -867,6 +867,7 @@ record_cmp(FunctionCallInfo fcinfo)
 	while (i1 < ncolumns1 || i2 < ncolumns2)
 	{
 		TypeCacheEntry *typentry;
+		Oid			collation;
 		FunctionCallInfoData locfcinfo;
 		int32		cmpresult;
 
@@ -898,6 +899,14 @@ record_cmp(FunctionCallInfo fcinfo)
 							format_type_be(tupdesc2->attrs[i2]->atttypid),
 							j + 1)));
 
+		/*
+		 * If they're not same collation, we don't complain here, but the
+		 * comparison function might.
+		 */
+		collation = tupdesc1->attrs[i1]->attcollation;
+		if (collation != tupdesc2->attrs[i2]->attcollation)
+			collation = InvalidOid;
+
 		/*
 		 * Lookup the comparison function if not done already
 		 */
@@ -935,7 +944,7 @@ record_cmp(FunctionCallInfo fcinfo)
 
 			/* Compare the pair of elements */
 			InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2,
-									 NULL, NULL);
+									 collation, NULL, NULL);
 			locfcinfo.arg[0] = values1[i1];
 			locfcinfo.arg[1] = values2[i2];
 			locfcinfo.argnull[0] = false;
@@ -1093,6 +1102,7 @@ record_eq(PG_FUNCTION_ARGS)
 	while (i1 < ncolumns1 || i2 < ncolumns2)
 	{
 		TypeCacheEntry *typentry;
+		Oid			collation;
 		FunctionCallInfoData locfcinfo;
 		bool		oprresult;
 
@@ -1124,6 +1134,14 @@ record_eq(PG_FUNCTION_ARGS)
 							format_type_be(tupdesc2->attrs[i2]->atttypid),
 							j + 1)));
 
+		/*
+		 * If they're not same collation, we don't complain here, but the
+		 * equality function might.
+		 */
+		collation = tupdesc1->attrs[i1]->attcollation;
+		if (collation != tupdesc2->attrs[i2]->attcollation)
+			collation = InvalidOid;
+
 		/*
 		 * Lookup the equality function if not done already
 		 */
@@ -1154,7 +1172,7 @@ record_eq(PG_FUNCTION_ARGS)
 
 			/* Compare the pair of elements */
 			InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
-									 NULL, NULL);
+									 collation, NULL, NULL);
 			locfcinfo.arg[0] = values1[i1];
 			locfcinfo.arg[1] = values2[i2];
 			locfcinfo.argnull[0] = false;
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index b046bc05e6245e45c704f05491a3b12c4f9619f1..4d800f8a007980dbac1d221d48f0fa8b0e30db66 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -285,19 +285,20 @@ var_eq_const(VariableStatData *vardata, Oid operator,
 			FmgrInfo	eqproc;
 
 			fmgr_info(get_opcode(operator), &eqproc);
-			fmgr_info_set_collation(DEFAULT_COLLATION_OID, &eqproc);
 
 			for (i = 0; i < nvalues; i++)
 			{
 				/* be careful to apply operator right way 'round */
 				if (varonleft)
-					match = DatumGetBool(FunctionCall2(&eqproc,
-													   values[i],
-													   constval));
+					match = DatumGetBool(FunctionCall2Coll(&eqproc,
+														   DEFAULT_COLLATION_OID,
+														   values[i],
+														   constval));
 				else
-					match = DatumGetBool(FunctionCall2(&eqproc,
-													   constval,
-													   values[i]));
+					match = DatumGetBool(FunctionCall2Coll(&eqproc,
+														   DEFAULT_COLLATION_OID,
+														   constval,
+														   values[i]));
 				if (match)
 					break;
 			}
@@ -515,7 +516,6 @@ scalarineqsel(PlannerInfo *root, Oid operator, bool isgt,
 	stats = (Form_pg_statistic) GETSTRUCT(vardata->statsTuple);
 
 	fmgr_info(get_opcode(operator), &opproc);
-	fmgr_info_set_collation(DEFAULT_COLLATION_OID, &opproc);
 
 	/*
 	 * If we have most-common-values info, add up the fractions of the MCV
@@ -598,12 +598,14 @@ mcv_selectivity(VariableStatData *vardata, FmgrInfo *opproc,
 		for (i = 0; i < nvalues; i++)
 		{
 			if (varonleft ?
-				DatumGetBool(FunctionCall2(opproc,
-										   values[i],
-										   constval)) :
-				DatumGetBool(FunctionCall2(opproc,
-										   constval,
-										   values[i])))
+				DatumGetBool(FunctionCall2Coll(opproc,
+											   DEFAULT_COLLATION_OID,
+											   values[i],
+											   constval)) :
+				DatumGetBool(FunctionCall2Coll(opproc,
+											   DEFAULT_COLLATION_OID,
+											   constval,
+											   values[i])))
 				mcv_selec += numbers[i];
 			sumcommon += numbers[i];
 		}
@@ -678,12 +680,14 @@ histogram_selectivity(VariableStatData *vardata, FmgrInfo *opproc,
 			for (i = n_skip; i < nvalues - n_skip; i++)
 			{
 				if (varonleft ?
-					DatumGetBool(FunctionCall2(opproc,
-											   values[i],
-											   constval)) :
-					DatumGetBool(FunctionCall2(opproc,
-											   constval,
-											   values[i])))
+					DatumGetBool(FunctionCall2Coll(opproc,
+												   DEFAULT_COLLATION_OID,
+												   values[i],
+												   constval)) :
+					DatumGetBool(FunctionCall2Coll(opproc,
+												   DEFAULT_COLLATION_OID,
+												   constval,
+												   values[i])))
 					nmatch++;
 			}
 			result = ((double) nmatch) / ((double) (nvalues - 2 * n_skip));
@@ -802,9 +806,10 @@ ineq_histogram_selectivity(PlannerInfo *root,
 														 NULL,
 														 &values[probe]);
 
-				ltcmp = DatumGetBool(FunctionCall2(opproc,
-												   values[probe],
-												   constval));
+				ltcmp = DatumGetBool(FunctionCall2Coll(opproc,
+													   DEFAULT_COLLATION_OID,
+													   values[probe],
+													   constval));
 				if (isgt)
 					ltcmp = !ltcmp;
 				if (ltcmp)
@@ -1255,7 +1260,6 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
 
 		/* Try to use the histogram entries to get selectivity */
 		fmgr_info(get_opcode(operator), &opproc);
-		fmgr_info_set_collation(DEFAULT_COLLATION_OID, &opproc);
 
 		selec = histogram_selectivity(&vardata, &opproc, constval, true,
 									  10, 1, &hist_size);
@@ -1705,7 +1709,6 @@ scalararraysel(PlannerInfo *root,
 	if (!oprsel)
 		return (Selectivity) 0.5;
 	fmgr_info(oprsel, &oprselproc);
-	fmgr_info_set_collation(DEFAULT_COLLATION_OID, &oprselproc);
 
 	/* deconstruct the expression */
 	Assert(list_length(clause->args) == 2);
@@ -2126,7 +2129,6 @@ eqjoinsel_inner(Oid operator,
 					nmatches;
 
 		fmgr_info(get_opcode(operator), &eqproc);
-		fmgr_info_set_collation(DEFAULT_COLLATION_OID, &eqproc);
 		hasmatch1 = (bool *) palloc0(nvalues1 * sizeof(bool));
 		hasmatch2 = (bool *) palloc0(nvalues2 * sizeof(bool));
 
@@ -2146,9 +2148,10 @@ eqjoinsel_inner(Oid operator,
 			{
 				if (hasmatch2[j])
 					continue;
-				if (DatumGetBool(FunctionCall2(&eqproc,
-											   values1[i],
-											   values2[j])))
+				if (DatumGetBool(FunctionCall2Coll(&eqproc,
+												   DEFAULT_COLLATION_OID,
+												   values1[i],
+												   values2[j])))
 				{
 					hasmatch1[i] = hasmatch2[j] = true;
 					matchprodfreq += numbers1[i] * numbers2[j];
@@ -2349,7 +2352,6 @@ eqjoinsel_semi(Oid operator,
 					nmatches;
 
 		fmgr_info(get_opcode(operator), &eqproc);
-		fmgr_info_set_collation(DEFAULT_COLLATION_OID, &eqproc);
 		hasmatch1 = (bool *) palloc0(nvalues1 * sizeof(bool));
 		hasmatch2 = (bool *) palloc0(nvalues2 * sizeof(bool));
 
@@ -2368,9 +2370,10 @@ eqjoinsel_semi(Oid operator,
 			{
 				if (hasmatch2[j])
 					continue;
-				if (DatumGetBool(FunctionCall2(&eqproc,
-											   values1[i],
-											   values2[j])))
+				if (DatumGetBool(FunctionCall2Coll(&eqproc,
+												   DEFAULT_COLLATION_OID,
+												   values1[i],
+												   values2[j])))
 				{
 					hasmatch1[i] = hasmatch2[j] = true;
 					nmatches++;
@@ -4503,7 +4506,6 @@ get_variable_range(PlannerInfo *root, VariableStatData *vardata, Oid sortop,
 		FmgrInfo	opproc;
 
 		fmgr_info(get_opcode(sortop), &opproc);
-		fmgr_info_set_collation(DEFAULT_COLLATION_OID, &opproc);
 
 		for (i = 0; i < nvalues; i++)
 		{
@@ -4513,12 +4515,16 @@ get_variable_range(PlannerInfo *root, VariableStatData *vardata, Oid sortop,
 				tmin_is_mcv = tmax_is_mcv = have_data = true;
 				continue;
 			}
-			if (DatumGetBool(FunctionCall2(&opproc, values[i], tmin)))
+			if (DatumGetBool(FunctionCall2Coll(&opproc,
+											   DEFAULT_COLLATION_OID,
+											   values[i], tmin)))
 			{
 				tmin = values[i];
 				tmin_is_mcv = true;
 			}
-			if (DatumGetBool(FunctionCall2(&opproc, tmax, values[i])))
+			if (DatumGetBool(FunctionCall2Coll(&opproc,
+											   DEFAULT_COLLATION_OID,
+											   tmax, values[i])))
 			{
 				tmax = values[i];
 				tmax_is_mcv = true;
@@ -5183,7 +5189,6 @@ prefix_selectivity(PlannerInfo *root, VariableStatData *vardata,
 	if (cmpopr == InvalidOid)
 		elog(ERROR, "no >= operator for opfamily %u", opfamily);
 	fmgr_info(get_opcode(cmpopr), &opproc);
-	fmgr_info_set_collation(DEFAULT_COLLATION_OID, &opproc);
 
 	prefixsel = ineq_histogram_selectivity(root, vardata, &opproc, true,
 										   prefixcon->constvalue,
@@ -5205,9 +5210,8 @@ prefix_selectivity(PlannerInfo *root, VariableStatData *vardata,
 	if (cmpopr == InvalidOid)
 		elog(ERROR, "no < operator for opfamily %u", opfamily);
 	fmgr_info(get_opcode(cmpopr), &opproc);
-	fmgr_info_set_collation(DEFAULT_COLLATION_OID, &opproc);
-
-	greaterstrcon = make_greater_string(prefixcon, &opproc);
+	greaterstrcon = make_greater_string(prefixcon, &opproc,
+										DEFAULT_COLLATION_OID);
 	if (greaterstrcon)
 	{
 		Selectivity topsel;
@@ -5502,22 +5506,21 @@ pattern_selectivity(Const *patt, Pattern_Type ptype)
  * in the form of a Const node; else return NULL.
  *
  * The caller must provide the appropriate "less than" comparison function
- * for testing the strings.  In particular, ltproc->fn_collation specifies
- * the locale for comparisons.
+ * for testing the strings, along with the collation to use.
  *
  * The key requirement here is that given a prefix string, say "foo",
  * we must be able to generate another string "fop" that is greater than
  * all strings "foobar" starting with "foo".  We can test that we have
- * generated a string greater than the prefix string, but in non-C locales
+ * generated a string greater than the prefix string, but in non-C collations
  * that is not a bulletproof guarantee that an extension of the string might
  * not sort after it; an example is that "foo " is less than "foo!", but it
  * is not clear that a "dictionary" sort ordering will consider "foo!" less
  * than "foo bar".	CAUTION: Therefore, this function should be used only for
- * estimation purposes when working in a non-C locale.
+ * estimation purposes when working in a non-C collation.
  *
  * To try to catch most cases where an extended string might otherwise sort
  * before the result value, we determine which of the strings "Z", "z", "y",
- * and "9" is seen as largest by the locale, and append that to the given
+ * and "9" is seen as largest by the collation, and append that to the given
  * prefix before trying to find a string that compares as larger.
  *
  * If we max out the righthand byte, truncate off the last character
@@ -5529,7 +5532,7 @@ pattern_selectivity(Const *patt, Pattern_Type ptype)
  * won't have to try more than one or two strings before succeeding.
  */
 Const *
-make_greater_string(const Const *str_const, FmgrInfo *ltproc)
+make_greater_string(const Const *str_const, FmgrInfo *ltproc, Oid collation)
 {
 	Oid			datatype = str_const->consttype;
 	char	   *workstr;
@@ -5565,7 +5568,7 @@ make_greater_string(const Const *str_const, FmgrInfo *ltproc)
 	{
 		workstr = TextDatumGetCString(str_const->constvalue);
 		len = strlen(workstr);
-		if (lc_collate_is_c(ltproc->fn_collation) || len == 0)
+		if (lc_collate_is_c(collation) || len == 0)
 			cmpstr = str_const->constvalue;
 		else
 		{
@@ -5573,19 +5576,19 @@ make_greater_string(const Const *str_const, FmgrInfo *ltproc)
 			static char suffixchar = 0;
 			static Oid	suffixcollation = 0;
 
-			if (!suffixchar || suffixcollation != ltproc->fn_collation)
+			if (!suffixchar || suffixcollation != collation)
 			{
 				char	   *best;
 
 				best = "Z";
-				if (varstr_cmp(best, 1, "z", 1, ltproc->fn_collation) < 0)
+				if (varstr_cmp(best, 1, "z", 1, collation) < 0)
 					best = "z";
-				if (varstr_cmp(best, 1, "y", 1, ltproc->fn_collation) < 0)
+				if (varstr_cmp(best, 1, "y", 1, collation) < 0)
 					best = "y";
-				if (varstr_cmp(best, 1, "9", 1, ltproc->fn_collation) < 0)
+				if (varstr_cmp(best, 1, "9", 1, collation) < 0)
 					best = "9";
 				suffixchar = *best;
-				suffixcollation = ltproc->fn_collation;
+				suffixcollation = collation;
 			}
 
 			/* And build the string to compare to */
@@ -5621,9 +5624,10 @@ make_greater_string(const Const *str_const, FmgrInfo *ltproc)
 			else
 				workstr_const = string_to_bytea_const(workstr, len);
 
-			if (DatumGetBool(FunctionCall2(ltproc,
-										   cmpstr,
-										   workstr_const->constvalue)))
+			if (DatumGetBool(FunctionCall2Coll(ltproc,
+											   collation,
+											   cmpstr,
+											   workstr_const->constvalue)))
 			{
 				/* Successfully made a string larger than cmpstr */
 				if (cmptxt)
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 5caa53d4d25f67d8fbc01c96ceb0a82edce974b7..350e040474b413dec4280fd1e63c1f0613c5dcde 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -935,7 +935,7 @@ CatalogCacheInitializeCache(CatCache *cache)
 		cache->cc_skey[i].sk_strategy = BTEqualStrategyNumber;
 		cache->cc_skey[i].sk_subtype = InvalidOid;
 		/* Currently, there are no catcaches on collation-aware data types */
-		cache->cc_skey[i].sk_func.fn_collation = InvalidOid;
+		cache->cc_skey[i].sk_collation = InvalidOid;
 
 		CACHE4_elog(DEBUG2, "CatalogCacheInitializeCache %s %d %p",
 					cache->cc_relname,
diff --git a/src/backend/utils/fmgr/README b/src/backend/utils/fmgr/README
index 6647fe95f729a316198039bd75dd45db6dc084dd..a650eb14a370bbe07f077fb65b319cd7be161efb 100644
--- a/src/backend/utils/fmgr/README
+++ b/src/backend/utils/fmgr/README
@@ -71,7 +71,6 @@ typedef struct
     bool        fn_strict;  /* function is "strict" (NULL in => NULL out) */
     bool        fn_retset;  /* function returns a set (over multiple calls) */
     unsigned char fn_stats; /* collect stats if track_functions > this */
-    Oid         fn_collation;   /* collation that function should use */
     void       *fn_extra;   /* extra space for use by handler */
     MemoryContext fn_mcxt;  /* memory context to store fn_extra in */
     Node       *fn_expr;    /* expression parse tree for call, or NULL */
@@ -92,14 +91,12 @@ these values come from the function's pg_proc entry.  fn_stats is also
 set up to control whether or not to track runtime statistics for calling
 this function.
 
-fn_collation supplies the collation to use for collation-sensitive
-functions.  If the function is being called as part of a SQL expression,
-fn_expr will point to the expression parse tree for the function call; this
-can be used to extract parse-time knowledge about the actual arguments.
-Note that these two fields really are information about the arguments
-rather than information about the function, but it's proven to be more
-convenient to keep them in FmgrInfo than in FunctionCallInfoData where
-they might more logically go.
+If the function is being called as part of a SQL expression, fn_expr will
+point to the expression parse tree for the function call; this can be used
+to extract parse-time knowledge about the actual arguments.  Note that this
+field really is information about the arguments rather than information
+about the function, but it's proven to be more convenient to keep it in
+FmgrInfo than in FunctionCallInfoData where it might more logically go.
 
 
 During a call of a function, the following data structure is created
@@ -110,6 +107,7 @@ typedef struct
     FmgrInfo   *flinfo;         /* ptr to lookup info used for this call */
     Node       *context;        /* pass info about context of call */
     Node       *resultinfo;     /* pass or return extra info about result */
+    Oid         fncollation;    /* collation for function to use */
     bool        isnull;         /* function must set true if result is NULL */
     short       nargs;          /* # arguments actually passed */
     Datum       arg[FUNC_MAX_ARGS];  /* Arguments passed to function */
@@ -137,6 +135,11 @@ function that returns a set, as discussed below.)  Like the context field,
 resultinfo is a hook for expansion; fmgr itself doesn't constrain the use
 of the field.
 
+fncollation is the input collation derived by the parser, or InvalidOid
+when there are no inputs of collatable types or they don't share a common
+collation.  This is effectively a hidden additional argument, which
+collation-sensitive functions can use to determine their behavior.
+
 nargs, arg[], and argnull[] hold the arguments being passed to the function.
 Notice that all the arguments passed to a function (as well as its result
 value) will now uniformly be of type Datum.  As discussed below, callers
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 0288fbab4bc65e4d4c38bfac150815309f3c59e9..ffa19d5a2d26efce4fd4b121a0cab536b48d3aae 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -192,7 +192,6 @@ fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
 	 * elogs.
 	 */
 	finfo->fn_oid = InvalidOid;
-	finfo->fn_collation = InvalidOid;	/* caller may set this later */
 	finfo->fn_extra = NULL;
 	finfo->fn_mcxt = mcxt;
 	finfo->fn_expr = NULL;		/* caller may set this later */
@@ -901,7 +900,6 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
 
 		fmgr_info_cxt_security(fcinfo->flinfo->fn_oid, &fcache->flinfo,
 							   fcinfo->flinfo->fn_mcxt, true);
-		fcache->flinfo.fn_collation = fcinfo->flinfo->fn_collation;
 		fcache->flinfo.fn_expr = fcinfo->flinfo->fn_expr;
 
 		tuple = SearchSysCache1(PROCOID,
@@ -1012,12 +1010,12 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
  * look at FmgrInfo, since there won't be any.
  */
 Datum
-DirectFunctionCall1(PGFunction func, Datum arg1)
+DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1)
 {
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 1, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, NULL, 1, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.argnull[0] = false;
@@ -1032,12 +1030,12 @@ DirectFunctionCall1(PGFunction func, Datum arg1)
 }
 
 Datum
-DirectFunctionCall2(PGFunction func, Datum arg1, Datum arg2)
+DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2)
 {
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 2, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, NULL, 2, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1054,13 +1052,13 @@ DirectFunctionCall2(PGFunction func, Datum arg1, Datum arg2)
 }
 
 Datum
-DirectFunctionCall3(PGFunction func, Datum arg1, Datum arg2,
+DirectFunctionCall3Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
 					Datum arg3)
 {
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 3, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, NULL, 3, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1079,13 +1077,13 @@ DirectFunctionCall3(PGFunction func, Datum arg1, Datum arg2,
 }
 
 Datum
-DirectFunctionCall4(PGFunction func, Datum arg1, Datum arg2,
+DirectFunctionCall4Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
 					Datum arg3, Datum arg4)
 {
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 4, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, NULL, 4, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1106,13 +1104,13 @@ DirectFunctionCall4(PGFunction func, Datum arg1, Datum arg2,
 }
 
 Datum
-DirectFunctionCall5(PGFunction func, Datum arg1, Datum arg2,
+DirectFunctionCall5Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
 					Datum arg3, Datum arg4, Datum arg5)
 {
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 5, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, NULL, 5, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1135,14 +1133,14 @@ DirectFunctionCall5(PGFunction func, Datum arg1, Datum arg2,
 }
 
 Datum
-DirectFunctionCall6(PGFunction func, Datum arg1, Datum arg2,
+DirectFunctionCall6Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
 					Datum arg3, Datum arg4, Datum arg5,
 					Datum arg6)
 {
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 6, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, NULL, 6, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1167,14 +1165,14 @@ DirectFunctionCall6(PGFunction func, Datum arg1, Datum arg2,
 }
 
 Datum
-DirectFunctionCall7(PGFunction func, Datum arg1, Datum arg2,
+DirectFunctionCall7Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
 					Datum arg3, Datum arg4, Datum arg5,
 					Datum arg6, Datum arg7)
 {
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 7, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, NULL, 7, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1201,14 +1199,14 @@ DirectFunctionCall7(PGFunction func, Datum arg1, Datum arg2,
 }
 
 Datum
-DirectFunctionCall8(PGFunction func, Datum arg1, Datum arg2,
+DirectFunctionCall8Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
 					Datum arg3, Datum arg4, Datum arg5,
 					Datum arg6, Datum arg7, Datum arg8)
 {
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 8, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, NULL, 8, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1237,7 +1235,7 @@ DirectFunctionCall8(PGFunction func, Datum arg1, Datum arg2,
 }
 
 Datum
-DirectFunctionCall9(PGFunction func, Datum arg1, Datum arg2,
+DirectFunctionCall9Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
 					Datum arg3, Datum arg4, Datum arg5,
 					Datum arg6, Datum arg7, Datum arg8,
 					Datum arg9)
@@ -1245,7 +1243,7 @@ DirectFunctionCall9(PGFunction func, Datum arg1, Datum arg2,
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 9, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, NULL, 9, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1276,72 +1274,18 @@ DirectFunctionCall9(PGFunction func, Datum arg1, Datum arg2,
 }
 
 
-/*
- * These are the same as DirectFunctionCallN except that a nonzero
- * collation can be specified.	No other fields of FmgrInfo are made valid.
- */
-Datum
-DirectFunctionCall1WithCollation(PGFunction func, Oid collation, Datum arg1)
-{
-	FunctionCallInfoData fcinfo;
-	FmgrInfo	flinfo;
-	Datum		result;
-
-	MemSet(&flinfo, 0, sizeof(flinfo));
-	flinfo.fn_collation = collation;
-	InitFunctionCallInfoData(fcinfo, &flinfo, 1, NULL, NULL);
-
-	fcinfo.arg[0] = arg1;
-	fcinfo.argnull[0] = false;
-
-	result = (*func) (&fcinfo);
-
-	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %p returned NULL", (void *) func);
-
-	return result;
-}
-
-Datum
-DirectFunctionCall2WithCollation(PGFunction func, Oid collation,
-								 Datum arg1, Datum arg2)
-{
-	FunctionCallInfoData fcinfo;
-	FmgrInfo	flinfo;
-	Datum		result;
-
-	MemSet(&flinfo, 0, sizeof(flinfo));
-	flinfo.fn_collation = collation;
-	InitFunctionCallInfoData(fcinfo, &flinfo, 2, NULL, NULL);
-
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-
-	result = (*func) (&fcinfo);
-
-	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %p returned NULL", (void *) func);
-
-	return result;
-}
-
-
 /*
  * These are for invocation of a previously-looked-up function with a
  * directly-computed parameter list.  Note that neither arguments nor result
  * are allowed to be NULL.
  */
 Datum
-FunctionCall1(FmgrInfo *flinfo, Datum arg1)
+FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
 {
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 1, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, flinfo, 1, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.argnull[0] = false;
@@ -1356,7 +1300,7 @@ FunctionCall1(FmgrInfo *flinfo, Datum arg1)
 }
 
 Datum
-FunctionCall2(FmgrInfo *flinfo, Datum arg1, Datum arg2)
+FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
 {
 	/*
 	 * XXX if you change this routine, see also the inlined version in
@@ -1365,7 +1309,7 @@ FunctionCall2(FmgrInfo *flinfo, Datum arg1, Datum arg2)
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 2, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, flinfo, 2, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1382,13 +1326,13 @@ FunctionCall2(FmgrInfo *flinfo, Datum arg1, Datum arg2)
 }
 
 Datum
-FunctionCall3(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
 			  Datum arg3)
 {
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 3, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, flinfo, 3, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1407,13 +1351,13 @@ FunctionCall3(FmgrInfo *flinfo, Datum arg1, Datum arg2,
 }
 
 Datum
-FunctionCall4(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+FunctionCall4Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
 			  Datum arg3, Datum arg4)
 {
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 4, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, flinfo, 4, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1434,13 +1378,13 @@ FunctionCall4(FmgrInfo *flinfo, Datum arg1, Datum arg2,
 }
 
 Datum
-FunctionCall5(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+FunctionCall5Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
 			  Datum arg3, Datum arg4, Datum arg5)
 {
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 5, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, flinfo, 5, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1463,14 +1407,14 @@ FunctionCall5(FmgrInfo *flinfo, Datum arg1, Datum arg2,
 }
 
 Datum
-FunctionCall6(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+FunctionCall6Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
 			  Datum arg3, Datum arg4, Datum arg5,
 			  Datum arg6)
 {
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 6, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, flinfo, 6, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1495,14 +1439,14 @@ FunctionCall6(FmgrInfo *flinfo, Datum arg1, Datum arg2,
 }
 
 Datum
-FunctionCall7(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+FunctionCall7Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
 			  Datum arg3, Datum arg4, Datum arg5,
 			  Datum arg6, Datum arg7)
 {
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 7, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, flinfo, 7, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1529,14 +1473,14 @@ FunctionCall7(FmgrInfo *flinfo, Datum arg1, Datum arg2,
 }
 
 Datum
-FunctionCall8(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+FunctionCall8Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
 			  Datum arg3, Datum arg4, Datum arg5,
 			  Datum arg6, Datum arg7, Datum arg8)
 {
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 8, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, flinfo, 8, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1565,7 +1509,7 @@ FunctionCall8(FmgrInfo *flinfo, Datum arg1, Datum arg2,
 }
 
 Datum
-FunctionCall9(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+FunctionCall9Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
 			  Datum arg3, Datum arg4, Datum arg5,
 			  Datum arg6, Datum arg7, Datum arg8,
 			  Datum arg9)
@@ -1573,7 +1517,7 @@ FunctionCall9(FmgrInfo *flinfo, Datum arg1, Datum arg2,
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 9, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, flinfo, 9, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1612,7 +1556,7 @@ FunctionCall9(FmgrInfo *flinfo, Datum arg1, Datum arg2,
  * do the fmgr_info() once and then use FunctionCallN().
  */
 Datum
-OidFunctionCall0(Oid functionId)
+OidFunctionCall0Coll(Oid functionId, Oid collation)
 {
 	FmgrInfo	flinfo;
 	FunctionCallInfoData fcinfo;
@@ -1620,7 +1564,7 @@ OidFunctionCall0(Oid functionId)
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 0, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, &flinfo, 0, collation, NULL, NULL);
 
 	result = FunctionCallInvoke(&fcinfo);
 
@@ -1632,7 +1576,7 @@ OidFunctionCall0(Oid functionId)
 }
 
 Datum
-OidFunctionCall1(Oid functionId, Datum arg1)
+OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1)
 {
 	FmgrInfo	flinfo;
 	FunctionCallInfoData fcinfo;
@@ -1640,7 +1584,7 @@ OidFunctionCall1(Oid functionId, Datum arg1)
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 1, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, &flinfo, 1, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.argnull[0] = false;
@@ -1655,7 +1599,7 @@ OidFunctionCall1(Oid functionId, Datum arg1)
 }
 
 Datum
-OidFunctionCall2(Oid functionId, Datum arg1, Datum arg2)
+OidFunctionCall2Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2)
 {
 	FmgrInfo	flinfo;
 	FunctionCallInfoData fcinfo;
@@ -1663,7 +1607,7 @@ OidFunctionCall2(Oid functionId, Datum arg1, Datum arg2)
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 2, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, &flinfo, 2, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1680,7 +1624,7 @@ OidFunctionCall2(Oid functionId, Datum arg1, Datum arg2)
 }
 
 Datum
-OidFunctionCall3(Oid functionId, Datum arg1, Datum arg2,
+OidFunctionCall3Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
 				 Datum arg3)
 {
 	FmgrInfo	flinfo;
@@ -1689,7 +1633,7 @@ OidFunctionCall3(Oid functionId, Datum arg1, Datum arg2,
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 3, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, &flinfo, 3, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1708,7 +1652,7 @@ OidFunctionCall3(Oid functionId, Datum arg1, Datum arg2,
 }
 
 Datum
-OidFunctionCall4(Oid functionId, Datum arg1, Datum arg2,
+OidFunctionCall4Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
 				 Datum arg3, Datum arg4)
 {
 	FmgrInfo	flinfo;
@@ -1717,7 +1661,7 @@ OidFunctionCall4(Oid functionId, Datum arg1, Datum arg2,
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 4, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, &flinfo, 4, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1738,7 +1682,7 @@ OidFunctionCall4(Oid functionId, Datum arg1, Datum arg2,
 }
 
 Datum
-OidFunctionCall5(Oid functionId, Datum arg1, Datum arg2,
+OidFunctionCall5Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
 				 Datum arg3, Datum arg4, Datum arg5)
 {
 	FmgrInfo	flinfo;
@@ -1747,7 +1691,7 @@ OidFunctionCall5(Oid functionId, Datum arg1, Datum arg2,
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 5, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, &flinfo, 5, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1770,7 +1714,7 @@ OidFunctionCall5(Oid functionId, Datum arg1, Datum arg2,
 }
 
 Datum
-OidFunctionCall6(Oid functionId, Datum arg1, Datum arg2,
+OidFunctionCall6Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
 				 Datum arg3, Datum arg4, Datum arg5,
 				 Datum arg6)
 {
@@ -1780,7 +1724,7 @@ OidFunctionCall6(Oid functionId, Datum arg1, Datum arg2,
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 6, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, &flinfo, 6, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1805,7 +1749,7 @@ OidFunctionCall6(Oid functionId, Datum arg1, Datum arg2,
 }
 
 Datum
-OidFunctionCall7(Oid functionId, Datum arg1, Datum arg2,
+OidFunctionCall7Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
 				 Datum arg3, Datum arg4, Datum arg5,
 				 Datum arg6, Datum arg7)
 {
@@ -1815,7 +1759,7 @@ OidFunctionCall7(Oid functionId, Datum arg1, Datum arg2,
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 7, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, &flinfo, 7, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1842,7 +1786,7 @@ OidFunctionCall7(Oid functionId, Datum arg1, Datum arg2,
 }
 
 Datum
-OidFunctionCall8(Oid functionId, Datum arg1, Datum arg2,
+OidFunctionCall8Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
 				 Datum arg3, Datum arg4, Datum arg5,
 				 Datum arg6, Datum arg7, Datum arg8)
 {
@@ -1852,7 +1796,7 @@ OidFunctionCall8(Oid functionId, Datum arg1, Datum arg2,
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 8, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, &flinfo, 8, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1881,7 +1825,7 @@ OidFunctionCall8(Oid functionId, Datum arg1, Datum arg2,
 }
 
 Datum
-OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2,
+OidFunctionCall9Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
 				 Datum arg3, Datum arg4, Datum arg5,
 				 Datum arg6, Datum arg7, Datum arg8,
 				 Datum arg9)
@@ -1892,7 +1836,7 @@ OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2,
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 9, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, &flinfo, 9, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -1953,7 +1897,7 @@ InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
 
 	pushed = SPI_push_conditional();
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 3, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
 
 	fcinfo.arg[0] = CStringGetDatum(str);
 	fcinfo.arg[1] = ObjectIdGetDatum(typioparam);
@@ -2028,7 +1972,7 @@ ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf,
 
 	pushed = SPI_push_conditional();
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 3, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
 
 	fcinfo.arg[0] = PointerGetDatum(buf);
 	fcinfo.arg[1] = ObjectIdGetDatum(typioparam);
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index bd5b4b0a7d7d22ebd5693c8df7fc84cd20f4e704..dcfb8f957a9bb203f4ab9ffefb140ac9141c28dc 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -373,6 +373,7 @@ struct Tuplesortstate
 	Oid			datumType;
 	FmgrInfo	sortOpFn;		/* cached lookup data for sortOperator */
 	int			sortFnFlags;	/* equivalent to sk_flags */
+	Oid			sortCollation;	/* equivalent to sk_collation */
 	/* we need typelen and byval in order to know how to copy the Datums. */
 	int			datumTypeLen;
 	bool		datumTypeByVal;
@@ -582,7 +583,8 @@ tuplesort_begin_common(int workMem, bool randomAccess)
 Tuplesortstate *
 tuplesort_begin_heap(TupleDesc tupDesc,
 					 int nkeys, AttrNumber *attNums,
-				  Oid *sortOperators, Oid *collations, bool *nullsFirstFlags,
+					 Oid *sortOperators, Oid *sortCollations,
+					 bool *nullsFirstFlags,
 					 int workMem, bool randomAccess)
 {
 	Tuplesortstate *state = tuplesort_begin_common(workMem, randomAccess);
@@ -647,7 +649,7 @@ tuplesort_begin_heap(TupleDesc tupDesc,
 							   attNums[i],
 							   InvalidStrategy,
 							   InvalidOid,
-							   collations ? collations[i] : InvalidOid,
+							   sortCollations[i],
 							   sortFunction,
 							   (Datum) 0);
 	}
@@ -795,8 +797,8 @@ tuplesort_begin_index_hash(Relation indexRel,
 }
 
 Tuplesortstate *
-tuplesort_begin_datum(Oid datumType,
-					Oid sortOperator, Oid sortCollation, bool nullsFirstFlag,
+tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
+					  bool nullsFirstFlag,
 					  int workMem, bool randomAccess)
 {
 	Tuplesortstate *state = tuplesort_begin_common(workMem, randomAccess);
@@ -837,12 +839,12 @@ tuplesort_begin_datum(Oid datumType,
 		elog(ERROR, "operator %u is not a valid ordering operator",
 			 sortOperator);
 	fmgr_info(sortFunction, &state->sortOpFn);
-	fmgr_info_set_collation(sortCollation, &state->sortOpFn);
 
-	/* set ordering flags */
+	/* set ordering flags and collation */
 	state->sortFnFlags = reverse ? SK_BT_DESC : 0;
 	if (nullsFirstFlag)
 		state->sortFnFlags |= SK_BT_NULLS_FIRST;
+	state->sortCollation = sortCollation;
 
 	/* lookup necessary attributes of the datum type */
 	get_typlenbyval(datumType, &typlen, &typbyval);
@@ -2630,15 +2632,15 @@ SelectSortFunction(Oid sortOperator,
 }
 
 /*
- * Inline-able copy of FunctionCall2() to save some cycles in sorting.
+ * Inline-able copy of FunctionCall2Coll() to save some cycles in sorting.
  */
 static inline Datum
-myFunctionCall2(FmgrInfo *flinfo, Datum arg1, Datum arg2)
+myFunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
 {
 	FunctionCallInfoData fcinfo;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 2, NULL, NULL);
+	InitFunctionCallInfoData(fcinfo, flinfo, 2, collation, NULL, NULL);
 
 	fcinfo.arg[0] = arg1;
 	fcinfo.arg[1] = arg2;
@@ -2661,7 +2663,7 @@ myFunctionCall2(FmgrInfo *flinfo, Datum arg1, Datum arg2)
  * NULLS_FIRST options are encoded in sk_flags the same way btree does it.
  */
 static inline int32
-inlineApplySortFunction(FmgrInfo *sortFunction, int sk_flags,
+inlineApplySortFunction(FmgrInfo *sortFunction, int sk_flags, Oid collation,
 						Datum datum1, bool isNull1,
 						Datum datum2, bool isNull2)
 {
@@ -2685,8 +2687,8 @@ inlineApplySortFunction(FmgrInfo *sortFunction, int sk_flags,
 	}
 	else
 	{
-		compare = DatumGetInt32(myFunctionCall2(sortFunction,
-												datum1, datum2));
+		compare = DatumGetInt32(myFunctionCall2Coll(sortFunction, collation,
+													datum1, datum2));
 
 		if (sk_flags & SK_BT_DESC)
 			compare = -compare;
@@ -2700,11 +2702,11 @@ inlineApplySortFunction(FmgrInfo *sortFunction, int sk_flags,
  * C99's brain-dead notions about how to implement inline functions...
  */
 int32
-ApplySortFunction(FmgrInfo *sortFunction, int sortFlags,
+ApplySortFunction(FmgrInfo *sortFunction, int sortFlags, Oid collation,
 				  Datum datum1, bool isNull1,
 				  Datum datum2, bool isNull2)
 {
-	return inlineApplySortFunction(sortFunction, sortFlags,
+	return inlineApplySortFunction(sortFunction, sortFlags, collation,
 								   datum1, isNull1,
 								   datum2, isNull2);
 }
@@ -2729,6 +2731,7 @@ comparetup_heap(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
 
 	/* Compare the leading sort key */
 	compare = inlineApplySortFunction(&scanKey->sk_func, scanKey->sk_flags,
+									  scanKey->sk_collation,
 									  a->datum1, a->isnull1,
 									  b->datum1, b->isnull1);
 	if (compare != 0)
@@ -2753,6 +2756,7 @@ comparetup_heap(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
 		datum2 = heap_getattr(&rtup, attno, tupDesc, &isnull2);
 
 		compare = inlineApplySortFunction(&scanKey->sk_func, scanKey->sk_flags,
+										  scanKey->sk_collation,
 										  datum1, isnull1,
 										  datum2, isnull2);
 		if (compare != 0)
@@ -2874,6 +2878,7 @@ comparetup_cluster(const SortTuple *a, const SortTuple *b,
 	if (state->indexInfo->ii_KeyAttrNumbers[0] != 0)
 	{
 		compare = inlineApplySortFunction(&scanKey->sk_func, scanKey->sk_flags,
+										  scanKey->sk_collation,
 										  a->datum1, a->isnull1,
 										  b->datum1, b->isnull1);
 		if (compare != 0 || state->nKeys == 1)
@@ -2910,6 +2915,7 @@ comparetup_cluster(const SortTuple *a, const SortTuple *b,
 
 			compare = inlineApplySortFunction(&scanKey->sk_func,
 											  scanKey->sk_flags,
+											  scanKey->sk_collation,
 											  datum1, isnull1,
 											  datum2, isnull2);
 			if (compare != 0)
@@ -2947,6 +2953,7 @@ comparetup_cluster(const SortTuple *a, const SortTuple *b,
 		{
 			compare = inlineApplySortFunction(&scanKey->sk_func,
 											  scanKey->sk_flags,
+											  scanKey->sk_collation,
 											  l_index_values[nkey],
 											  l_index_isnull[nkey],
 											  r_index_values[nkey],
@@ -3060,6 +3067,7 @@ comparetup_index_btree(const SortTuple *a, const SortTuple *b,
 
 	/* Compare the leading sort key */
 	compare = inlineApplySortFunction(&scanKey->sk_func, scanKey->sk_flags,
+									  scanKey->sk_collation,
 									  a->datum1, a->isnull1,
 									  b->datum1, b->isnull1);
 	if (compare != 0)
@@ -3086,6 +3094,7 @@ comparetup_index_btree(const SortTuple *a, const SortTuple *b,
 		datum2 = index_getattr(tuple2, nkey, tupDes, &isnull2);
 
 		compare = inlineApplySortFunction(&scanKey->sk_func, scanKey->sk_flags,
+										  scanKey->sk_collation,
 										  datum1, isnull1,
 										  datum2, isnull2);
 		if (compare != 0)
@@ -3293,6 +3302,7 @@ comparetup_datum(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
 	CHECK_FOR_INTERRUPTS();
 
 	return inlineApplySortFunction(&state->sortOpFn, state->sortFnFlags,
+								   state->sortCollation,
 								   a->datum1, a->isnull1,
 								   b->datum1, b->isnull1);
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 74c1098458c2e5108e95507e6da00ca98b5534c6..06c6fa2f9c6ec66682bb05ba8fdaac94a8751882 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -303,6 +303,8 @@ typedef struct GinState
 	FmgrInfo	comparePartialFn[INDEX_MAX_KEYS];		/* optional method */
 	/* canPartialMatch[i] is true if comparePartialFn[i] is valid */
 	bool		canPartialMatch[INDEX_MAX_KEYS];
+	/* Collations to supply to the compareFns and comparePartialFns */
+	Oid			compareCollation[INDEX_MAX_KEYS];
 } GinState;
 
 /* XLog stuff */
diff --git a/src/include/access/skey.h b/src/include/access/skey.h
index 1d0071ac2d33ae414b416515ea1f814aace0649d..a82e46ee0e1b8c5ed8ebaff11cc031ff6764358c 100644
--- a/src/include/access/skey.h
+++ b/src/include/access/skey.h
@@ -52,16 +52,16 @@ typedef uint16 StrategyNumber;
  * the operator.  When using a ScanKey in a heap scan, these fields are not
  * used and may be set to InvalidStrategy/InvalidOid.
  *
- * If the operator is collation-sensitive, sk_func.fn_collation must be set
+ * If the operator is collation-sensitive, sk_collation must be set
  * correctly as well.
  *
  * A ScanKey can also represent a condition "column IS NULL" or "column
  * IS NOT NULL"; these cases are signaled by the SK_SEARCHNULL and
  * SK_SEARCHNOTNULL flag bits respectively.  The argument is always NULL,
- * and the sk_strategy, sk_subtype, and sk_func fields are not used (unless
- * set by the index AM).  Currently, SK_SEARCHNULL and SK_SEARCHNOTNULL are
- * supported only for index scans, not heap scans; and not all index AMs
- * support them.
+ * and the sk_strategy, sk_subtype, sk_collation, and sk_func fields are
+ * not used (unless set by the index AM).  Currently, SK_SEARCHNULL and
+ * SK_SEARCHNOTNULL are supported only for index scans, not heap scans;
+ * and not all index AMs support them.
  *
  * A ScanKey can also represent an ordering operator invocation, that is
  * an ordering requirement "ORDER BY indexedcol op constant".  This looks
@@ -70,8 +70,8 @@ typedef uint16 StrategyNumber;
  *
  * Note: in some places, ScanKeys are used as a convenient representation
  * for the invocation of an access method support procedure.  In this case
- * sk_strategy/sk_subtype are not meaningful, and sk_func may refer to a
- * function that returns something other than boolean.
+ * sk_strategy/sk_subtype are not meaningful (but sk_collation can be); and
+ * sk_func may refer to a function that returns something other than boolean.
  */
 typedef struct ScanKeyData
 {
@@ -79,6 +79,7 @@ typedef struct ScanKeyData
 	AttrNumber	sk_attno;		/* table or index column number */
 	StrategyNumber sk_strategy; /* operator strategy number */
 	Oid			sk_subtype;		/* strategy subtype */
+	Oid			sk_collation;	/* collation to use, if needed */
 	FmgrInfo	sk_func;		/* lookup info for function to call */
 	Datum		sk_argument;	/* data to compare */
 } ScanKeyData;
@@ -99,7 +100,7 @@ typedef ScanKeyData *ScanKey;
  *		sk_attno = index column number for leading column of row comparison
  *		sk_strategy = btree strategy code for semantics of row comparison
  *				(ie, < <= > or >=)
- *		sk_subtype, sk_func: not used
+ *		sk_subtype, sk_collation, sk_func: not used
  *		sk_argument: pointer to subsidiary ScanKey array
  * If the header is part of a ScanKey array that's sorted by attno, it
  * must be sorted according to the leading column number.
diff --git a/src/include/access/valid.h b/src/include/access/valid.h
index e81f4cb723bfb02eadf51ffd057bdb39aa1a8b06..f52ff4fb17952c0bc6bc7cd090e0bcf21701ad54 100644
--- a/src/include/access/valid.h
+++ b/src/include/access/valid.h
@@ -54,8 +54,9 @@ do \
 			break; \
 		} \
  \
-		__test = FunctionCall2(&__cur_keys->sk_func, \
-							   __atp, __cur_keys->sk_argument); \
+		__test = FunctionCall2Coll(&__cur_keys->sk_func, \
+								   __cur_keys->sk_collation, \
+								   __atp, __cur_keys->sk_argument); \
  \
 		if (!DatumGetBool(__test)) \
 		{ \
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index e58060f834615d41181835a67b61f6054fd6d260..60d47d97b9d6e4033c73a57cc0da07794bb60471 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -41,10 +41,10 @@ typedef Datum (*PGFunction) (FunctionCallInfo fcinfo);
  * to be called multiple times, the lookup need be done only once and the
  * info struct saved for re-use.
  *
- * Note that fn_collation and fn_expr really are parse-time-determined
- * information about the arguments, rather than about the function itself.
- * But it's convenient to store them here rather than in FunctionCallInfoData,
- * where they might more logically belong.
+ * Note that fn_expr really is parse-time-determined information about the
+ * arguments, rather than about the function itself.  But it's convenient
+ * to store it here rather than in FunctionCallInfoData, where it might more
+ * logically belong.
  */
 typedef struct FmgrInfo
 {
@@ -55,7 +55,6 @@ typedef struct FmgrInfo
 	bool		fn_strict;		/* function is "strict" (NULL in => NULL out) */
 	bool		fn_retset;		/* function returns a set */
 	unsigned char fn_stats;		/* collect stats if track_functions > this */
-	Oid			fn_collation;	/* collation that function should use */
 	void	   *fn_extra;		/* extra space for use by handler */
 	MemoryContext fn_mcxt;		/* memory context to store fn_extra in */
 	fmNodePtr	fn_expr;		/* expression parse tree for call, or NULL */
@@ -69,6 +68,7 @@ typedef struct FunctionCallInfoData
 	FmgrInfo   *flinfo;			/* ptr to lookup info used for this call */
 	fmNodePtr	context;		/* pass info about context of call */
 	fmNodePtr	resultinfo;		/* pass or return extra info about result */
+	Oid			fncollation;	/* collation for function to use */
 	bool		isnull;			/* function must set true if result is NULL */
 	short		nargs;			/* # arguments actually passed */
 	Datum		arg[FUNC_MAX_ARGS];		/* Arguments passed to function */
@@ -89,9 +89,7 @@ extern void fmgr_info(Oid functionId, FmgrInfo *finfo);
 extern void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo,
 			  MemoryContext mcxt);
 
-/* Macros for setting the fn_collation and fn_expr fields */
-#define fmgr_info_set_collation(collationId, finfo) \
-	((finfo)->fn_collation = (collationId))
+/* Convenience macro for setting the fn_expr field */
 #define fmgr_info_set_expr(expr, finfo) \
 	((finfo)->fn_expr = (expr))
 
@@ -108,11 +106,12 @@ extern void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo,
  * explicitly set each required element to false, so we don't try to zero
  * out the argnull[] array in the macro.
  */
-#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Context, Resultinfo) \
+#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo) \
 	do { \
 		(Fcinfo).flinfo = (Flinfo); \
 		(Fcinfo).context = (Context); \
 		(Fcinfo).resultinfo = (Resultinfo); \
+		(Fcinfo).fncollation = (Collation); \
 		(Fcinfo).isnull = false; \
 		(Fcinfo).nargs = (Nargs); \
 	} while (0)
@@ -150,8 +149,7 @@ extern void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo,
 /*
  * Get collation function should use.
  */
-#define PG_GET_COLLATION() \
-	(fcinfo->flinfo ? fcinfo->flinfo->fn_collation : InvalidOid)
+#define PG_GET_COLLATION()	(fcinfo->fncollation)
 
 /*
  * Get number of arguments passed to function.
@@ -434,56 +432,68 @@ extern int no_such_variable
  * directly-computed parameter list.  Note that neither arguments nor result
  * are allowed to be NULL.
  */
-extern Datum DirectFunctionCall1(PGFunction func, Datum arg1);
-extern Datum DirectFunctionCall2(PGFunction func, Datum arg1, Datum arg2);
-extern Datum DirectFunctionCall3(PGFunction func, Datum arg1, Datum arg2,
+extern Datum DirectFunctionCall1Coll(PGFunction func, Oid collation,
+									 Datum arg1);
+extern Datum DirectFunctionCall2Coll(PGFunction func, Oid collation,
+									 Datum arg1, Datum arg2);
+extern Datum DirectFunctionCall3Coll(PGFunction func, Oid collation,
+									 Datum arg1, Datum arg2,
 					Datum arg3);
-extern Datum DirectFunctionCall4(PGFunction func, Datum arg1, Datum arg2,
+extern Datum DirectFunctionCall4Coll(PGFunction func, Oid collation,
+									 Datum arg1, Datum arg2,
 					Datum arg3, Datum arg4);
-extern Datum DirectFunctionCall5(PGFunction func, Datum arg1, Datum arg2,
+extern Datum DirectFunctionCall5Coll(PGFunction func, Oid collation,
+									 Datum arg1, Datum arg2,
 					Datum arg3, Datum arg4, Datum arg5);
-extern Datum DirectFunctionCall6(PGFunction func, Datum arg1, Datum arg2,
+extern Datum DirectFunctionCall6Coll(PGFunction func, Oid collation,
+									 Datum arg1, Datum arg2,
 					Datum arg3, Datum arg4, Datum arg5,
 					Datum arg6);
-extern Datum DirectFunctionCall7(PGFunction func, Datum arg1, Datum arg2,
+extern Datum DirectFunctionCall7Coll(PGFunction func, Oid collation,
+									 Datum arg1, Datum arg2,
 					Datum arg3, Datum arg4, Datum arg5,
 					Datum arg6, Datum arg7);
-extern Datum DirectFunctionCall8(PGFunction func, Datum arg1, Datum arg2,
+extern Datum DirectFunctionCall8Coll(PGFunction func, Oid collation,
+									 Datum arg1, Datum arg2,
 					Datum arg3, Datum arg4, Datum arg5,
 					Datum arg6, Datum arg7, Datum arg8);
-extern Datum DirectFunctionCall9(PGFunction func, Datum arg1, Datum arg2,
+extern Datum DirectFunctionCall9Coll(PGFunction func, Oid collation,
+									 Datum arg1, Datum arg2,
 					Datum arg3, Datum arg4, Datum arg5,
 					Datum arg6, Datum arg7, Datum arg8,
 					Datum arg9);
 
-/* The same, but passing a collation to use */
-extern Datum DirectFunctionCall1WithCollation(PGFunction func, Oid collation,
-								 Datum arg1);
-extern Datum DirectFunctionCall2WithCollation(PGFunction func, Oid collation,
-								 Datum arg1, Datum arg2);
-
 /* These are for invocation of a previously-looked-up function with a
  * directly-computed parameter list.  Note that neither arguments nor result
  * are allowed to be NULL.
  */
-extern Datum FunctionCall1(FmgrInfo *flinfo, Datum arg1);
-extern Datum FunctionCall2(FmgrInfo *flinfo, Datum arg1, Datum arg2);
-extern Datum FunctionCall3(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+extern Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation,
+							   Datum arg1);
+extern Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation,
+							   Datum arg1, Datum arg2);
+extern Datum FunctionCall3Coll(FmgrInfo *flinfo, Oid collation,
+							   Datum arg1, Datum arg2,
 			  Datum arg3);
-extern Datum FunctionCall4(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+extern Datum FunctionCall4Coll(FmgrInfo *flinfo, Oid collation,
+							   Datum arg1, Datum arg2,
 			  Datum arg3, Datum arg4);
-extern Datum FunctionCall5(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+extern Datum FunctionCall5Coll(FmgrInfo *flinfo, Oid collation,
+							   Datum arg1, Datum arg2,
 			  Datum arg3, Datum arg4, Datum arg5);
-extern Datum FunctionCall6(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+extern Datum FunctionCall6Coll(FmgrInfo *flinfo, Oid collation,
+							   Datum arg1, Datum arg2,
 			  Datum arg3, Datum arg4, Datum arg5,
 			  Datum arg6);
-extern Datum FunctionCall7(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+extern Datum FunctionCall7Coll(FmgrInfo *flinfo, Oid collation,
+							   Datum arg1, Datum arg2,
 			  Datum arg3, Datum arg4, Datum arg5,
 			  Datum arg6, Datum arg7);
-extern Datum FunctionCall8(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+extern Datum FunctionCall8Coll(FmgrInfo *flinfo, Oid collation,
+							   Datum arg1, Datum arg2,
 			  Datum arg3, Datum arg4, Datum arg5,
 			  Datum arg6, Datum arg7, Datum arg8);
-extern Datum FunctionCall9(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+extern Datum FunctionCall9Coll(FmgrInfo *flinfo, Oid collation,
+							   Datum arg1, Datum arg2,
 			  Datum arg3, Datum arg4, Datum arg5,
 			  Datum arg6, Datum arg7, Datum arg8,
 			  Datum arg9);
@@ -494,29 +504,100 @@ extern Datum FunctionCall9(FmgrInfo *flinfo, Datum arg1, Datum arg2,
  * by FunctionCallN().	If the same function is to be invoked repeatedly,
  * do the FunctionLookup() once and then use FunctionCallN().
  */
-extern Datum OidFunctionCall0(Oid functionId);
-extern Datum OidFunctionCall1(Oid functionId, Datum arg1);
-extern Datum OidFunctionCall2(Oid functionId, Datum arg1, Datum arg2);
-extern Datum OidFunctionCall3(Oid functionId, Datum arg1, Datum arg2,
+extern Datum OidFunctionCall0Coll(Oid functionId, Oid collation);
+extern Datum OidFunctionCall1Coll(Oid functionId, Oid collation,
+								  Datum arg1);
+extern Datum OidFunctionCall2Coll(Oid functionId, Oid collation,
+								  Datum arg1, Datum arg2);
+extern Datum OidFunctionCall3Coll(Oid functionId, Oid collation,
+								  Datum arg1, Datum arg2,
 				 Datum arg3);
-extern Datum OidFunctionCall4(Oid functionId, Datum arg1, Datum arg2,
+extern Datum OidFunctionCall4Coll(Oid functionId, Oid collation,
+								  Datum arg1, Datum arg2,
 				 Datum arg3, Datum arg4);
-extern Datum OidFunctionCall5(Oid functionId, Datum arg1, Datum arg2,
+extern Datum OidFunctionCall5Coll(Oid functionId, Oid collation,
+								  Datum arg1, Datum arg2,
 				 Datum arg3, Datum arg4, Datum arg5);
-extern Datum OidFunctionCall6(Oid functionId, Datum arg1, Datum arg2,
+extern Datum OidFunctionCall6Coll(Oid functionId, Oid collation,
+								  Datum arg1, Datum arg2,
 				 Datum arg3, Datum arg4, Datum arg5,
 				 Datum arg6);
-extern Datum OidFunctionCall7(Oid functionId, Datum arg1, Datum arg2,
+extern Datum OidFunctionCall7Coll(Oid functionId, Oid collation,
+								  Datum arg1, Datum arg2,
 				 Datum arg3, Datum arg4, Datum arg5,
 				 Datum arg6, Datum arg7);
-extern Datum OidFunctionCall8(Oid functionId, Datum arg1, Datum arg2,
+extern Datum OidFunctionCall8Coll(Oid functionId, Oid collation,
+								  Datum arg1, Datum arg2,
 				 Datum arg3, Datum arg4, Datum arg5,
 				 Datum arg6, Datum arg7, Datum arg8);
-extern Datum OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2,
+extern Datum OidFunctionCall9Coll(Oid functionId, Oid collation,
+								  Datum arg1, Datum arg2,
 				 Datum arg3, Datum arg4, Datum arg5,
 				 Datum arg6, Datum arg7, Datum arg8,
 				 Datum arg9);
 
+/* These macros allow the collation argument to be omitted (with a default of
+ * InvalidOid, ie, no collation).  They exist mostly for backwards
+ * compatibility of source code.
+ */
+#define DirectFunctionCall1(func, arg1) \
+	DirectFunctionCall1Coll(func, InvalidOid, arg1)
+#define DirectFunctionCall2(func, arg1, arg2) \
+	DirectFunctionCall2Coll(func, InvalidOid, arg1, arg2)
+#define DirectFunctionCall3(func, arg1, arg2, arg3) \
+	DirectFunctionCall3Coll(func, InvalidOid, arg1, arg2, arg3)
+#define DirectFunctionCall4(func, arg1, arg2, arg3, arg4) \
+	DirectFunctionCall4Coll(func, InvalidOid, arg1, arg2, arg3, arg4)
+#define DirectFunctionCall5(func, arg1, arg2, arg3, arg4, arg5) \
+	DirectFunctionCall5Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5)
+#define DirectFunctionCall6(func, arg1, arg2, arg3, arg4, arg5, arg6) \
+	DirectFunctionCall6Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6)
+#define DirectFunctionCall7(func, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
+	DirectFunctionCall7Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
+#define DirectFunctionCall8(func, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
+	DirectFunctionCall8Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
+#define DirectFunctionCall9(func, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
+	DirectFunctionCall9Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
+#define FunctionCall1(flinfo, arg1) \
+	FunctionCall1Coll(flinfo, InvalidOid, arg1)
+#define FunctionCall2(flinfo, arg1, arg2) \
+	FunctionCall2Coll(flinfo, InvalidOid, arg1, arg2)
+#define FunctionCall3(flinfo, arg1, arg2, arg3) \
+	FunctionCall3Coll(flinfo, InvalidOid, arg1, arg2, arg3)
+#define FunctionCall4(flinfo, arg1, arg2, arg3, arg4) \
+	FunctionCall4Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4)
+#define FunctionCall5(flinfo, arg1, arg2, arg3, arg4, arg5) \
+	FunctionCall5Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5)
+#define FunctionCall6(flinfo, arg1, arg2, arg3, arg4, arg5, arg6) \
+	FunctionCall6Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6)
+#define FunctionCall7(flinfo, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
+	FunctionCall7Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
+#define FunctionCall8(flinfo, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
+	FunctionCall8Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
+#define FunctionCall9(flinfo, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
+	FunctionCall9Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
+#define OidFunctionCall0(functionId) \
+	OidFunctionCall0Coll(functionId, InvalidOid)
+#define OidFunctionCall1(functionId, arg1) \
+	OidFunctionCall1Coll(functionId, InvalidOid, arg1)
+#define OidFunctionCall2(functionId, arg1, arg2) \
+	OidFunctionCall2Coll(functionId, InvalidOid, arg1, arg2)
+#define OidFunctionCall3(functionId, arg1, arg2, arg3) \
+	OidFunctionCall3Coll(functionId, InvalidOid, arg1, arg2, arg3)
+#define OidFunctionCall4(functionId, arg1, arg2, arg3, arg4) \
+	OidFunctionCall4Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4)
+#define OidFunctionCall5(functionId, arg1, arg2, arg3, arg4, arg5) \
+	OidFunctionCall5Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5)
+#define OidFunctionCall6(functionId, arg1, arg2, arg3, arg4, arg5, arg6) \
+	OidFunctionCall6Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6)
+#define OidFunctionCall7(functionId, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
+	OidFunctionCall7Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
+#define OidFunctionCall8(functionId, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
+	OidFunctionCall8Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
+#define OidFunctionCall9(functionId, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
+	OidFunctionCall9Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
+
+
 /* Special cases for convenient invocation of datatype I/O functions. */
 extern Datum InputFunctionCall(FmgrInfo *flinfo, char *str,
 				  Oid typioparam, int32 typmod);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 9c688c036861cca70b4bfdd4109acfb2b130cd18..16756616e5215503ba4e26889fce2b4d144d24de 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -864,6 +864,7 @@ typedef struct RowCompareExprState
 	List	   *largs;			/* the left-hand input arguments */
 	List	   *rargs;			/* the right-hand input arguments */
 	FmgrInfo   *funcs;			/* array of comparison function info */
+	Oid		   *collations;		/* array of collations to use */
 } RowCompareExprState;
 
 /* ----------------
diff --git a/src/include/utils/selfuncs.h b/src/include/utils/selfuncs.h
index c1b417ad8fbd3be553afcd529862c139b1e8c75f..dd38a0292fc763c6189f5133f8db681532da5347 100644
--- a/src/include/utils/selfuncs.h
+++ b/src/include/utils/selfuncs.h
@@ -135,7 +135,8 @@ extern Pattern_Prefix_Status pattern_fixed_prefix(Const *patt,
 					 Oid collation,
 					 Const **prefix,
 					 Const **rest);
-extern Const *make_greater_string(const Const *str_const, FmgrInfo *ltproc);
+extern Const *make_greater_string(const Const *str_const, FmgrInfo *ltproc,
+								  Oid collation);
 
 extern Datum eqsel(PG_FUNCTION_ARGS);
 extern Datum neqsel(PG_FUNCTION_ARGS);
diff --git a/src/include/utils/tuplesort.h b/src/include/utils/tuplesort.h
index a2085df8691fcbd9db29ac82f66b51d9a459c023..1ebcbfe17242a8e5262fe5d942210d0d77b1dd73 100644
--- a/src/include/utils/tuplesort.h
+++ b/src/include/utils/tuplesort.h
@@ -60,7 +60,8 @@ typedef struct Tuplesortstate Tuplesortstate;
 
 extern Tuplesortstate *tuplesort_begin_heap(TupleDesc tupDesc,
 					 int nkeys, AttrNumber *attNums,
-				  Oid *sortOperators, Oid *collations, bool *nullsFirstFlags,
+					 Oid *sortOperators, Oid *sortCollations,
+					 bool *nullsFirstFlags,
 					 int workMem, bool randomAccess);
 extern Tuplesortstate *tuplesort_begin_cluster(TupleDesc tupDesc,
 						Relation indexRel,
@@ -72,7 +73,8 @@ extern Tuplesortstate *tuplesort_begin_index_hash(Relation indexRel,
 						   uint32 hash_mask,
 						   int workMem, bool randomAccess);
 extern Tuplesortstate *tuplesort_begin_datum(Oid datumType,
-					Oid sortOperator, Oid sortCollation, bool nullsFirstFlag,
+					  Oid sortOperator, Oid sortCollation,
+					  bool nullsFirstFlag,
 					  int workMem, bool randomAccess);
 
 extern void tuplesort_set_bound(Tuplesortstate *state, int64 bound);
@@ -125,6 +127,7 @@ extern void SelectSortFunction(Oid sortOperator, bool nulls_first,
  * reverse-sort and NULLs-ordering properly.
  */
 extern int32 ApplySortFunction(FmgrInfo *sortFunction, int sortFlags,
+				  Oid collation,
 				  Datum datum1, bool isNull1,
 				  Datum datum2, bool isNull2);
 
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 9f919b88c20546ed87600bc77b813c25f5724e94..535fea9257c22e5cc54dc956ebd59a6865340a55 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -348,7 +348,7 @@ do_compile(FunctionCallInfo fcinfo,
 	function->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
 	function->fn_tid = procTup->t_self;
 	function->fn_is_trigger = is_trigger;
-	function->fn_input_collation = fcinfo->flinfo->fn_collation;
+	function->fn_input_collation = fcinfo->fncollation;
 	function->fn_cxt = func_cxt;
 	function->out_param_varno = -1;		/* set up for no OUT param */
 	function->resolve_option = plpgsql_variable_conflict;
@@ -2331,7 +2331,7 @@ compute_function_hashkey(FunctionCallInfo fcinfo,
 	}
 
 	/* get input collation, if known */
-	hashkey->inputCollation = fcinfo->flinfo->fn_collation;
+	hashkey->inputCollation = fcinfo->fncollation;
 
 	if (procStruct->pronargs > 0)
 	{