Commit a19002d4 authored by Tom Lane's avatar Tom Lane

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
...@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment