aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/parser/parse_coerce.c29
-rw-r--r--src/test/regress/expected/collate.out16
-rw-r--r--src/test/regress/sql/collate.sql6
3 files changed, 39 insertions, 12 deletions
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index d5310f27db1..aa4a21126d3 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;
@@ -388,20 +389,26 @@ coerce_type(ParseState *pstate, Node *node,
{
/*
* If we have a COLLATE clause, we have to push the coercion
- * underneath the COLLATE. This is really ugly, but there is little
- * choice because the above hacks on Consts and Params wouldn't happen
+ * underneath the COLLATE; or discard the COLLATE if the target type
+ * isn't collatable. This is really ugly, but there is little choice
+ * because the above hacks on Consts and Params wouldn't happen
* otherwise. This kluge has consequences in coerce_to_target_type.
*/
CollateExpr *coll = (CollateExpr *) node;
- CollateExpr *newcoll = makeNode(CollateExpr);
- newcoll->arg = (Expr *)
- coerce_type(pstate, (Node *) coll->arg,
- inputTypeId, targetTypeId, targetTypeMod,
- ccontext, cformat, location);
- newcoll->collOid = coll->collOid;
- newcoll->location = coll->location;
- return (Node *) newcoll;
+ result = coerce_type(pstate, (Node *) coll->arg,
+ inputTypeId, targetTypeId, targetTypeMod,
+ ccontext, cformat, location);
+ if (type_is_collatable(targetTypeId))
+ {
+ CollateExpr *newcoll = makeNode(CollateExpr);
+
+ newcoll->arg = (Expr *) result;
+ newcoll->collOid = coll->collOid;
+ newcoll->location = coll->location;
+ result = (Node *) newcoll;
+ }
+ return result;
}
pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
&funcId);
diff --git a/src/test/regress/expected/collate.out b/src/test/regress/expected/collate.out
index c42ab8f7037..0b60b555147 100644
--- a/src/test/regress/expected/collate.out
+++ b/src/test/regress/expected/collate.out
@@ -688,13 +688,26 @@ SELECT collation for ((SELECT b FROM collate_test1 LIMIT 1));
"C"
(1 row)
+-- old bug with not dropping COLLATE when coercing to non-collatable type
+CREATE VIEW collate_on_int AS
+SELECT c1+1 AS c1p FROM
+ (SELECT ('4' COLLATE "C")::INT AS c1) ss;
+\d+ collate_on_int
+ View "collate_tests.collate_on_int"
+ Column | Type | Collation | Nullable | Default | Storage | Description
+--------+---------+-----------+----------+---------+---------+-------------
+ c1p | integer | | | | plain |
+View definition:
+ SELECT ss.c1 + 1 AS c1p
+ FROM ( SELECT 4 AS c1) ss;
+
--
-- Clean up. Many of these table names will be re-used if the user is
-- trying to run any platform-specific collation tests later, so we
-- must get rid of them.
--
DROP SCHEMA collate_tests CASCADE;
-NOTICE: drop cascades to 18 other objects
+NOTICE: drop cascades to 19 other objects
DETAIL: drop cascades to table collate_test1
drop cascades to table collate_test_like
drop cascades to table collate_test2
@@ -713,3 +726,4 @@ drop cascades to table collate_test21
drop cascades to table collate_test22
drop cascades to collation mycoll2
drop cascades to table collate_test23
+drop cascades to view collate_on_int
diff --git a/src/test/regress/sql/collate.sql b/src/test/regress/sql/collate.sql
index 82f9c855b88..30f811ba896 100644
--- a/src/test/regress/sql/collate.sql
+++ b/src/test/regress/sql/collate.sql
@@ -266,6 +266,12 @@ SELECT collation for ('foo'::text);
SELECT collation for ((SELECT a FROM collate_test1 LIMIT 1)); -- non-collatable type - error
SELECT collation for ((SELECT b FROM collate_test1 LIMIT 1));
+-- old bug with not dropping COLLATE when coercing to non-collatable type
+CREATE VIEW collate_on_int AS
+SELECT c1+1 AS c1p FROM
+ (SELECT ('4' COLLATE "C")::INT AS c1) ss;
+\d+ collate_on_int
+
--
-- Clean up. Many of these table names will be re-used if the user is