From 2d59643dbccaf73bc1f90875ea02dcad641379cd Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 14 Apr 2020 17:30:13 -0400 Subject: [PATCH] Account for collation when coercing the output of a SQL function. Commit 913bbd88d overlooked that the result of coerce_to_target_type might need collation fixups. Per report from Andreas Joseph Krogh. Discussion: https://postgr.es/m/VisenaEmail.72.37d08ec2b8cb8fb5.17179940cd3@tc7-visena --- src/backend/executor/functions.c | 3 +++ src/test/regress/expected/collate.out | 15 ++++++++++++++- src/test/regress/sql/collate.sql | 8 ++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 1c387a952e3..f940f48c6da 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -24,6 +24,7 @@ #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "parser/parse_coerce.h" +#include "parser/parse_collate.h" #include "parser/parse_func.h" #include "storage/proc.h" #include "tcop/utility.h" @@ -1989,6 +1990,7 @@ coerce_fn_result_column(TargetEntry *src_tle, -1); if (cast_result == NULL) return false; + assign_expr_collations(NULL, cast_result); src_tle->expr = (Expr *) cast_result; /* Make a Var referencing the possibly-modified TLE */ new_tle_expr = (Expr *) makeVarFromTargetEntry(1, src_tle); @@ -2007,6 +2009,7 @@ coerce_fn_result_column(TargetEntry *src_tle, -1); if (cast_result == NULL) return false; + assign_expr_collations(NULL, cast_result); /* Did the coercion actually do anything? */ if (cast_result != (Node *) var) *upper_tlist_nontrivial = true; diff --git a/src/test/regress/expected/collate.out b/src/test/regress/expected/collate.out index 0dee7d783a0..c42ab8f7037 100644 --- a/src/test/regress/expected/collate.out +++ b/src/test/regress/expected/collate.out @@ -536,6 +536,18 @@ SELECT a, CAST(b AS varchar) FROM collate_test2 ORDER BY 2; 3 | bbc (4 rows) +-- result of a SQL function +CREATE FUNCTION vc (text) RETURNS text LANGUAGE sql + AS 'select $1::varchar'; +SELECT a, b FROM collate_test1 ORDER BY a, vc(b); + a | b +---+----- + 1 | abc + 2 | Abc + 3 | bbc + 4 | ABD +(4 rows) + -- polymorphism SELECT * FROM unnest((SELECT array_agg(b ORDER BY b) FROM collate_test1)) ORDER BY 1; unnest @@ -682,7 +694,7 @@ SELECT collation for ((SELECT b FROM collate_test1 LIMIT 1)); -- must get rid of them. -- DROP SCHEMA collate_tests CASCADE; -NOTICE: drop cascades to 17 other objects +NOTICE: drop cascades to 18 other objects DETAIL: drop cascades to table collate_test1 drop cascades to table collate_test_like drop cascades to table collate_test2 @@ -694,6 +706,7 @@ drop cascades to view collview1 drop cascades to view collview2 drop cascades to view collview3 drop cascades to type testdomain +drop cascades to function vc(text) drop cascades to function dup(anyelement) drop cascades to table collate_test20 drop cascades to table collate_test21 diff --git a/src/test/regress/sql/collate.sql b/src/test/regress/sql/collate.sql index 89de26a227e..82f9c855b88 100644 --- a/src/test/regress/sql/collate.sql +++ b/src/test/regress/sql/collate.sql @@ -177,6 +177,14 @@ SELECT a, CAST(b AS varchar) FROM collate_test1 ORDER BY 2; SELECT a, CAST(b AS varchar) FROM collate_test2 ORDER BY 2; +-- result of a SQL function + +CREATE FUNCTION vc (text) RETURNS text LANGUAGE sql + AS 'select $1::varchar'; + +SELECT a, b FROM collate_test1 ORDER BY a, vc(b); + + -- polymorphism SELECT * FROM unnest((SELECT array_agg(b ORDER BY b) FROM collate_test1)) ORDER BY 1;