transformPartitionBoundValue(ParseState *pstate, Node *val,
							 const char *colName, Oid colType, int32 colTypmod,
							 Oid partCollation)
{
	Node	   *value;

	/* Transform raw parsetree */
	value = transformExpr(pstate, val, EXPR_KIND_PARTITION_BOUND);

	/*
	 * Check that the input expression's collation is compatible with one
	 * specified for the parent's partition key (partcollation).  Don't throw
	 * an error if it's the default collation which we'll replace with the
	 * parent's collation anyway.
	 */
	if (IsA(value, CollateExpr))
	{
		Oid			exprCollOid = exprCollation(value);

		/*
		 * Check we have a collation iff it is a collatable type.  The only
		 * expected failures here are (1) COLLATE applied to a noncollatable
		 * type, or (2) partition bound expression had an unresolved
		 * collation.  But we might as well code this to be a complete
		 * consistency check.
		 */
		if (type_is_collatable(colType))
		{
			if (!OidIsValid(exprCollOid))
				ereport(ERROR,
						(errcode(ERRCODE_INDETERMINATE_COLLATION),
						 errmsg("could not determine which collation to use for partition bound expression"),
						 errhint("Use the COLLATE clause to set the collation explicitly.")));
		}
		else
		{
			if (OidIsValid(exprCollOid))
				ereport(ERROR,
						(errcode(ERRCODE_DATATYPE_MISMATCH),
						 errmsg("collations are not supported by type %s",
								format_type_be(colType))));
		}

		if (OidIsValid(exprCollOid) &&
			exprCollOid != DEFAULT_COLLATION_OID &&
			exprCollOid != partCollation)
			ereport(ERROR,
					(errcode(ERRCODE_DATATYPE_MISMATCH),
					 errmsg("collation of partition bound value for column \"%s\" does not match partition key collation \"%s\"",
							colName, get_collation_name(partCollation)),
					 parser_errposition(pstate, exprLocation(value))));
	}

	/* Coerce to correct type */
	value = coerce_to_target_type(pstate,
								  value, exprType(value),
								  colType,
								  colTypmod,
								  COERCION_ASSIGNMENT,
								  COERCE_IMPLICIT_CAST,
								  -1);

	if (value == NULL)
		ereport(ERROR,
				(errcode(ERRCODE_DATATYPE_MISMATCH),
				 errmsg("specified value cannot be cast to type %s for column \"%s\"",
						format_type_be(colType), colName),
				 parser_errposition(pstate, exprLocation(val))));

	/* Simplify the expression, in case we had a coercion */
	if (!IsA(value, Const))
	{
		assign_expr_collations(pstate, value);
		value = (Node *) expression_planner((Expr *) value);
	}

	/*
	 * transformExpr() should have already rejected column references,
	 * subqueries, aggregates, window functions, and SRFs, based on the
	 * EXPR_KIND_ for a default expression.
	 */
	Assert(!contain_var_clause(value));

	/*
	 * Evaluate the expression, assigning the partition key's collation to the
	 * resulting Const expression.
	 */
	value = (Node *) evaluate_expr((Expr *) value, colType, colTypmod,
								   partCollation);
	if (!IsA(value, Const))
		elog(ERROR, "could not evaluate partition bound expression");

	return (Const *) value;
}
transformPartitionBoundValue(ParseState *pstate, Node *val,
							 const char *colName, Oid colType, int32 colTypmod,
							 Oid partCollation)
{
	Node	   *value;

	 
	value = transformExpr(pstate, val, EXPR_KIND_PARTITION_BOUND);

	 
	if (IsA(value, CollateExpr))
	{
		Oid			exprCollOid = exprCollation(value);

		 
		if (type_is_collatable(colType))
		{
			if (!OidIsValid(exprCollOid))
				ereport(ERROR,
						(errcode(ERRCODE_INDETERMINATE_COLLATION),
						 errmsg("could not determine which collation to use for partition bound expression"),
						 errhint("Use the COLLATE clause to set the collation explicitly.")));
		}
		else
		{
			if (OidIsValid(exprCollOid))
				ereport(ERROR,
						(errcode(ERRCODE_DATATYPE_MISMATCH),
						 errmsg("collations are not supported by type %s",
								format_type_be(colType))));
		}

		if (OidIsValid(exprCollOid) &&
			exprCollOid != DEFAULT_COLLATION_OID &&
			exprCollOid != partCollation)
			ereport(ERROR,
					(errcode(ERRCODE_DATATYPE_MISMATCH),
					 errmsg("collation of partition bound value for column \"%s\" does not match partition key collation \"%s\"",
							colName, get_collation_name(partCollation)),
					 parser_errposition(pstate, exprLocation(value))));
	}

	 
	value = coerce_to_target_type(pstate,
								  value, exprType(value),
								  colType,
								  colTypmod,
								  COERCION_ASSIGNMENT,
								  COERCE_IMPLICIT_CAST,
								  -1);

	if (value == NULL)
		ereport(ERROR,
				(errcode(ERRCODE_DATATYPE_MISMATCH),
				 errmsg("specified value cannot be cast to type %s for column \"%s\"",
						format_type_be(colType), colName),
				 parser_errposition(pstate, exprLocation(val))));

	 
	if (!IsA(value, Const))
	{
		assign_expr_collations(pstate, value);
		value = (Node *) expression_planner((Expr *) value);
	}

	 
	Assert(!contain_var_clause(value));

	 
	value = (Node *) evaluate_expr((Expr *) value, colType, colTypmod,
								   partCollation);
	if (!IsA(value, Const))
		elog(ERROR, "could not evaluate partition bound expression");

	return (Const *) value;
}