From b4dca9097633c585da232bc640f2517b3c443f09 Mon Sep 17 00:00:00 2001 From: Marina Polyakova Date: Sat, 19 Nov 2022 17:24:55 +0300 Subject: [PATCH v2 1/3] Fix encoding check in initdb when the option --icu-locale is not used First check that the selected encoding is supported by ICU (the encoding can be set from lc_ctype which can be set from an environment variable). Only then check the option for the ICU locale. --- src/bin/initdb/initdb.c | 35 +++++++++++++------------------ src/bin/initdb/t/001_initdb.pl | 17 ++++++++++----- src/bin/scripts/t/020_createdb.pl | 26 ++++++++++++++++++----- 3 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index f61a043055..444c8a505a 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -2047,7 +2047,7 @@ check_locale_encoding(const char *locale, int user_enc) * * this should match the similar check in the backend createdb() function */ -static bool +static void check_icu_locale_encoding(int user_enc) { if (!(is_encoding_supported_by_icu(user_enc))) @@ -2058,9 +2058,19 @@ check_icu_locale_encoding(int user_enc) pg_log_error_hint("Rerun %s and either do not specify an encoding explicitly, " "or choose a matching combination.", progname); - return false; + exit(1); } - return true; + + if (!icu_locale) + pg_fatal("ICU locale must be specified"); + + /* + * In supported builds, the ICU locale ID will be checked by the backend + * during post-bootstrap initialization. + */ +#ifndef USE_ICU + pg_fatal("ICU is not supported in this build"); +#endif } /* @@ -2113,20 +2123,6 @@ setlocales(void) check_locale_name(LC_CTYPE, lc_messages, &canonname); lc_messages = canonname; #endif - - if (locale_provider == COLLPROVIDER_ICU) - { - if (!icu_locale) - pg_fatal("ICU locale must be specified"); - - /* - * In supported builds, the ICU locale ID will be checked by the - * backend during post-bootstrap initialization. - */ -#ifndef USE_ICU - pg_fatal("ICU is not supported in this build"); -#endif - } } /* @@ -2388,9 +2384,8 @@ setup_locale_encoding(void) !check_locale_encoding(lc_collate, encodingid)) exit(1); /* check_locale_encoding printed the error */ - if (locale_provider == COLLPROVIDER_ICU && - !check_icu_locale_encoding(encodingid)) - exit(1); + if (locale_provider == COLLPROVIDER_ICU) + check_icu_locale_encoding(encodingid); } diff --git a/src/bin/initdb/t/001_initdb.pl b/src/bin/initdb/t/001_initdb.pl index 164fc11cbf..20fe29851c 100644 --- a/src/bin/initdb/t/001_initdb.pl +++ b/src/bin/initdb/t/001_initdb.pl @@ -123,28 +123,35 @@ if ($ENV{with_icu} eq 'yes') [ 'initdb', '--no-sync', '--locale-provider=icu', '--encoding=SQL_ASCII', - '--icu-locale=en', "$tempdir/dataX" + "$tempdir/dataX" ], qr/error: encoding mismatch/, 'fails for encoding not supported by ICU'); } else { - command_fails( - [ 'initdb', '--no-sync', '--locale-provider=icu', "$tempdir/data2" ], + command_fails_like( + [ + 'initdb', '--no-sync', + '--locale-provider=icu', '--icu-locale=en', + "$tempdir/data2" + ], + qr/error: ICU is not supported in this build/, 'locale provider ICU fails since no ICU support'); } -command_fails( +command_fails_like( [ 'initdb', '--no-sync', '--locale-provider=xyz', "$tempdir/dataX" ], + qr/error: unrecognized locale provider: xyz/, 'fails for invalid locale provider'); -command_fails( +command_fails_like( [ 'initdb', '--no-sync', '--locale-provider=libc', '--icu-locale=en', "$tempdir/dataX" ], + qr/error: --icu-locale cannot be specified unless locale provider "icu" is chosen/, 'fails for invalid option combination'); done_testing(); diff --git a/src/bin/scripts/t/020_createdb.pl b/src/bin/scripts/t/020_createdb.pl index a74bf3b0d8..3030ea7f9d 100644 --- a/src/bin/scripts/t/020_createdb.pl +++ b/src/bin/scripts/t/020_createdb.pl @@ -30,11 +30,12 @@ if ($ENV{with_icu} eq 'yes') # This fails because template0 uses libc provider and has no ICU # locale set. It would succeed if template0 used the icu # provider. XXX Maybe split into multiple tests? - $node->command_fails( + $node->command_fails_like( [ 'createdb', '-T', 'template0', '-E', 'UTF8', '--locale-provider=icu', 'foobar4' ], + qr/ERROR: ICU locale must be specified/, 'create database with ICU fails without ICU locale specified'); $node->issues_sql_like( @@ -46,12 +47,13 @@ if ($ENV{with_icu} eq 'yes') qr/statement: CREATE DATABASE foobar5 .* LOCALE_PROVIDER icu ICU_LOCALE 'en'/, 'create database with ICU locale specified'); - $node->command_fails( + $node->command_fails_like( [ 'createdb', '-T', 'template0', '-E', 'UTF8', '--locale-provider=icu', '--icu-locale=@colNumeric=lower', 'foobarX' ], + qr/ERROR: could not open collator for locale/, 'fails for invalid ICU locale'); $node->command_fails_like( @@ -78,18 +80,32 @@ if ($ENV{with_icu} eq 'yes') } else { - $node->command_fails( - [ 'createdb', '-T', 'template0', '--locale-provider=icu', 'foobar4' ], + $node->command_fails_like( + [ + 'createdb', '-T', 'template0', '-E', 'UTF8', + '--locale-provider=icu', '--icu-locale=en', 'foobar4' + ], + qr/ERROR: ICU is not supported in this build/, 'create database with ICU fails since no ICU support'); } $node->command_fails([ 'createdb', 'foobar1' ], 'fails if database already exists'); -$node->command_fails( +$node->command_fails_like( [ 'createdb', '-T', 'template0', '--locale-provider=xyz', 'foobarX' ], + qr/ERROR: unrecognized locale provider: xyz/, 'fails for invalid locale provider'); +$node->command_fails_like( + [ + 'createdb', '-T', + 'template0', '--locale-provider=libc', + '--icu-locale=en', 'foobarX' + ], + qr/ERROR: ICU locale cannot be specified unless locale provider is ICU/, + 'fails for invalid option combination'); + # Check use of templates with shared dependencies copied from the template. my ($ret, $stdout, $stderr) = $node->psql( 'foobar2', -- 2.25.1