1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-21 02:52:47 +03:00

Force LC_COLLATE to C in postmaster.

Avoid dependence on setlocale().

strcoll(), etc., are not called directly; all collation-sensitive
calls should go through pg_locale.c and use the appropriate
provider. By setting LC_COLLATE to C, we avoid accidentally depending
on libc behavior when using a different provider.

No behavior change in the backend, but it's possible that some
extensions will be affected. Such extensions should be updated to use
the pg_locale_t APIs.

Discussion: https://postgr.es/m/9875f7f9-50f1-4b5d-86fc-ee8b03e8c162@eisentraut.org
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
This commit is contained in:
Jeff Davis
2025-07-16 14:13:18 -07:00
parent 0858f0f96e
commit 5e6e42e44f
6 changed files with 42 additions and 37 deletions

View File

@@ -125,13 +125,17 @@ main(int argc, char *argv[])
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("postgres"));
/*
* In the postmaster, absorb the environment values for LC_COLLATE and
* LC_CTYPE. Individual backends will change these later to settings
* taken from pg_database, but the postmaster cannot do that. If we leave
* these set to "C" then message localization might not work well in the
* postmaster.
* Collation is handled by pg_locale.c, and the behavior is dependent on
* the provider. strcoll(), etc., should not be called directly.
*/
init_locale("LC_COLLATE", LC_COLLATE, "C");
/*
* In the postmaster, absorb the environment value for LC_CTYPE.
* Individual backends will change it later to pg_database.datctype, but
* the postmaster cannot do that. If we leave it set to "C" then message
* localization might not work well in the postmaster.
*/
init_locale("LC_COLLATE", LC_COLLATE, "");
init_locale("LC_CTYPE", LC_CTYPE, "");
/*

View File

@@ -417,12 +417,11 @@ CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connect
datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datctype);
ctype = TextDatumGetCString(datum);
if (pg_perm_setlocale(LC_COLLATE, collate) == NULL)
ereport(FATAL,
(errmsg("database locale is incompatible with operating system"),
errdetail("The database was initialized with LC_COLLATE \"%s\", "
" which is not recognized by setlocale().", collate),
errhint("Recreate the database with another locale or install the missing locale.")));
/*
* Historcally, we set LC_COLLATE from datcollate, as well. That's no
* longer necessary because all collation behavior is handled through
* pg_locale_t.
*/
if (pg_perm_setlocale(LC_CTYPE, ctype) == NULL)
ereport(FATAL,