Yulin PEI <ype...@connect.ust.hk> writes: > I found it could cause a crash when executing sql statement: `CREATE VIEW > v1(c1) AS (SELECT ('4' COLLATE "C")::INT FROM generate_series(1, 10)); ` in > postgres 13.2 release.
Nice catch. I don't think the code in DefineVirtualRelation is wrong: exprCollation shouldn't report any collation for an expression of a non-collatable type. Rather the problem is with an old kluge in coerce_type(), which will push a type coercion underneath a CollateExpr ... without any mind for the possibility that the coercion result isn't collatable. So the right fix is more or less the attached. regards, tom lane
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index d5310f27db..228ee8e7d6 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -95,6 +95,7 @@ coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, * *must* know that to avoid possibly calling hide_coercion_node on * something that wasn't generated by coerce_type. Note that if there are * multiple stacked CollateExprs, we just discard all but the topmost. + * Also, if the target type isn't collatable, we discard the CollateExpr. */ origexpr = expr; while (expr && IsA(expr, CollateExpr)) @@ -114,7 +115,7 @@ coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, ccontext, cformat, location, (result != expr && !IsA(result, Const))); - if (expr != origexpr) + if (expr != origexpr && type_is_collatable(targettype)) { /* Reinstall top CollateExpr */ CollateExpr *coll = (CollateExpr *) origexpr; @@ -384,7 +385,7 @@ coerce_type(ParseState *pstate, Node *node, if (result) return result; } - if (IsA(node, CollateExpr)) + if (IsA(node, CollateExpr) && type_is_collatable(targetTypeId)) { /* * If we have a COLLATE clause, we have to push the coercion