mirror of
https://github.com/postgres/postgres.git
synced 2025-05-06 19:59:18 +03:00
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.
This commit is contained in:
parent
7c76906b7e
commit
a19002d4e5
@ -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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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
|
|||||||
ä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
|
|||||||
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
|
|||||||
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;
|
|||||||
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user