|
58 | 58 | #include"catalog/pg_collation.h"
|
59 | 59 | #include"catalog/pg_control.h"
|
60 | 60 | #include"mb/pg_wchar.h"
|
| 61 | +#include"miscadmin.h" |
61 | 62 | #include"utils/builtins.h"
|
62 | 63 | #include"utils/formatting.h"
|
63 | 64 | #include"utils/guc_hooks.h"
|
@@ -95,6 +96,8 @@ char *locale_monetary;
|
95 | 96 | char*locale_numeric;
|
96 | 97 | char*locale_time;
|
97 | 98 |
|
| 99 | +inticu_validation_level=ERROR; |
| 100 | + |
98 | 101 | /*
|
99 | 102 | * lc_time localization cache.
|
100 | 103 | *
|
@@ -2821,24 +2824,77 @@ icu_set_collation_attributes(UCollator *collator, const char *loc,
|
2821 | 2824 | pfree(lower_str);
|
2822 | 2825 | }
|
2823 | 2826 |
|
2824 |
| -#endif/* USE_ICU */ |
| 2827 | +#endif |
2825 | 2828 |
|
2826 | 2829 | /*
|
2827 |
| - *Check if the givenlocaleIDis valid, and ereport(ERROR) if it isn't. |
| 2830 | + *Perform best-effort check that thelocale isavalid one. |
2828 | 2831 | */
|
2829 | 2832 | void
|
2830 |
| -check_icu_locale(constchar*icu_locale) |
| 2833 | +icu_validate_locale(constchar*loc_str) |
2831 | 2834 | {
|
2832 | 2835 | #ifdefUSE_ICU
|
2833 |
| -UCollator*collator; |
| 2836 | +UCollator*collator; |
| 2837 | +UErrorCodestatus; |
| 2838 | +charlang[ULOC_LANG_CAPACITY]; |
| 2839 | +boolfound= false; |
| 2840 | +intelevel=icu_validation_level; |
| 2841 | + |
| 2842 | +/* no validation */ |
| 2843 | +if (elevel<0) |
| 2844 | +return; |
| 2845 | + |
| 2846 | +/* downgrade to WARNING during pg_upgrade */ |
| 2847 | +if (IsBinaryUpgrade&&elevel>WARNING) |
| 2848 | +elevel=WARNING; |
| 2849 | + |
| 2850 | +/* validate that we can extract the language */ |
| 2851 | +status=U_ZERO_ERROR; |
| 2852 | +uloc_getLanguage(loc_str,lang,ULOC_LANG_CAPACITY,&status); |
| 2853 | +if (U_FAILURE(status)) |
| 2854 | +{ |
| 2855 | +ereport(elevel, |
| 2856 | +(errmsg("could not get language from ICU locale \"%s\": %s", |
| 2857 | +loc_str,u_errorName(status)), |
| 2858 | +errhint("To disable ICU locale validation, set parameter icu_validation_level to DISABLED."))); |
| 2859 | +return; |
| 2860 | +} |
| 2861 | + |
| 2862 | +/* check for special language name */ |
| 2863 | +if (strcmp(lang,"")==0|| |
| 2864 | +strcmp(lang,"root")==0||strcmp(lang,"und")==0|| |
| 2865 | +strcmp(lang,"c")==0||strcmp(lang,"posix")==0) |
| 2866 | +found= true; |
2834 | 2867 |
|
2835 |
| -collator=pg_ucol_open(icu_locale); |
| 2868 | +/* search for matching language within ICU */ |
| 2869 | +for (int32_ti=0; !found&&i<uloc_countAvailable();i++) |
| 2870 | +{ |
| 2871 | +constchar*otherloc=uloc_getAvailable(i); |
| 2872 | +charotherlang[ULOC_LANG_CAPACITY]; |
| 2873 | + |
| 2874 | +status=U_ZERO_ERROR; |
| 2875 | +uloc_getLanguage(otherloc,otherlang,ULOC_LANG_CAPACITY,&status); |
| 2876 | +if (U_FAILURE(status)) |
| 2877 | +continue; |
| 2878 | + |
| 2879 | +if (strcmp(lang,otherlang)==0) |
| 2880 | +found= true; |
| 2881 | +} |
| 2882 | + |
| 2883 | +if (!found) |
| 2884 | +ereport(elevel, |
| 2885 | +(errmsg("ICU locale \"%s\" has unknown language \"%s\"", |
| 2886 | +loc_str,lang), |
| 2887 | +errhint("To disable ICU locale validation, set parameter icu_validation_level to DISABLED."))); |
| 2888 | + |
| 2889 | +/* check that it can be opened */ |
| 2890 | +collator=pg_ucol_open(loc_str); |
2836 | 2891 | ucol_close(collator);
|
2837 |
| -#else |
| 2892 | +#else/* not USE_ICU */ |
| 2893 | +/* could get here if a collation was created by a build with ICU */ |
2838 | 2894 | ereport(ERROR,
|
2839 | 2895 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
2840 | 2896 | errmsg("ICU is not supported in this build")));
|
2841 |
| -#endif |
| 2897 | +#endif/* not USE_ICU */ |
2842 | 2898 | }
|
2843 | 2899 |
|
2844 | 2900 | /*
|
|