v4-0003-Initialize-datctype-in-global-locale_t-variable.patch
text/x-patch
Filename: v4-0003-Initialize-datctype-in-global-locale_t-variable.patch
Type: text/x-patch
Part: 2
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v4-0003
Subject: Initialize datctype in global locale_t variable.
| File | + | − |
|---|---|---|
| src/backend/utils/adt/pg_locale_libc.c | 35 | 0 |
| src/backend/utils/init/postinit.c | 2 | 0 |
| src/include/utils/pg_locale.h | 7 | 0 |
From 3b7f43c4ad3b2bd99de95ae9db980d7bc465a8a9 Mon Sep 17 00:00:00 2001
From: Jeff Davis <jeff@j-davis.com>
Date: Fri, 6 Jun 2025 14:13:16 -0700
Subject: [PATCH v4 3/8] Initialize datctype in global locale_t variable.
Callers of locale-aware ctype operations should use the "_l" variants
of the functions and pass global_libc_ctype for the locale. Doing so
avoids depending on setlocale().
Discussion: https://postgr.es/m/9875f7f9-50f1-4b5d-86fc-ee8b03e8c162@eisentraut.org
---
src/backend/utils/adt/pg_locale_libc.c | 35 ++++++++++++++++++++++++++
src/backend/utils/init/postinit.c | 2 ++
src/include/utils/pg_locale.h | 7 ++++++
3 files changed, 44 insertions(+)
diff --git a/src/backend/utils/adt/pg_locale_libc.c b/src/backend/utils/adt/pg_locale_libc.c
index 8d88b53c375..33a082b6490 100644
--- a/src/backend/utils/adt/pg_locale_libc.c
+++ b/src/backend/utils/adt/pg_locale_libc.c
@@ -81,6 +81,12 @@
*/
#define TEXTBUFLEN 1024
+/*
+ * Represents datctype locale in a global variable, so that we don't need to
+ * rely on setlocale() anywhere.
+ */
+locale_t global_libc_ctype = NULL;
+
extern pg_locale_t create_pg_locale_libc(Oid collid, MemoryContext context);
static int strncoll_libc(const char *arg1, ssize_t len1,
@@ -665,6 +671,35 @@ strupper_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen,
return result_size;
}
+/*
+ * Initialize global locale for LC_COLLATE and LC_CTYPE from datcollate and
+ * datctype, respectively.
+ *
+ * NB: should be consistent with make_libc_collator(), except that it must
+ * create the locale even for "C" and "POSIX".
+ */
+void
+init_global_libc_ctype(const char *ctype)
+{
+ locale_t loc = 0;
+
+ /* Normal case where they're the same */
+ errno = 0;
+#ifndef WIN32
+ loc = newlocale(LC_CTYPE_MASK, ctype, NULL);
+#else
+ loc = _create_locale(LC_ALL, ctype);
+#endif
+ if (!loc)
+ ereport(FATAL,
+ (errmsg("database locale is incompatible with operating system"),
+ errdetail("The database was initialized with LC_CTYPE \"%s\", "
+ " which is not recognized by setlocale().", ctype),
+ errhint("Recreate the database with another locale or install the missing locale.")));
+
+ global_libc_ctype = loc;
+}
+
pg_locale_t
create_pg_locale_libc(Oid collid, MemoryContext context)
{
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 464f1196be3..81bde31a791 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -429,6 +429,8 @@ CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connect
" which is not recognized by setlocale().", ctype),
errhint("Recreate the database with another locale or install the missing locale.")));
+ init_global_libc_ctype(ctype);
+
if (strcmp(ctype, "C") == 0 ||
strcmp(ctype, "POSIX") == 0)
database_ctype_is_c = true;
diff --git a/src/include/utils/pg_locale.h b/src/include/utils/pg_locale.h
index 6c60f2e2a74..a4ab020685f 100644
--- a/src/include/utils/pg_locale.h
+++ b/src/include/utils/pg_locale.h
@@ -34,6 +34,12 @@ extern PGDLLIMPORT char *localized_full_days[];
extern PGDLLIMPORT char *localized_abbrev_months[];
extern PGDLLIMPORT char *localized_full_months[];
+/*
+ * Represents datcollate and datctype locales in a global variable, so that we
+ * don't need to rely on setlocale() anywhere.
+ */
+extern PGDLLIMPORT locale_t global_libc_ctype;
+
/* is the databases's LC_CTYPE the C locale? */
extern PGDLLIMPORT bool database_ctype_is_c;
@@ -169,6 +175,7 @@ struct pg_locale_struct
} info;
};
+extern void init_global_libc_ctype(const char *ctype);
extern void init_database_collation(void);
extern pg_locale_t pg_newlocale_from_collation(Oid collid);
--
2.43.0