Skip to content

Commit 1f050c0

Browse files
committed
Fix bug in support for collation attributes on older ICU versions
Unrecognized attribute names are supposed to be ignored. But the code would error out on an unrecognized attribute value even if it did not recognize the attribute name. So unrecognized attributes wouldn't really be ignored unless the value happened to be one that matched a recognized value. This would break some important cases where the attribute would be processed by ucol_open() directly. Fix that and add a test case. The restructured code should also avoid compiler warnings about initializing a UColAttribute value to -1, because the type might be an unsigned enum. (reported by Andres Freund)
1 parent 53680c1 commit 1f050c0

File tree

3 files changed

+23
-4
lines changed

3 files changed

+23
-4
lines changed

src/backend/utils/adt/pg_locale.c

+6-4
Original file line numberDiff line numberDiff line change
@@ -1623,8 +1623,8 @@ icu_set_collation_attributes(UCollator *collator, const char *loc)
16231623
{
16241624
char *name;
16251625
char *value;
1626-
UColAttribute uattr = -1;
1627-
UColAttributeValue uvalue = -1;
1626+
UColAttribute uattr;
1627+
UColAttributeValue uvalue;
16281628
UErrorCode status;
16291629

16301630
status = U_ZERO_ERROR;
@@ -1650,7 +1650,9 @@ icu_set_collation_attributes(UCollator *collator, const char *loc)
16501650
uattr = UCOL_NORMALIZATION_MODE;
16511651
else if (strcmp(name, "colnumeric") == 0)
16521652
uattr = UCOL_NUMERIC_COLLATION;
1653-
/* ignore if unknown */
1653+
else
1654+
/* ignore if unknown */
1655+
continue;
16541656

16551657
if (strcmp(value, "primary") == 0)
16561658
uvalue = UCOL_PRIMARY;
@@ -1677,7 +1679,7 @@ icu_set_collation_attributes(UCollator *collator, const char *loc)
16771679
else
16781680
status = U_ILLEGAL_ARGUMENT_ERROR;
16791681

1680-
if (uattr != -1 && uvalue != -1)
1682+
if (status == U_ZERO_ERROR)
16811683
ucol_setAttribute(collator, uattr, uvalue, &status);
16821684

16831685
/*

src/test/regress/expected/collate.icu.utf8.out

+10
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,7 @@ select textrange_en_us('A','Z') @> 'b'::text;
11011101
drop type textrange_c;
11021102
drop type textrange_en_us;
11031103
-- test ICU collation customization
1104+
-- test the attributes handled by icu_set_collation_attributes()
11041105
CREATE COLLATION testcoll_ignore_accents (provider = icu, locale = '@colStrength=primary;colCaseLevel=yes');
11051106
SELECT 'aaá' > 'AAA' COLLATE "und-x-icu", 'aaá' < 'AAA' COLLATE testcoll_ignore_accents;
11061107
?column? | ?column?
@@ -1139,6 +1140,15 @@ SELECT 'A-21' > 'A-123' COLLATE "und-x-icu", 'A-21' < 'A-123' COLLATE testcoll_n
11391140

11401141
CREATE COLLATION testcoll_error1 (provider = icu, locale = '@colNumeric=lower');
11411142
ERROR: could not open collator for locale "@colNumeric=lower": U_ILLEGAL_ARGUMENT_ERROR
1143+
-- test that attributes not handled by icu_set_collation_attributes()
1144+
-- (handled by ucol_open() directly) also work
1145+
CREATE COLLATION testcoll_de_phonebook (provider = icu, locale = 'de@collation=phonebook');
1146+
SELECT 'Goldmann' < 'Götz' COLLATE "de-x-icu", 'Goldmann' > 'Götz' COLLATE testcoll_de_phonebook;
1147+
?column? | ?column?
1148+
----------+----------
1149+
t | t
1150+
(1 row)
1151+
11421152
-- cleanup
11431153
SET client_min_messages TO warning;
11441154
DROP SCHEMA collate_tests CASCADE;

src/test/regress/sql/collate.icu.utf8.sql

+7
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,8 @@ drop type textrange_en_us;
427427

428428
-- test ICU collation customization
429429

430+
-- test the attributes handled by icu_set_collation_attributes()
431+
430432
CREATE COLLATION testcoll_ignore_accents (provider = icu, locale = '@colStrength=primary;colCaseLevel=yes');
431433
SELECT 'aaá' > 'AAA' COLLATE "und-x-icu", 'aaá' < 'AAA' COLLATE testcoll_ignore_accents;
432434

@@ -445,6 +447,11 @@ SELECT 'A-21' > 'A-123' COLLATE "und-x-icu", 'A-21' < 'A-123' COLLATE testcoll_n
445447

446448
CREATE COLLATION testcoll_error1 (provider = icu, locale = '@colNumeric=lower');
447449

450+
-- test that attributes not handled by icu_set_collation_attributes()
451+
-- (handled by ucol_open() directly) also work
452+
CREATE COLLATION testcoll_de_phonebook (provider = icu, locale = 'de@collation=phonebook');
453+
SELECT 'Goldmann' < 'Götz' COLLATE "de-x-icu", 'Goldmann' > 'Götz' COLLATE testcoll_de_phonebook;
454+
448455

449456
-- cleanup
450457
SET client_min_messages TO warning;

0 commit comments

Comments
 (0)