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);