diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 596cd864017b3f0c5a2a9db3255eaeb8631ca82e..d7573b8ef50429be24eee8daf12cae5311f1c365 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -4337,10 +4337,12 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
 		{
 			Oid			baseTypeId;
 			int32		baseTypeMod;
+			Oid			baseTypeColl;
 
 			baseTypeMod = typmod;
 			baseTypeId = getBaseTypeAndTypmod(typeOid, &baseTypeMod);
-			defval = (Expr *) makeNullConst(baseTypeId, baseTypeMod);
+			baseTypeColl = get_typcollation(baseTypeId);
+			defval = (Expr *) makeNullConst(baseTypeId, baseTypeMod, baseTypeColl);
 			defval = (Expr *) coerce_to_target_type(NULL,
 													(Node *) defval,
 													baseTypeId,
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index e410818900d5c12f4ea76761eb238285ed58ec42..c153ca00dbf520a61220015b34bc64f3909c8e26 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -4653,7 +4653,7 @@ ExecInitExpr(Expr *node, PlanState *parent)
 						 * don't really care what type of NULL it is, so
 						 * always make an int4 NULL.
 						 */
-						e = (Expr *) makeNullConst(INT4OID, -1);
+						e = (Expr *) makeNullConst(INT4OID, -1, InvalidOid);
 					}
 					estate = ExecInitExpr(e, parent);
 					outlist = lappend(outlist, estate);
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index ce3b77b847ea58b2febd5f993fa4a2af4aa7fd54..70d126c521340418cc5714d9c3d30d83f13d6c84 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -1501,6 +1501,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
 					/* The type of the null we insert isn't important */
 					null_expr = (Expr *) makeConst(INT4OID,
 												   -1,
+												   InvalidOid,
 												   sizeof(int32),
 												   (Datum) 0,
 												   true,		/* isnull */
@@ -1562,6 +1563,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
 				/* The type of the null we insert isn't important */
 				null_expr = (Expr *) makeConst(INT4OID,
 											   -1,
+											   InvalidOid,
 											   sizeof(int32),
 											   (Datum) 0,
 											   true,	/* isnull */
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 41e597cfffb93adcc1431a2ae4edf5c15dcda4e8..4d2eccf81790561eb25938b663a5470e9a37db5c 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -271,6 +271,7 @@ makeFromExpr(List *fromlist, Node *quals)
 Const *
 makeConst(Oid consttype,
 		  int32 consttypmod,
+		  Oid constcollid,
 		  int constlen,
 		  Datum constvalue,
 		  bool constisnull,
@@ -280,7 +281,7 @@ makeConst(Oid consttype,
 
 	cnst->consttype = consttype;
 	cnst->consttypmod = consttypmod;
-	cnst->constcollid = get_typcollation(consttype);
+	cnst->constcollid = constcollid;
 	cnst->constlen = constlen;
 	cnst->constvalue = constvalue;
 	cnst->constisnull = constisnull;
@@ -298,7 +299,7 @@ makeConst(Oid consttype,
  * storage properties.
  */
 Const *
-makeNullConst(Oid consttype, int32 consttypmod)
+makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
 {
 	int16		typLen;
 	bool		typByVal;
@@ -306,6 +307,7 @@ makeNullConst(Oid consttype, int32 consttypmod)
 	get_typlenbyval(consttype, &typLen, &typByVal);
 	return makeConst(consttype,
 					 consttypmod,
+					 constcollid,
 					 (int) typLen,
 					 (Datum) 0,
 					 true,
@@ -320,7 +322,7 @@ Node *
 makeBoolConst(bool value, bool isnull)
 {
 	/* note that pg_type.h hardwires size of bool as 1 ... duplicate it */
-	return (Node *) makeConst(BOOLOID, -1, 1,
+	return (Node *) makeConst(BOOLOID, -1, InvalidOid, 1,
 							  BoolGetDatum(value), isnull, true);
 }
 
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 925155c64d4d0b100a860b08de093ae6e186b33c..ecae57bdbbf0c3f50949b143adbc139c91f6fc4d 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -19,6 +19,7 @@
 
 #include "access/skey.h"
 #include "catalog/pg_am.h"
+#include "catalog/pg_collation.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_opfamily.h"
 #include "catalog/pg_type.h"
@@ -3233,7 +3234,9 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opfamily, Datum rightop)
 
 	expr = make_opclause(opr1oid, BOOLOID, false,
 						 (Expr *) leftop,
-						 (Expr *) makeConst(datatype, -1, -1, opr1right,
+						 (Expr *) makeConst(datatype, -1,
+											InvalidOid,	/* not collatable */
+											-1, opr1right,
 											false, false),
 						 InvalidOid, InvalidOid);
 	result = list_make1(make_simple_restrictinfo(expr));
@@ -3249,7 +3252,9 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opfamily, Datum rightop)
 
 	expr = make_opclause(opr2oid, BOOLOID, false,
 						 (Expr *) leftop,
-						 (Expr *) makeConst(datatype, -1, -1, opr2right,
+						 (Expr *) makeConst(datatype, -1,
+											InvalidOid,	/* not collatable */
+											-1, opr2right,
 											false, false),
 						 InvalidOid, InvalidOid);
 	result = lappend(result, make_simple_restrictinfo(expr));
@@ -3288,8 +3293,38 @@ static Const *
 string_to_const(const char *str, Oid datatype)
 {
 	Datum		conval = string_to_datum(str, datatype);
+	Oid			collation;
+	int			constlen;
 
-	return makeConst(datatype, -1,
-					 ((datatype == NAMEOID) ? NAMEDATALEN : -1),
+	/*
+	 * We only need to support a few datatypes here, so hard-wire properties
+	 * instead of incurring the expense of catalog lookups.
+	 */
+	switch (datatype)
+	{
+		case TEXTOID:
+		case VARCHAROID:
+		case BPCHAROID:
+			collation = DEFAULT_COLLATION_OID;
+			constlen = -1;
+			break;
+
+		case NAMEOID:
+			collation = InvalidOid;
+			constlen = NAMEDATALEN;
+			break;
+
+		case BYTEAOID:
+			collation = InvalidOid;
+			constlen = -1;
+			break;
+
+		default:
+			elog(ERROR, "unexpected datatype in string_to_const: %u",
+				 datatype);
+			return NULL;
+	}
+
+	return makeConst(datatype, -1, collation, constlen,
 					 conval, false, false);
 }
diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c
index 39203703e61bc1ba36cb4a7a41769a3074c3804d..f2ddf2a8442215a6dc8b5b0bee133604ddaa1aad 100644
--- a/src/backend/optimizer/plan/planagg.c
+++ b/src/backend/optimizer/plan/planagg.c
@@ -429,7 +429,8 @@ build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo,
 
 	/* set up expressions for LIMIT 1 */
 	parse->limitOffset = NULL;
-	parse->limitCount = (Node *) makeConst(INT8OID, -1, sizeof(int64),
+	parse->limitCount = (Node *) makeConst(INT8OID, -1, InvalidOid,
+										   sizeof(int64),
 										   Int64GetDatum(1), false,
 										   FLOAT8PASSBYVAL);
 
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index 63447aa536eaa17caefc908aae1d0a0311c1683e..4ba8921528f405771ee544da1abceeb2fe236806 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -269,6 +269,7 @@ expand_targetlist(List *tlist, int command_type,
 					{
 						new_expr = (Node *) makeConst(atttype,
 													  -1,
+													  attcollation,
 													  att_tup->attlen,
 													  (Datum) 0,
 													  true,		/* isnull */
@@ -286,6 +287,7 @@ expand_targetlist(List *tlist, int command_type,
 						/* Insert NULL for dropped column */
 						new_expr = (Node *) makeConst(INT4OID,
 													  -1,
+													  InvalidOid,
 													  sizeof(int32),
 													  (Datum) 0,
 													  true,		/* isnull */
@@ -307,6 +309,7 @@ expand_targetlist(List *tlist, int command_type,
 						/* Insert NULL for dropped column */
 						new_expr = (Node *) makeConst(INT4OID,
 													  -1,
+													  InvalidOid,
 													  sizeof(int32),
 													  (Datum) 0,
 													  true,		/* isnull */
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 606e5fe60a5f4becda1835170360692bc2103394..e15a8620426319f3a6a640add1c668f85c480055 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -910,6 +910,7 @@ generate_setop_tlist(List *colTypes, int flag,
 		/* flag value is the given constant */
 		expr = (Node *) makeConst(INT4OID,
 								  -1,
+								  InvalidOid,
 								  sizeof(int4),
 								  Int32GetDatum(flag),
 								  false,
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 0fddbae60a364ba46ba719b90083fe4fdc4fb15f..1a63146e6f156256feeafb9487c4bab742a4ca30 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -101,7 +101,7 @@ static List *simplify_and_arguments(List *args,
 static Node *simplify_boolean_equality(Oid opno, List *args);
 static Expr *simplify_function(Oid funcid,
 				  Oid result_type, int32 result_typmod,
-				  Oid input_collid, List **args,
+				  Oid result_collid, Oid input_collid, List **args,
 				  bool has_named_args,
 				  bool allow_inline,
 				  eval_const_expressions_context *context);
@@ -114,19 +114,21 @@ static List *add_function_defaults(List *args, Oid result_type,
 static List *fetch_function_defaults(HeapTuple func_tuple);
 static void recheck_cast_function_args(List *args, Oid result_type,
 						   HeapTuple func_tuple);
-static Expr *evaluate_function(Oid funcid,
-				  Oid result_type, int32 result_typmod,
-				  Oid input_collid, List *args, HeapTuple func_tuple,
+static Expr *evaluate_function(Oid funcid, Oid result_type, int32 result_typmod,
+				  Oid result_collid, Oid input_collid, List *args,
+				  HeapTuple func_tuple,
 				  eval_const_expressions_context *context);
-static Expr *inline_function(Oid funcid, Oid result_type, Oid input_collid,
-				List *args, HeapTuple func_tuple,
+static Expr *inline_function(Oid funcid, Oid result_type, Oid result_collid,
+				Oid input_collid, List *args,
+				HeapTuple func_tuple,
 				eval_const_expressions_context *context);
 static Node *substitute_actual_parameters(Node *expr, int nargs, List *args,
 							 int *usecounts);
 static Node *substitute_actual_parameters_mutator(Node *node,
 							  substitute_actual_parameters_context *context);
 static void sql_inline_error_callback(void *arg);
-static Expr *evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod);
+static Expr *evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
+			  Oid result_collation);
 static Query *substitute_actual_srf_parameters(Query *expr,
 								 int nargs, List *args);
 static Node *substitute_actual_srf_parameters_mutator(Node *node,
@@ -2141,7 +2143,6 @@ eval_const_expressions_mutator(Node *node,
 					int16		typLen;
 					bool		typByVal;
 					Datum		pval;
-					Const	   *cnst;
 
 					Assert(prm->ptype == param->paramtype);
 					get_typlenbyval(param->paramtype, &typLen, &typByVal);
@@ -2149,14 +2150,13 @@ eval_const_expressions_mutator(Node *node,
 						pval = prm->value;
 					else
 						pval = datumCopy(prm->value, typByVal, typLen);
-					cnst = makeConst(param->paramtype,
-									 param->paramtypmod,
-									 (int) typLen,
-									 pval,
-									 prm->isnull,
-									 typByVal);
-					cnst->constcollid = param->paramcollid;
-					return (Node *) cnst;
+					return (Node *) makeConst(param->paramtype,
+											  param->paramtypmod,
+											  param->paramcollid,
+											  (int) typLen,
+											  pval,
+											  prm->isnull,
+											  typByVal);
 				}
 			}
 		}
@@ -2196,6 +2196,7 @@ eval_const_expressions_mutator(Node *node,
 		 */
 		simple = simplify_function(expr->funcid,
 								   expr->funcresulttype, exprTypmod(node),
+								   expr->funccollid,
 								   expr->inputcollid,
 								   &args,
 								   has_named_args, true, context);
@@ -2247,6 +2248,7 @@ eval_const_expressions_mutator(Node *node,
 		 */
 		simple = simplify_function(expr->opfuncid,
 								   expr->opresulttype, -1,
+								   expr->opcollid,
 								   expr->inputcollid,
 								   &args,
 								   false, true, context);
@@ -2343,6 +2345,7 @@ eval_const_expressions_mutator(Node *node,
 			 */
 			simple = simplify_function(expr->opfuncid,
 									   expr->opresulttype, -1,
+									   expr->opcollid,
 									   expr->inputcollid,
 									   &args,
 									   false, false, context);
@@ -2532,6 +2535,7 @@ eval_const_expressions_mutator(Node *node,
 		simple = simplify_function(outfunc,
 								   CSTRINGOID, -1,
 								   InvalidOid,
+								   InvalidOid,
 								   &args,
 								   false, true, context);
 		if (simple)				/* successfully simplified output fn */
@@ -2541,15 +2545,16 @@ eval_const_expressions_mutator(Node *node,
 			 * all three, trusting that nothing downstream will complain.
 			 */
 			args = list_make3(simple,
-							  makeConst(OIDOID, -1, sizeof(Oid),
+							  makeConst(OIDOID, -1, InvalidOid, sizeof(Oid),
 										ObjectIdGetDatum(intypioparam),
 										false, true),
-							  makeConst(INT4OID, -1, sizeof(int32),
+							  makeConst(INT4OID, -1, InvalidOid, sizeof(int32),
 										Int32GetDatum(-1),
 										false, true));
 
 			simple = simplify_function(infunc,
 									   expr->resulttype, -1,
+									   expr->resultcollid,
 									   InvalidOid,
 									   &args,
 									   false, true, context);
@@ -2602,7 +2607,8 @@ eval_const_expressions_mutator(Node *node,
 			 func_volatile(newexpr->elemfuncid) == PROVOLATILE_IMMUTABLE))
 			return (Node *) evaluate_expr((Expr *) newexpr,
 										  newexpr->resulttype,
-										  newexpr->resulttypmod);
+										  newexpr->resulttypmod,
+										  newexpr->resultcollid);
 
 		/* Else we must return the partially-simplified node */
 		return (Node *) newexpr;
@@ -2826,7 +2832,8 @@ eval_const_expressions_mutator(Node *node,
 		if (all_const)
 			return (Node *) evaluate_expr((Expr *) newarray,
 										  newarray->array_typeid,
-										  exprTypmod(node));
+										  exprTypmod(node),
+										  newarray->array_collid);
 
 		return (Node *) newarray;
 	}
@@ -2866,7 +2873,9 @@ eval_const_expressions_mutator(Node *node,
 
 		/* If all the arguments were constant null, the result is just null */
 		if (newargs == NIL)
-			return (Node *) makeNullConst(coalesceexpr->coalescetype, -1);
+			return (Node *) makeNullConst(coalesceexpr->coalescetype,
+										  -1,
+										  coalesceexpr->coalescecollid);
 
 		newcoalesce = makeNode(CoalesceExpr);
 		newcoalesce->coalescetype = coalesceexpr->coalescetype;
@@ -3380,7 +3389,8 @@ simplify_boolean_equality(Oid opno, List *args)
  * (which might originally have been an operator; we don't care)
  *
  * Inputs are the function OID, actual result type OID (which is needed for
- * polymorphic functions) and typmod, input collation to use for the function,
+ * polymorphic functions), result typmod, result collation,
+ * the input collation to use for the function,
  * the pre-simplified argument list, and some flags;
  * also the context data for eval_const_expressions.
  *
@@ -3395,8 +3405,7 @@ simplify_boolean_equality(Oid opno, List *args)
  */
 static Expr *
 simplify_function(Oid funcid, Oid result_type, int32 result_typmod,
-				  Oid input_collid,
-				  List **args,
+				  Oid result_collid, Oid input_collid, List **args,
 				  bool has_named_args,
 				  bool allow_inline,
 				  eval_const_expressions_context *context)
@@ -3427,11 +3436,12 @@ simplify_function(Oid funcid, Oid result_type, int32 result_typmod,
 		*args = add_function_defaults(*args, result_type, func_tuple, context);
 
 	newexpr = evaluate_function(funcid, result_type, result_typmod,
-								input_collid, *args,
+								result_collid, input_collid, *args,
 								func_tuple, context);
 
 	if (!newexpr && allow_inline)
-		newexpr = inline_function(funcid, result_type, input_collid, *args,
+		newexpr = inline_function(funcid, result_type, result_collid,
+								  input_collid, *args,
 								  func_tuple, context);
 
 	ReleaseSysCache(func_tuple);
@@ -3679,7 +3689,8 @@ recheck_cast_function_args(List *args, Oid result_type, HeapTuple func_tuple)
  */
 static Expr *
 evaluate_function(Oid funcid, Oid result_type, int32 result_typmod,
-				  Oid input_collid, List *args, HeapTuple func_tuple,
+				  Oid result_collid, Oid input_collid, List *args,
+				  HeapTuple func_tuple,
 				  eval_const_expressions_context *context)
 {
 	Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
@@ -3726,7 +3737,8 @@ evaluate_function(Oid funcid, Oid result_type, int32 result_typmod,
 	 * function is not otherwise immutable.
 	 */
 	if (funcform->proisstrict && has_null_input)
-		return (Expr *) makeNullConst(result_type, result_typmod);
+		return (Expr *) makeNullConst(result_type, result_typmod,
+									  result_collid);
 
 	/*
 	 * Otherwise, can simplify only if all inputs are constants. (For a
@@ -3760,12 +3772,13 @@ evaluate_function(Oid funcid, Oid result_type, int32 result_typmod,
 	newexpr->funcresulttype = result_type;
 	newexpr->funcretset = false;
 	newexpr->funcformat = COERCE_DONTCARE;		/* doesn't matter */
-	newexpr->funccollid = InvalidOid;			/* doesn't matter */
+	newexpr->funccollid = result_collid;		/* doesn't matter */
 	newexpr->inputcollid = input_collid;
 	newexpr->args = args;
 	newexpr->location = -1;
 
-	return evaluate_expr((Expr *) newexpr, result_type, result_typmod);
+	return evaluate_expr((Expr *) newexpr, result_type, result_typmod,
+						 result_collid);
 }
 
 /*
@@ -3798,7 +3811,8 @@ evaluate_function(Oid funcid, Oid result_type, int32 result_typmod,
  * simplify the function.
  */
 static Expr *
-inline_function(Oid funcid, Oid result_type, Oid input_collid, List *args,
+inline_function(Oid funcid, Oid result_type, Oid result_collid,
+				Oid input_collid, List *args,
 				HeapTuple func_tuple,
 				eval_const_expressions_context *context)
 {
@@ -3888,7 +3902,7 @@ inline_function(Oid funcid, Oid result_type, Oid input_collid, List *args,
 	fexpr->funcresulttype = result_type;
 	fexpr->funcretset = false;
 	fexpr->funcformat = COERCE_DONTCARE;		/* doesn't matter */
-	fexpr->funccollid = InvalidOid;				/* doesn't matter */
+	fexpr->funccollid = result_collid;			/* doesn't matter */
 	fexpr->inputcollid = input_collid;
 	fexpr->args = args;
 	fexpr->location = -1;
@@ -4051,16 +4065,16 @@ inline_function(Oid funcid, Oid result_type, Oid input_collid, List *args,
 	 * it's possible that the function result is used directly as a sort key
 	 * or in other places where we expect exprCollation() to tell the truth.
 	 */
-	if (OidIsValid(input_collid))
+	if (OidIsValid(result_collid))
 	{
 		Oid		exprcoll = exprCollation(newexpr);
 
-		if (OidIsValid(exprcoll) && exprcoll != input_collid)
+		if (OidIsValid(exprcoll) && exprcoll != result_collid)
 		{
 			CollateExpr   *newnode = makeNode(CollateExpr);
 
 			newnode->arg = (Expr *) newexpr;
-			newnode->collOid = input_collid;
+			newnode->collOid = result_collid;
 			newnode->location = -1;
 
 			newexpr = (Node *) newnode;
@@ -4165,7 +4179,8 @@ sql_inline_error_callback(void *arg)
  * code and ensure we get the same result as the executor would get.
  */
 static Expr *
-evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod)
+evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
+			  Oid result_collation)
 {
 	EState	   *estate;
 	ExprState  *exprstate;
@@ -4231,7 +4246,8 @@ evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod)
 	/*
 	 * Make the constant result node.
 	 */
-	return (Expr *) makeConst(result_type, result_typmod, resultTypLen,
+	return (Expr *) makeConst(result_type, result_typmod, result_collation,
+							  resultTypLen,
 							  const_val, const_is_null,
 							  resultTypByVal);
 }
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index 9b59b032976333138bcbeb6f308c90a34501adcd..cc03f9f48e605040759c85bc3c5ee7e57f58a9f6 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -753,6 +753,7 @@ build_coercion_expression(Node *node,
 			/* Pass target typmod as an int4 constant */
 			cons = makeConst(INT4OID,
 							 -1,
+							 InvalidOid,
 							 sizeof(int32),
 							 Int32GetDatum(targetTypMod),
 							 false,
@@ -766,6 +767,7 @@ build_coercion_expression(Node *node,
 			/* Pass it a boolean isExplicit parameter, too */
 			cons = makeConst(BOOLOID,
 							 -1,
+							 InvalidOid,
 							 sizeof(bool),
 							 BoolGetDatum(isExplicit),
 							 false,
@@ -890,7 +892,8 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
 			 * can't use atttypid here, but it doesn't really matter what type
 			 * the Const claims to be.
 			 */
-			newargs = lappend(newargs, makeNullConst(INT4OID, -1));
+			newargs = lappend(newargs,
+							  makeNullConst(INT4OID, -1, InvalidOid));
 			continue;
 		}
 
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index 2c76c557ecc741259326d787b6e17e137fdd4df7..07257accc828fe76dec18cfa39ea438a45f2ce64 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -347,6 +347,7 @@ transformArraySubscripts(ParseState *pstate,
 				/* Make a constant 1 */
 				subexpr = (Node *) makeConst(INT4OID,
 											 -1,
+											 InvalidOid,
 											 sizeof(int32),
 											 Int32GetDatum(1),
 											 false,
@@ -526,6 +527,7 @@ make_const(ParseState *pstate, Value *value, int location)
 			/* return a null const */
 			con = makeConst(UNKNOWNOID,
 							-1,
+							InvalidOid,
 							-2,
 							(Datum) 0,
 							true,
@@ -540,6 +542,7 @@ make_const(ParseState *pstate, Value *value, int location)
 
 	con = makeConst(typeid,
 					-1,			/* typmod -1 is OK for all cases */
+					InvalidOid,	/* all cases are uncollatable types */
 					typelen,
 					val,
 					false,
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 488b1425a35db1d002fa0f87a7a0be4988a0bd17..7bfafdb5cfb2f2648f54bb353a2233e84bcbca8c 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -1870,7 +1870,8 @@ expandTupleDesc(TupleDesc tupdesc, Alias *eref,
 					 * can't use atttypid here, but it doesn't really matter
 					 * what type the Const claims to be.
 					 */
-					*colvars = lappend(*colvars, makeNullConst(INT4OID, -1));
+					*colvars = lappend(*colvars,
+									   makeNullConst(INT4OID, -1, InvalidOid));
 				}
 			}
 			continue;
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 550783547e8927251d882d80e3dc49108a85f713..8e92b99b5b20a5b841c062846a9c80341e24f31c 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -434,7 +434,8 @@ transformAssignedExpr(ParseState *pstate,
 			 * is not really a source value to work with. Insert a NULL
 			 * constant as the source value.
 			 */
-			colVar = (Node *) makeNullConst(attrtype, attrtypmod);
+			colVar = (Node *) makeNullConst(attrtype, attrtypmod,
+											attrcollation);
 		}
 		else
 		{
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 87d39174a4486f2d0ba3eae6004d03b27c99ae36..a695b01239952bfa57b92b07ca6f50a7a9e5c7ab 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -208,7 +208,7 @@ AcquireRewriteLocks(Query *parsetree, bool forUpdatePushedDown)
 							 * now-dropped type OID, but it doesn't really
 							 * matter what type the Const claims to be.
 							 */
-							aliasvar = (Var *) makeNullConst(INT4OID, -1);
+							aliasvar = (Var *) makeNullConst(INT4OID, -1, InvalidOid);
 						}
 					}
 					newaliasvars = lappend(newaliasvars, aliasvar);
@@ -719,6 +719,7 @@ rewriteTargetListIU(Query *parsetree, Relation target_relation,
 				{
 					new_expr = (Node *) makeConst(att_tup->atttypid,
 												  -1,
+												  att_tup->attcollation,
 												  att_tup->attlen,
 												  (Datum) 0,
 												  true, /* isnull */
@@ -1082,6 +1083,7 @@ rewriteValuesRTE(RangeTblEntry *rte, Relation target_relation, List *attrnos)
 				{
 					new_expr = (Node *) makeConst(att_tup->atttypid,
 												  -1,
+												  att_tup->attcollation,
 												  att_tup->attlen,
 												  (Datum) 0,
 												  true, /* isnull */
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c
index 49a6df0e80747f8cd74fdfac1a314d1f08bd5d9a..d3985b2093e9cdbbeeb763ab8f5023fabf7b923b 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -1281,7 +1281,8 @@ ResolveNew_callback(Var *var,
 			/* Otherwise replace unmatched var with a null */
 			/* need coerce_to_domain in case of NOT NULL domain constraint */
 			return coerce_to_domain((Node *) makeNullConst(var->vartype,
-														   var->vartypmod),
+														   var->vartypmod,
+														   var->varcollid),
 									InvalidOid, -1,
 									var->vartype,
 									COERCE_IMPLICIT_CAST,
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 33f300bfea214ea3b5d78e98079cbf760f8da18e..c757fcb424f41df99abb9fbebed596d645c81827 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -1686,6 +1686,7 @@ scalararraysel(PlannerInfo *root,
 	Node	   *leftop;
 	Node	   *rightop;
 	Oid			nominal_element_type;
+	Oid			nominal_element_collation;
 	RegProcedure oprsel;
 	FmgrInfo	oprselproc;
 	Selectivity s1;
@@ -1712,6 +1713,8 @@ scalararraysel(PlannerInfo *root,
 	nominal_element_type = get_base_element_type(exprType(rightop));
 	if (!OidIsValid(nominal_element_type))
 		return (Selectivity) 0.5;		/* probably shouldn't happen */
+	/* get nominal collation, too, for generating constants */
+	nominal_element_collation = exprCollation(rightop);
 
 	/* look through any binary-compatible relabeling of rightop */
 	rightop = strip_array_coercion(rightop);
@@ -1759,6 +1762,7 @@ scalararraysel(PlannerInfo *root,
 			args = list_make2(leftop,
 							  makeConst(nominal_element_type,
 										-1,
+										nominal_element_collation,
 										elmlen,
 										elem_values[i],
 										elem_nulls[i],
@@ -5616,9 +5620,39 @@ static Const *
 string_to_const(const char *str, Oid datatype)
 {
 	Datum		conval = string_to_datum(str, datatype);
+	Oid			collation;
+	int			constlen;
 
-	return makeConst(datatype, -1,
-					 ((datatype == NAMEOID) ? NAMEDATALEN : -1),
+	/*
+	 * We only need to support a few datatypes here, so hard-wire properties
+	 * instead of incurring the expense of catalog lookups.
+	 */
+	switch (datatype)
+	{
+		case TEXTOID:
+		case VARCHAROID:
+		case BPCHAROID:
+			collation = DEFAULT_COLLATION_OID;
+			constlen = -1;
+			break;
+
+		case NAMEOID:
+			collation = InvalidOid;
+			constlen = NAMEDATALEN;
+			break;
+
+		case BYTEAOID:
+			collation = InvalidOid;
+			constlen = -1;
+			break;
+
+		default:
+			elog(ERROR, "unexpected datatype in string_to_const: %u",
+				 datatype);
+			return NULL;
+	}
+
+	return makeConst(datatype, -1, collation, constlen,
 					 conval, false, false);
 }
 
@@ -5635,7 +5669,7 @@ string_to_bytea_const(const char *str, size_t str_len)
 	SET_VARSIZE(bstr, VARHDRSZ + str_len);
 	conval = PointerGetDatum(bstr);
 
-	return makeConst(BYTEAOID, -1, -1, conval, false, false);
+	return makeConst(BYTEAOID, -1, InvalidOid, -1, conval, false, false);
 }
 
 /*-------------------------------------------------------------------------
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 6af23429ad8aaa75cbdec760943e02a475226ce6..6bcaf30ffe71e590e6f2879e6824f1416174e52b 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -2084,6 +2084,7 @@ get_typdefault(Oid typid)
 			/* Build a Const node containing the value */
 			expr = (Node *) makeConst(typid,
 									  -1,
+									  type->typcollation,
 									  type->typlen,
 									  datum,
 									  false,
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index ead7c403ccecf773e6a95c6de87a42a4ac3e943a..152cb0de2b90b9efd3e610e2b90e8be53e09aa4b 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -48,12 +48,13 @@ extern FromExpr *makeFromExpr(List *fromlist, Node *quals);
 
 extern Const *makeConst(Oid consttype,
 		  int32 consttypmod,
+		  Oid constcollid,
 		  int constlen,
 		  Datum constvalue,
 		  bool constisnull,
 		  bool constbyval);
 
-extern Const *makeNullConst(Oid consttype, int32 consttypmod);
+extern Const *makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid);
 
 extern Node *makeBoolConst(bool value, bool isnull);