Fix bug in support for collation attributes on older ICU versions
authorPeter Eisentraut <[email protected]>
Tue, 19 Mar 2019 08:37:46 +0000 (09:37 +0100)
committerPeter Eisentraut <[email protected]>
Tue, 19 Mar 2019 08:37:46 +0000 (09:37 +0100)
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)

src/backend/utils/adt/pg_locale.c
src/test/regress/expected/collate.icu.utf8.out
src/test/regress/sql/collate.icu.utf8.sql

index ec14bad4e34bfcc74c606cf9416d4b164a2b04a4..7fe10e284aa09b3ed16fdc0c7cd52ddfe9a0e418 100644 (file)
@@ -1623,8 +1623,8 @@ icu_set_collation_attributes(UCollator *collator, const char *loc)
        {
            char       *name;
            char       *value;
-           UColAttribute uattr = -1;
-           UColAttributeValue uvalue = -1;
+           UColAttribute uattr;
+           UColAttributeValue uvalue;
            UErrorCode  status;
 
            status = U_ZERO_ERROR;
@@ -1650,7 +1650,9 @@ icu_set_collation_attributes(UCollator *collator, const char *loc)
                uattr = UCOL_NORMALIZATION_MODE;
            else if (strcmp(name, "colnumeric") == 0)
                uattr = UCOL_NUMERIC_COLLATION;
-           /* ignore if unknown */
+           else
+               /* ignore if unknown */
+               continue;
 
            if (strcmp(value, "primary") == 0)
                uvalue = UCOL_PRIMARY;
@@ -1677,7 +1679,7 @@ icu_set_collation_attributes(UCollator *collator, const char *loc)
            else
                status = U_ILLEGAL_ARGUMENT_ERROR;
 
-           if (uattr != -1 && uvalue != -1)
+           if (status == U_ZERO_ERROR)
                ucol_setAttribute(collator, uattr, uvalue, &status);
 
            /*
index 4b94921cf889ba720417f47786bebc9e2197597c..b66193d1be23e3fee21cb9a0eb8166f3992acfff 100644 (file)
@@ -1101,6 +1101,7 @@ select textrange_en_us('A','Z') @> 'b'::text;
 drop type textrange_c;
 drop type textrange_en_us;
 -- test ICU collation customization
+-- test the attributes handled by icu_set_collation_attributes()
 CREATE COLLATION testcoll_ignore_accents (provider = icu, locale = '@colStrength=primary;colCaseLevel=yes');
 SELECT 'aaá' > 'AAA' COLLATE "und-x-icu", 'aaá' < 'AAA' COLLATE testcoll_ignore_accents;
  ?column? | ?column? 
@@ -1139,6 +1140,15 @@ SELECT 'A-21' > 'A-123' COLLATE "und-x-icu", 'A-21' < 'A-123' COLLATE testcoll_n
 
 CREATE COLLATION testcoll_error1 (provider = icu, locale = '@colNumeric=lower');
 ERROR:  could not open collator for locale "@colNumeric=lower": U_ILLEGAL_ARGUMENT_ERROR
+-- test that attributes not handled by icu_set_collation_attributes()
+-- (handled by ucol_open() directly) also work
+CREATE COLLATION testcoll_de_phonebook (provider = icu, locale = 'de@collation=phonebook');
+SELECT 'Goldmann' < 'Götz' COLLATE "de-x-icu", 'Goldmann' > 'Götz' COLLATE testcoll_de_phonebook;
+ ?column? | ?column? 
+----------+----------
+ t        | t
+(1 row)
+
 -- cleanup
 SET client_min_messages TO warning;
 DROP SCHEMA collate_tests CASCADE;
index 73fb1232a7da8c97d6e892346542a4429e2a57a5..68c2d69659365480d8f49462d556a4f61a0c8b2e 100644 (file)
@@ -427,6 +427,8 @@ drop type textrange_en_us;
 
 -- test ICU collation customization
 
+-- test the attributes handled by icu_set_collation_attributes()
+
 CREATE COLLATION testcoll_ignore_accents (provider = icu, locale = '@colStrength=primary;colCaseLevel=yes');
 SELECT 'aaá' > 'AAA' COLLATE "und-x-icu", 'aaá' < 'AAA' COLLATE testcoll_ignore_accents;
 
@@ -445,6 +447,11 @@ SELECT 'A-21' > 'A-123' COLLATE "und-x-icu", 'A-21' < 'A-123' COLLATE testcoll_n
 
 CREATE COLLATION testcoll_error1 (provider = icu, locale = '@colNumeric=lower');
 
+-- test that attributes not handled by icu_set_collation_attributes()
+-- (handled by ucol_open() directly) also work
+CREATE COLLATION testcoll_de_phonebook (provider = icu, locale = 'de@collation=phonebook');
+SELECT 'Goldmann' < 'Götz' COLLATE "de-x-icu", 'Goldmann' > 'Götz' COLLATE testcoll_de_phonebook;
+
 
 -- cleanup
 SET client_min_messages TO warning;