Skip to content

Commit 2dfa3fe

Browse files
committed
Remove complaints about COLLATE clauses in partition bound values.
transformPartitionBoundValue went out of its way to do the wrong thing: there is no reason to complain about a non-matching COLLATE clause in a partition boundary expression. We're coercing the bound expression to the target column type as though by an implicit assignment, and the rules for implicit assignment say that collations can be implicitly converted. What we *do* need to do, and the code is not doing, is apply assign_expr_collations() to the bound expression. While this is merely a definition disagreement, that is a bug that needs to be back-patched, so I'll commit it separately. Discussion: https://postgr.es/m/CAJV4CdrZ5mKuaEsRSbLf2URQ3h6iMtKD=hik8MaF5WwdmC9uZw@mail.gmail.com
1 parent 0a87ddf commit 2dfa3fe

File tree

3 files changed

+21
-73
lines changed

3 files changed

+21
-73
lines changed

src/backend/parser/parse_utilcmd.c

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4183,50 +4183,6 @@ transformPartitionBoundValue(ParseState *pstate, Node *val,
41834183
*/
41844184
Assert(!contain_var_clause(value));
41854185

4186-
/*
4187-
* Check that the input expression's collation is compatible with one
4188-
* specified for the parent's partition key (partcollation). Don't throw
4189-
* an error if it's the default collation which we'll replace with the
4190-
* parent's collation anyway.
4191-
*/
4192-
if (IsA(value, CollateExpr))
4193-
{
4194-
Oid exprCollOid = exprCollation(value);
4195-
4196-
/*
4197-
* Check we have a collation iff it is a collatable type. The only
4198-
* expected failures here are (1) COLLATE applied to a noncollatable
4199-
* type, or (2) partition bound expression had an unresolved
4200-
* collation. But we might as well code this to be a complete
4201-
* consistency check.
4202-
*/
4203-
if (type_is_collatable(colType))
4204-
{
4205-
if (!OidIsValid(exprCollOid))
4206-
ereport(ERROR,
4207-
(errcode(ERRCODE_INDETERMINATE_COLLATION),
4208-
errmsg("could not determine which collation to use for partition bound expression"),
4209-
errhint("Use the COLLATE clause to set the collation explicitly.")));
4210-
}
4211-
else
4212-
{
4213-
if (OidIsValid(exprCollOid))
4214-
ereport(ERROR,
4215-
(errcode(ERRCODE_DATATYPE_MISMATCH),
4216-
errmsg("collations are not supported by type %s",
4217-
format_type_be(colType))));
4218-
}
4219-
4220-
if (OidIsValid(exprCollOid) &&
4221-
exprCollOid != DEFAULT_COLLATION_OID &&
4222-
exprCollOid != partCollation)
4223-
ereport(ERROR,
4224-
(errcode(ERRCODE_DATATYPE_MISMATCH),
4225-
errmsg("collation of partition bound value for column \"%s\" does not match partition key collation \"%s\"",
4226-
colName, get_collation_name(partCollation)),
4227-
parser_errposition(pstate, exprLocation(value))));
4228-
}
4229-
42304186
/*
42314187
* Coerce to the correct type. This might cause an explicit coercion step
42324188
* to be added on top of the expression, which must be evaluated before

src/test/regress/expected/create_table.out

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -652,8 +652,6 @@ CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (genera
652652
ERROR: set-returning functions are not allowed in partition bound
653653
LINE 1: ...expr_fail PARTITION OF list_parted FOR VALUES IN (generate_s...
654654
^
655-
CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN ('1' collate "POSIX");
656-
ERROR: collations are not supported by type integer
657655
CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN ((1+1) collate "POSIX");
658656
ERROR: collations are not supported by type integer
659657
LINE 1: ...ail PARTITION OF list_parted FOR VALUES IN ((1+1) collate "P...
@@ -1026,28 +1024,28 @@ create table parted_collate_must_match1 partition of parted_collate_must_match
10261024
create table parted_collate_must_match2 partition of parted_collate_must_match
10271025
(b collate "POSIX") for values from ('m') to ('z');
10281026
drop table parted_collate_must_match;
1029-
-- check that specifying incompatible collations for partition bound
1030-
-- expressions fails promptly
1027+
-- check that non-matching collations for partition bound
1028+
-- expressions are coerced to the right collation
10311029
create table test_part_coll_posix (a text) partition by range (a collate "POSIX");
1032-
-- fail
1030+
-- ok, collation is implicitly coerced
10331031
create table test_part_coll partition of test_part_coll_posix for values from ('a' collate "C") to ('g');
1034-
ERROR: collation of partition bound value for column "a" does not match partition key collation "POSIX"
1035-
LINE 1: ...artition of test_part_coll_posix for values from ('a' collat...
1036-
^
1037-
-- ok
1038-
create table test_part_coll partition of test_part_coll_posix for values from ('a' collate "POSIX") to ('g');
10391032
-- ok
10401033
create table test_part_coll2 partition of test_part_coll_posix for values from ('g') to ('m');
1041-
-- using a cast expression uses the target type's default collation
1042-
-- fail
1034+
-- ok, collation is implicitly coerced
10431035
create table test_part_coll_cast partition of test_part_coll_posix for values from (name 'm' collate "C") to ('s');
1044-
ERROR: collation of partition bound value for column "a" does not match partition key collation "POSIX"
1045-
LINE 1: ...ion of test_part_coll_posix for values from (name 'm' collat...
1046-
^
1047-
-- ok
1048-
create table test_part_coll_cast partition of test_part_coll_posix for values from (name 'm' collate "POSIX") to ('s');
10491036
-- ok; partition collation silently overrides the default collation of type 'name'
10501037
create table test_part_coll_cast2 partition of test_part_coll_posix for values from (name 's') to ('z');
1038+
\d+ test_part_coll_posix
1039+
Partitioned table "public.test_part_coll_posix"
1040+
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
1041+
--------+------+-----------+----------+---------+----------+--------------+-------------
1042+
a | text | | | | extended | |
1043+
Partition key: RANGE (a COLLATE "POSIX")
1044+
Partitions: test_part_coll FOR VALUES FROM ('a') TO ('g'),
1045+
test_part_coll2 FOR VALUES FROM ('g') TO ('m'),
1046+
test_part_coll_cast FOR VALUES FROM ('m') TO ('s'),
1047+
test_part_coll_cast2 FOR VALUES FROM ('s') TO ('z')
1048+
10511049
drop table test_part_coll_posix;
10521050
-- Partition bound in describe output
10531051
\d+ part_b

src/test/regress/sql/create_table.sql

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,6 @@ CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (sum(so
549549
CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (sum(1));
550550
CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN ((select 1));
551551
CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN (generate_series(4, 6));
552-
CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN ('1' collate "POSIX");
553552
CREATE TABLE part_bogus_expr_fail PARTITION OF list_parted FOR VALUES IN ((1+1) collate "POSIX");
554553

555554
-- syntax does not allow empty list of values for list partitions
@@ -813,26 +812,21 @@ create table parted_collate_must_match2 partition of parted_collate_must_match
813812
(b collate "POSIX") for values from ('m') to ('z');
814813
drop table parted_collate_must_match;
815814

816-
-- check that specifying incompatible collations for partition bound
817-
-- expressions fails promptly
815+
-- check that non-matching collations for partition bound
816+
-- expressions are coerced to the right collation
818817

819818
create table test_part_coll_posix (a text) partition by range (a collate "POSIX");
820-
-- fail
819+
-- ok, collation is implicitly coerced
821820
create table test_part_coll partition of test_part_coll_posix for values from ('a' collate "C") to ('g');
822821
-- ok
823-
create table test_part_coll partition of test_part_coll_posix for values from ('a' collate "POSIX") to ('g');
824-
-- ok
825822
create table test_part_coll2 partition of test_part_coll_posix for values from ('g') to ('m');
826-
827-
-- using a cast expression uses the target type's default collation
828-
829-
-- fail
823+
-- ok, collation is implicitly coerced
830824
create table test_part_coll_cast partition of test_part_coll_posix for values from (name 'm' collate "C") to ('s');
831-
-- ok
832-
create table test_part_coll_cast partition of test_part_coll_posix for values from (name 'm' collate "POSIX") to ('s');
833825
-- ok; partition collation silently overrides the default collation of type 'name'
834826
create table test_part_coll_cast2 partition of test_part_coll_posix for values from (name 's') to ('z');
835827

828+
\d+ test_part_coll_posix
829+
836830
drop table test_part_coll_posix;
837831

838832
-- Partition bound in describe output

0 commit comments

Comments
 (0)