v8-0007-Introduce-hooks-for-creating-custom-pg_locale_t.patch
text/x-patch
Filename: v8-0007-Introduce-hooks-for-creating-custom-pg_locale_t.patch
Type: text/x-patch
Part: 6
Patch
Format: format-patch
Series: patch v8-0007
Subject: Introduce hooks for creating custom pg_locale_t.
| File | + | − |
|---|---|---|
| src/backend/utils/adt/pg_locale.c | 46 | 22 |
| src/include/utils/pg_locale.h | 24 | 0 |
| src/tools/pgindent/typedefs.list | 2 | 0 |
From 0db38e3a2f29a3638ead67ebcd98a0a414c2ad1e Mon Sep 17 00:00:00 2001
From: Jeff Davis <jeff@j-davis.com>
Date: Wed, 25 Sep 2024 16:10:28 -0700
Subject: [PATCH v8 7/7] Introduce hooks for creating custom pg_locale_t.
Now that collation, case mapping, and ctype behavior is controlled
with a method table, we can hook the behavior.
The hooks can provide their own arbitrary method table, which may be
based on a different version of ICU than what Postgres was built with,
or entirely unrelated to ICU/libc.
---
src/backend/utils/adt/pg_locale.c | 68 +++++++++++++++++++++----------
src/include/utils/pg_locale.h | 24 +++++++++++
src/tools/pgindent/typedefs.list | 2 +
3 files changed, 72 insertions(+), 22 deletions(-)
diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c
index d40ecf2357..c3fa68ead5 100644
--- a/src/backend/utils/adt/pg_locale.c
+++ b/src/backend/utils/adt/pg_locale.c
@@ -103,6 +103,9 @@ extern pg_locale_t create_pg_locale_builtin(Oid collid, MemoryContext context);
extern pg_locale_t create_pg_locale_icu(Oid collid, MemoryContext context);
extern pg_locale_t create_pg_locale_libc(Oid collid, MemoryContext context);
+create_pg_locale_hook_type create_pg_locale_hook = NULL;
+collation_version_hook_type collation_version_hook = NULL;
+
/* GUC settings */
char *locale_messages;
char *locale_monetary;
@@ -1209,7 +1212,7 @@ create_pg_locale(Oid collid, MemoryContext context)
{
HeapTuple tp;
Form_pg_collation collform;
- pg_locale_t result;
+ pg_locale_t result = NULL;
Datum datum;
bool isnull;
@@ -1218,15 +1221,21 @@ create_pg_locale(Oid collid, MemoryContext context)
elog(ERROR, "cache lookup failed for collation %u", collid);
collform = (Form_pg_collation) GETSTRUCT(tp);
- if (collform->collprovider == COLLPROVIDER_BUILTIN)
- result = create_pg_locale_builtin(collid, context);
- else if (collform->collprovider == COLLPROVIDER_ICU)
- result = create_pg_locale_icu(collid, context);
- else if (collform->collprovider == COLLPROVIDER_LIBC)
- result = create_pg_locale_libc(collid, context);
- else
- /* shouldn't happen */
- PGLOCALE_SUPPORT_ERROR(collform->collprovider);
+ if (create_pg_locale_hook != NULL)
+ result = create_pg_locale_hook(collid, context);
+
+ if (result == NULL)
+ {
+ if (collform->collprovider == COLLPROVIDER_BUILTIN)
+ result = create_pg_locale_builtin(collid, context);
+ else if (collform->collprovider == COLLPROVIDER_ICU)
+ result = create_pg_locale_icu(collid, context);
+ else if (collform->collprovider == COLLPROVIDER_LIBC)
+ result = create_pg_locale_libc(collid, context);
+ else
+ /* shouldn't happen */
+ PGLOCALE_SUPPORT_ERROR(collform->collprovider);
+ }
Assert((result->collate_is_c && result->collate == NULL) ||
(!result->collate_is_c && result->collate != NULL));
@@ -1289,7 +1298,7 @@ init_database_collation(void)
{
HeapTuple tup;
Form_pg_database dbform;
- pg_locale_t result;
+ pg_locale_t result = NULL;
Assert(default_locale == NULL);
@@ -1299,18 +1308,25 @@ init_database_collation(void)
elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
dbform = (Form_pg_database) GETSTRUCT(tup);
- if (dbform->datlocprovider == COLLPROVIDER_BUILTIN)
- result = create_pg_locale_builtin(DEFAULT_COLLATION_OID,
- TopMemoryContext);
- else if (dbform->datlocprovider == COLLPROVIDER_ICU)
- result = create_pg_locale_icu(DEFAULT_COLLATION_OID,
- TopMemoryContext);
- else if (dbform->datlocprovider == COLLPROVIDER_LIBC)
- result = create_pg_locale_libc(DEFAULT_COLLATION_OID,
+ if (create_pg_locale_hook != NULL)
+ result = create_pg_locale_hook(DEFAULT_COLLATION_OID,
TopMemoryContext);
- else
- /* shouldn't happen */
- PGLOCALE_SUPPORT_ERROR(dbform->datlocprovider);
+
+ if (result == NULL)
+ {
+ if (dbform->datlocprovider == COLLPROVIDER_BUILTIN)
+ result = create_pg_locale_builtin(DEFAULT_COLLATION_OID,
+ TopMemoryContext);
+ else if (dbform->datlocprovider == COLLPROVIDER_ICU)
+ result = create_pg_locale_icu(DEFAULT_COLLATION_OID,
+ TopMemoryContext);
+ else if (dbform->datlocprovider == COLLPROVIDER_LIBC)
+ result = create_pg_locale_libc(DEFAULT_COLLATION_OID,
+ TopMemoryContext);
+ else
+ /* shouldn't happen */
+ PGLOCALE_SUPPORT_ERROR(dbform->datlocprovider);
+ }
ReleaseSysCache(tup);
@@ -1379,6 +1395,14 @@ get_collation_actual_version(char collprovider, const char *collcollate)
{
char *collversion = NULL;
+ if (collation_version_hook != NULL)
+ {
+ char *version;
+
+ if (collation_version_hook(collprovider, collcollate, &version))
+ return version;
+ }
+
/*
* The only two supported locales (C and C.UTF-8) are both based on memcmp
* and are not expected to change, but track the version anyway.
diff --git a/src/include/utils/pg_locale.h b/src/include/utils/pg_locale.h
index 24f7ee4b61..7bd00a16a6 100644
--- a/src/include/utils/pg_locale.h
+++ b/src/include/utils/pg_locale.h
@@ -155,6 +155,30 @@ struct pg_locale_struct
typedef struct pg_locale_struct *pg_locale_t;
+/*
+ * Hooks to enable custom locale providers.
+ */
+
+/*
+ * Hook create_pg_locale(). Return result (allocated in the given context) to
+ * override; or return NULL to return control to create_pg_locale(). When
+ * creating the default database collation, collid is DEFAULT_COLLATION_OID.
+ */
+typedef pg_locale_t (*create_pg_locale_hook_type) (Oid collid,
+ MemoryContext context);
+
+/*
+ * Hook get_collation_actual_version(). Set *version out parameter and return
+ * true to override; or return false to return control to
+ * get_collation_actual_version().
+ */
+typedef bool (*collation_version_hook_type) (char collprovider,
+ const char *collcollate,
+ char **version);
+
+extern PGDLLIMPORT create_pg_locale_hook_type create_pg_locale_hook;
+extern PGDLLIMPORT collation_version_hook_type collation_version_hook;
+
extern void init_database_collation(void);
extern pg_locale_t pg_newlocale_from_collation(Oid collid);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 416a2cc76b..1d4247267b 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -3375,6 +3375,7 @@ cmpEntriesArg
codes_t
collation_cache_entry
collation_cache_hash
+collation_version_hook_type
color
colormaprange
compare_context
@@ -3391,6 +3392,7 @@ core_yyscan_t
corrupt_items
cost_qual_eval_context
cp_hash_func
+create_pg_locale_hook_type
create_upper_paths_hook_type
createdb_failure_params
crosstab_HashEnt
--
2.34.1