Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit c7db01e

Browse files
committed
Don't allow creation of database with ICU locale with unsupported encoding
Check in CREATE DATABASE and initdb that the selected encoding is supported by ICU. Before, they would pass but users would later get an error from the server when they tried to use the database. Also document that initdb sets the encoding to UTF8 by default if the ICU locale provider is chosen. Author: Marina Polyakova <m.polyakova@postgrespro.ru> Reviewed-by: Kyotaro Horiguchi <horikyota.ntt@gmail.com> Discussion: https://www.postgresql.org/message-id/6dd6db0984d86a51b7255ba79f111971@postgrespro.ru
1 parent cf2c7a7 commit c7db01e

File tree

5 files changed

+57
-4
lines changed

5 files changed

+57
-4
lines changed

doc/src/sgml/ref/initdb.sgml

+3-2
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,9 @@ PostgreSQL documentation
209209
<para>
210210
Selects the encoding of the template databases. This will also
211211
be the default encoding of any database you create later,
212-
unless you override it then. The default is derived from the locale, or
213-
<literal>SQL_ASCII</literal> if that does not work. The character sets supported by
212+
unless you override it then. The default is derived from the locale,
213+
if the libc locale provider is used, or <literal>UTF8</literal> if the
214+
ICU locale provider is used. The character sets supported by
214215
the <productname>PostgreSQL</productname> server are described
215216
in <xref linkend="multibyte-charset-supported"/>.
216217
</para>

src/backend/commands/dbcommands.c

+7-2
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,12 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
10341034

10351035
if (dblocprovider == COLLPROVIDER_ICU)
10361036
{
1037+
if (!(is_encoding_supported_by_icu(encoding)))
1038+
ereport(ERROR,
1039+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1040+
errmsg("encoding \"%s\" is not supported with ICU provider",
1041+
pg_encoding_to_char(encoding))));
1042+
10371043
/*
10381044
* This would happen if template0 uses the libc provider but the new
10391045
* database uses icu.
@@ -1042,10 +1048,9 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
10421048
ereport(ERROR,
10431049
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
10441050
errmsg("ICU locale must be specified")));
1045-
}
10461051

1047-
if (dblocprovider == COLLPROVIDER_ICU)
10481052
check_icu_locale(dbiculocale);
1053+
}
10491054

10501055
/*
10511056
* Check that the new encoding and locale settings match the source

src/bin/initdb/initdb.c

+29
Original file line numberDiff line numberDiff line change
@@ -2042,6 +2042,27 @@ check_locale_encoding(const char *locale, int user_enc)
20422042
return true;
20432043
}
20442044

2045+
/*
2046+
* check if the chosen encoding matches is supported by ICU
2047+
*
2048+
* this should match the similar check in the backend createdb() function
2049+
*/
2050+
static bool
2051+
check_icu_locale_encoding(int user_enc)
2052+
{
2053+
if (!(is_encoding_supported_by_icu(user_enc)))
2054+
{
2055+
pg_log_error("encoding mismatch");
2056+
pg_log_error_detail("The encoding you selected (%s) is not supported with the ICU provider.",
2057+
pg_encoding_to_char(user_enc));
2058+
pg_log_error_hint("Rerun %s and either do not specify an encoding explicitly, "
2059+
"or choose a matching combination.",
2060+
progname);
2061+
return false;
2062+
}
2063+
return true;
2064+
}
2065+
20452066
/*
20462067
* set up the locale variables
20472068
*
@@ -2310,7 +2331,11 @@ setup_locale_encoding(void)
23102331
}
23112332

23122333
if (!encoding && locale_provider == COLLPROVIDER_ICU)
2334+
{
23132335
encodingid = PG_UTF8;
2336+
printf(_("The default database encoding has been set to \"%s\".\n"),
2337+
pg_encoding_to_char(encodingid));
2338+
}
23142339
else if (!encoding)
23152340
{
23162341
int ctype_enc;
@@ -2362,6 +2387,10 @@ setup_locale_encoding(void)
23622387
if (!check_locale_encoding(lc_ctype, encodingid) ||
23632388
!check_locale_encoding(lc_collate, encodingid))
23642389
exit(1); /* check_locale_encoding printed the error */
2390+
2391+
if (locale_provider == COLLPROVIDER_ICU &&
2392+
!check_icu_locale_encoding(encodingid))
2393+
exit(1);
23652394
}
23662395

23672396

src/bin/initdb/t/001_initdb.pl

+9
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,15 @@
118118
],
119119
qr/FATAL: could not open collator for locale/,
120120
'fails for invalid ICU locale');
121+
122+
command_fails_like(
123+
[
124+
'initdb', '--no-sync',
125+
'--locale-provider=icu', '--encoding=SQL_ASCII',
126+
'--icu-locale=en', "$tempdir/dataX"
127+
],
128+
qr/error: encoding mismatch/,
129+
'fails for encoding not supported by ICU');
121130
}
122131
else
123132
{

src/bin/scripts/t/020_createdb.pl

+9
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@
5050
],
5151
'fails for invalid ICU locale');
5252

53+
$node->command_fails_like(
54+
[
55+
'createdb', '-T',
56+
'template0', '--locale-provider=icu',
57+
'--encoding=SQL_ASCII', 'foobarX'
58+
],
59+
qr/ERROR: encoding "SQL_ASCII" is not supported with ICU provider/,
60+
'fails for encoding not supported by ICU');
61+
5362
# additional node, which uses the icu provider
5463
my $node2 = PostgreSQL::Test::Cluster->new('icu');
5564
$node2->init(extra => ['--locale-provider=icu', '--icu-locale=en']);

0 commit comments

Comments
 (0)