Skip to content

Commit 8b3eb0c

Browse files
committed
Fix error inconsistency in older ICU versions.
To support older ICU versions, we rely on icu_set_collation_attributes() to do error checking that is handled directly by ucol_open() in newer ICU versions. Commit 3b50275 introduced a slight inconsistency, where the error report includes the fixed-up locale string, rather than the locale string passed to pg_ucol_open(). Refactor slightly so that pg_ucol_open() handles the errors from both ucol_open() and icu_set_collation_attributes(), making it easier to see any differences between the error reports. It also makes pg_ucol_open() responsible for closing the UCollator on error, which seems like the right place. Discussion: https://postgr.es/m/04182066-7655-344a-b8b7-040b1b2490fb%40enterprisedb.com Reviewed-by: Peter Eisentraut
1 parent 90189ee commit 8b3eb0c

File tree

1 file changed

+34
-28
lines changed

1 file changed

+34
-28
lines changed

src/backend/utils/adt/pg_locale.c

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ static size_t uchar_length(UConverter *converter,
147147
static int32_t uchar_convert(UConverter *converter,
148148
UChar *dest, int32_t destlen,
149149
const char *str, int32_t srclen);
150-
static void icu_set_collation_attributes(UCollator *collator, const char *loc);
150+
static void icu_set_collation_attributes(UCollator *collator, const char *loc,
151+
UErrorCode *status);
151152
#endif
152153

153154
/*
@@ -2496,6 +2497,7 @@ pg_ucol_open(const char *loc_str)
24962497
{
24972498
UCollator *collator;
24982499
UErrorCode status;
2500+
const char *orig_str = loc_str;
24992501
char *fixed_str = NULL;
25002502

25012503
/*
@@ -2544,11 +2546,27 @@ pg_ucol_open(const char *loc_str)
25442546
collator = ucol_open(loc_str, &status);
25452547
if (U_FAILURE(status))
25462548
ereport(ERROR,
2549+
/* use original string for error report */
25472550
(errmsg("could not open collator for locale \"%s\": %s",
2548-
loc_str, u_errorName(status))));
2551+
orig_str, u_errorName(status))));
25492552

25502553
if (U_ICU_VERSION_MAJOR_NUM < 54)
2551-
icu_set_collation_attributes(collator, loc_str);
2554+
{
2555+
status = U_ZERO_ERROR;
2556+
icu_set_collation_attributes(collator, loc_str, &status);
2557+
2558+
/*
2559+
* Pretend the error came from ucol_open(), for consistent error
2560+
* message across ICU versions.
2561+
*/
2562+
if (U_FAILURE(status))
2563+
{
2564+
ucol_close(collator);
2565+
ereport(ERROR,
2566+
(errmsg("could not open collator for locale \"%s\": %s",
2567+
orig_str, u_errorName(status))));
2568+
}
2569+
}
25522570

25532571
if (fixed_str != NULL)
25542572
pfree(fixed_str);
@@ -2698,9 +2716,9 @@ icu_from_uchar(char **result, const UChar *buff_uchar, int32_t len_uchar)
26982716
*/
26992717
pg_attribute_unused()
27002718
static void
2701-
icu_set_collation_attributes(UCollator *collator, const char *loc)
2719+
icu_set_collation_attributes(UCollator *collator, const char *loc,
2720+
UErrorCode *status)
27022721
{
2703-
UErrorCode status;
27042722
int32_t len;
27052723
char *icu_locale_id;
27062724
char *lower_str;
@@ -2713,15 +2731,13 @@ icu_set_collation_attributes(UCollator *collator, const char *loc)
27132731
* locale ID, e.g. "und@colcaselevel=yes;colstrength=primary", by
27142732
* uloc_canonicalize().
27152733
*/
2716-
status = U_ZERO_ERROR;
2717-
len = uloc_canonicalize(loc, NULL, 0, &status);
2734+
*status = U_ZERO_ERROR;
2735+
len = uloc_canonicalize(loc, NULL, 0, status);
27182736
icu_locale_id = palloc(len + 1);
2719-
status = U_ZERO_ERROR;
2720-
len = uloc_canonicalize(loc, icu_locale_id, len + 1, &status);
2721-
if (U_FAILURE(status))
2722-
ereport(ERROR,
2723-
(errmsg("canonicalization failed for locale string \"%s\": %s",
2724-
loc, u_errorName(status))));
2737+
*status = U_ZERO_ERROR;
2738+
len = uloc_canonicalize(loc, icu_locale_id, len + 1, status);
2739+
if (U_FAILURE(*status))
2740+
return;
27252741

27262742
lower_str = asc_tolower(icu_locale_id, strlen(icu_locale_id));
27272743

@@ -2743,7 +2759,7 @@ icu_set_collation_attributes(UCollator *collator, const char *loc)
27432759
UColAttribute uattr;
27442760
UColAttributeValue uvalue;
27452761

2746-
status = U_ZERO_ERROR;
2762+
*status = U_ZERO_ERROR;
27472763

27482764
*e = '\0';
27492765
name = token;
@@ -2793,22 +2809,12 @@ icu_set_collation_attributes(UCollator *collator, const char *loc)
27932809
else if (strcmp(value, "upper") == 0)
27942810
uvalue = UCOL_UPPER_FIRST;
27952811
else
2796-
status = U_ILLEGAL_ARGUMENT_ERROR;
2797-
2798-
if (status == U_ZERO_ERROR)
2799-
ucol_setAttribute(collator, uattr, uvalue, &status);
2800-
2801-
/*
2802-
* Pretend the error came from ucol_open(), for consistent error
2803-
* message across ICU versions.
2804-
*/
2805-
if (U_FAILURE(status))
28062812
{
2807-
ucol_close(collator);
2808-
ereport(ERROR,
2809-
(errmsg("could not open collator for locale \"%s\": %s",
2810-
loc, u_errorName(status))));
2813+
*status = U_ILLEGAL_ARGUMENT_ERROR;
2814+
break;
28112815
}
2816+
2817+
ucol_setAttribute(collator, uattr, uvalue, status);
28122818
}
28132819
}
28142820

0 commit comments

Comments
 (0)