Skip to content
Snippets Groups Projects
Commit a19002d4 authored by Tom Lane's avatar Tom Lane
Browse files

Adjust collation determination rules as per discussion.

Remove crude hack that tried to propagate collation through a
function-returning-record, ie, from the function's arguments to individual
fields selected from its result record.  That is just plain inconsistent,
because the function result is composite and cannot have a collation;
and there's no hope of making this kind of action-at-a-distance work
consistently.  Adjust regression test cases that expected this to happen.

Meanwhile, the behavior of casting to a domain with a declared collation
stays the same as it was, since that seemed to be the consensus.
parent 7c76906b
Branches
Tags
No related merge requests found
...@@ -289,10 +289,11 @@ assign_collations_walker(Node *node, assign_collations_context *context) ...@@ -289,10 +289,11 @@ assign_collations_walker(Node *node, assign_collations_context *context)
case T_FieldSelect: case T_FieldSelect:
{ {
/* /*
* FieldSelect is a special case because the field may have * For FieldSelect, the result has the field's declared
* a non-default collation, in which case we should use that. * collation, independently of what happened in the arguments.
* The field's collation was already looked up and saved * (The immediate argument must be composite and thus not
* in the node. * collatable, anyhow.) The field's collation was already
* looked up and saved in the node.
*/ */
FieldSelect *expr = (FieldSelect *) node; FieldSelect *expr = (FieldSelect *) node;
...@@ -304,24 +305,6 @@ assign_collations_walker(Node *node, assign_collations_context *context) ...@@ -304,24 +305,6 @@ assign_collations_walker(Node *node, assign_collations_context *context)
if (OidIsValid(expr->resultcollid)) if (OidIsValid(expr->resultcollid))
{ {
/* Node's result type is collatable. */ /* Node's result type is collatable. */
if (expr->resultcollid == DEFAULT_COLLATION_OID)
{
/*
* The immediate input node necessarily yields a
* composite type, so it will have no exposed
* collation. However, if we are selecting a field
* from a function returning composite, see if we
* can bubble up a collation from the function's
* input. XXX this is a bit of a hack, rethink ...
*/
if (IsA(expr->arg, FuncExpr))
{
FuncExpr *fexpr = (FuncExpr *) expr->arg;
if (OidIsValid(fexpr->inputcollid))
expr->resultcollid = fexpr->inputcollid;
}
}
/* Pass up field's collation as an implicit choice. */ /* Pass up field's collation as an implicit choice. */
collation = expr->resultcollid; collation = expr->resultcollid;
strength = COLLATE_IMPLICIT; strength = COLLATE_IMPLICIT;
... ...
......
...@@ -1384,7 +1384,7 @@ ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg, ...@@ -1384,7 +1384,7 @@ ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg,
fselect->fieldnum = i + 1; fselect->fieldnum = i + 1;
fselect->resulttype = att->atttypid; fselect->resulttype = att->atttypid;
fselect->resulttypmod = att->atttypmod; fselect->resulttypmod = att->atttypmod;
/* resultcollid may get overridden by parse_collate.c */ /* save attribute's collation for parse_collate.c */
fselect->resultcollid = att->attcollation; fselect->resultcollid = att->attcollation;
return (Node *) fselect; return (Node *) fselect;
} }
... ...
......
...@@ -1290,7 +1290,7 @@ ExpandRowReference(ParseState *pstate, Node *expr, ...@@ -1290,7 +1290,7 @@ ExpandRowReference(ParseState *pstate, Node *expr,
fselect->fieldnum = i + 1; fselect->fieldnum = i + 1;
fselect->resulttype = att->atttypid; fselect->resulttype = att->atttypid;
fselect->resulttypmod = att->atttypmod; fselect->resulttypmod = att->atttypmod;
/* resultcollid may get overridden by parse_collate.c */ /* save attribute's collation for parse_collate.c */
fselect->resultcollid = att->attcollation; fselect->resultcollid = att->attcollation;
if (targetlist) if (targetlist)
... ...
......
...@@ -771,33 +771,33 @@ SELECT * FROM unnest((SELECT array_agg(b ORDER BY b) FROM collate_test3)) ORDER ...@@ -771,33 +771,33 @@ SELECT * FROM unnest((SELECT array_agg(b ORDER BY b) FROM collate_test3)) ORDER
äbc äbc
(4 rows) (4 rows)
CREATE FUNCTION dup (f1 anyelement, f2 out anyelement, f3 out anyarray) CREATE FUNCTION dup (anyelement) RETURNS anyelement
AS 'select $1, array[$1,$1]' LANGUAGE sql; AS 'select $1' LANGUAGE sql;
SELECT a, (dup(b)).* FROM collate_test1 ORDER BY 2; SELECT a, dup(b) FROM collate_test1 ORDER BY 2;
a | f2 | f3 a | dup
---+-----+----------- ---+-----
1 | abc | {abc,abc} 1 | abc
4 | ABC | {ABC,ABC} 4 | ABC
2 | äbc | {äbc,äbc} 2 | äbc
3 | bbc | {bbc,bbc} 3 | bbc
(4 rows) (4 rows)
SELECT a, (dup(b)).* FROM collate_test2 ORDER BY 2; SELECT a, dup(b) FROM collate_test2 ORDER BY 2;
a | f2 | f3 a | dup
---+-----+----------- ---+-----
1 | abc | {abc,abc} 1 | abc
4 | ABC | {ABC,ABC} 4 | ABC
3 | bbc | {bbc,bbc} 3 | bbc
2 | äbc | {äbc,äbc} 2 | äbc
(4 rows) (4 rows)
SELECT a, (dup(b)).* FROM collate_test3 ORDER BY 2; SELECT a, dup(b) FROM collate_test3 ORDER BY 2;
a | f2 | f3 a | dup
---+-----+----------- ---+-----
4 | ABC | {ABC,ABC} 4 | ABC
1 | abc | {abc,abc} 1 | abc
3 | bbc | {bbc,bbc} 3 | bbc
2 | äbc | {äbc,äbc} 2 | äbc
(4 rows) (4 rows)
-- indexes -- indexes
... ...
......
...@@ -502,24 +502,24 @@ SELECT * FROM unnest((SELECT array_agg(b ORDER BY b) FROM collate_test2)) ORDER ...@@ -502,24 +502,24 @@ SELECT * FROM unnest((SELECT array_agg(b ORDER BY b) FROM collate_test2)) ORDER
bbc bbc
(4 rows) (4 rows)
CREATE FUNCTION dup (f1 anyelement, f2 out anyelement, f3 out anyarray) CREATE FUNCTION dup (anyelement) RETURNS anyelement
AS 'select $1, array[$1,$1]' LANGUAGE sql; AS 'select $1' LANGUAGE sql;
SELECT a, (dup(b)).* FROM collate_test1 ORDER BY 2; SELECT a, dup(b) FROM collate_test1 ORDER BY 2;
a | f2 | f3 a | dup
---+-----+----------- ---+-----
4 | ABD | {ABD,ABD} 4 | ABD
2 | Abc | {Abc,Abc} 2 | Abc
1 | abc | {abc,abc} 1 | abc
3 | bbc | {bbc,bbc} 3 | bbc
(4 rows) (4 rows)
SELECT a, (dup(b)).* FROM collate_test2 ORDER BY 2; SELECT a, dup(b) FROM collate_test2 ORDER BY 2;
a | f2 | f3 a | dup
---+-----+----------- ---+-----
4 | ABD | {ABD,ABD} 4 | ABD
2 | Abc | {Abc,Abc} 2 | Abc
1 | abc | {abc,abc} 1 | abc
3 | bbc | {bbc,bbc} 3 | bbc
(4 rows) (4 rows)
-- indexes -- indexes
... ...
......
...@@ -242,12 +242,12 @@ SELECT * FROM unnest((SELECT array_agg(b ORDER BY b) FROM collate_test1)) ORDER ...@@ -242,12 +242,12 @@ SELECT * FROM unnest((SELECT array_agg(b ORDER BY b) FROM collate_test1)) ORDER
SELECT * FROM unnest((SELECT array_agg(b ORDER BY b) FROM collate_test2)) ORDER BY 1; SELECT * FROM unnest((SELECT array_agg(b ORDER BY b) FROM collate_test2)) ORDER BY 1;
SELECT * FROM unnest((SELECT array_agg(b ORDER BY b) FROM collate_test3)) ORDER BY 1; SELECT * FROM unnest((SELECT array_agg(b ORDER BY b) FROM collate_test3)) ORDER BY 1;
CREATE FUNCTION dup (f1 anyelement, f2 out anyelement, f3 out anyarray) CREATE FUNCTION dup (anyelement) RETURNS anyelement
AS 'select $1, array[$1,$1]' LANGUAGE sql; AS 'select $1' LANGUAGE sql;
SELECT a, (dup(b)).* FROM collate_test1 ORDER BY 2; SELECT a, dup(b) FROM collate_test1 ORDER BY 2;
SELECT a, (dup(b)).* FROM collate_test2 ORDER BY 2; SELECT a, dup(b) FROM collate_test2 ORDER BY 2;
SELECT a, (dup(b)).* FROM collate_test3 ORDER BY 2; SELECT a, dup(b) FROM collate_test3 ORDER BY 2;
-- indexes -- indexes
... ...
......
...@@ -168,11 +168,11 @@ SELECT a, CAST(b AS varchar) FROM collate_test2 ORDER BY 2; ...@@ -168,11 +168,11 @@ SELECT a, CAST(b AS varchar) FROM collate_test2 ORDER BY 2;
SELECT * FROM unnest((SELECT array_agg(b ORDER BY b) FROM collate_test1)) ORDER BY 1; SELECT * FROM unnest((SELECT array_agg(b ORDER BY b) FROM collate_test1)) ORDER BY 1;
SELECT * FROM unnest((SELECT array_agg(b ORDER BY b) FROM collate_test2)) ORDER BY 1; SELECT * FROM unnest((SELECT array_agg(b ORDER BY b) FROM collate_test2)) ORDER BY 1;
CREATE FUNCTION dup (f1 anyelement, f2 out anyelement, f3 out anyarray) CREATE FUNCTION dup (anyelement) RETURNS anyelement
AS 'select $1, array[$1,$1]' LANGUAGE sql; AS 'select $1' LANGUAGE sql;
SELECT a, (dup(b)).* FROM collate_test1 ORDER BY 2; SELECT a, dup(b) FROM collate_test1 ORDER BY 2;
SELECT a, (dup(b)).* FROM collate_test2 ORDER BY 2; SELECT a, dup(b) FROM collate_test2 ORDER BY 2;
-- indexes -- indexes
... ...
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment