v5-0008-Introduce-hooks-for-creating-custom-pg_locale_t.patch
text/x-patch
Filename: v5-0008-Introduce-hooks-for-creating-custom-pg_locale_t.patch
Type: text/x-patch
Part: 0
Patch
Format: format-patch
Series: patch v5-0008
Subject: Introduce hooks for creating custom pg_locale_t.
| File | + | − |
|---|---|---|
| src/backend/utils/adt/pg_locale.c | 35 | 20 |
| src/include/utils/pg_locale.h | 16 | 0 |
From f20966d84bcdc8edc7fe2d93ded092e4a6ef7252 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 v5 8/8] 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 | 55 ++++++++++++++++++++-----------
src/include/utils/pg_locale.h | 16 +++++++++
2 files changed, 51 insertions(+), 20 deletions(-)
diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c
index 12f8987065c..2409190fd84 100644
--- a/src/backend/utils/adt/pg_locale.c
+++ b/src/backend/utils/adt/pg_locale.c
@@ -100,6 +100,9 @@ extern pg_locale_t dat_create_locale_libc(HeapTuple dattuple);
extern pg_locale_t coll_create_locale_libc(HeapTuple colltuple,
MemoryContext context);
+default_pg_locale_hook_type default_pg_locale_hook = NULL;
+create_pg_locale_hook_type create_pg_locale_hook = NULL;
+
#ifdef USE_ICU
extern UCollator *pg_ucol_open(const char *loc_str);
#endif
@@ -1409,22 +1412,28 @@ create_pg_locale(Oid collid, MemoryContext context)
Datum datum;
bool isnull;
Form_pg_collation collform;
- pg_locale_t result;
+ pg_locale_t result = NULL;
tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
if (!HeapTupleIsValid(tp))
elog(ERROR, "cache lookup failed for collation %u", collid);
collform = (Form_pg_collation) GETSTRUCT(tp);
- if (collform->collprovider == COLLPROVIDER_BUILTIN)
- result = coll_create_locale_builtin(tp, context);
- else if (collform->collprovider == COLLPROVIDER_ICU)
- result = coll_create_locale_icu(tp, context);
- else if (collform->collprovider == COLLPROVIDER_LIBC)
- result = coll_create_locale_libc(tp, context);
- else
- /* shouldn't happen */
- PGLOCALE_SUPPORT_ERROR(collform->collprovider);
+ if (create_pg_locale_hook != NULL)
+ result = create_pg_locale_hook(tp, context);
+
+ if (result == NULL)
+ {
+ if (collform->collprovider == COLLPROVIDER_BUILTIN)
+ result = coll_create_locale_builtin(tp, context);
+ else if (collform->collprovider == COLLPROVIDER_ICU)
+ result = coll_create_locale_icu(tp, context);
+ else if (collform->collprovider == COLLPROVIDER_LIBC)
+ result = coll_create_locale_libc(tp, context);
+ else
+ /* shouldn't happen */
+ PGLOCALE_SUPPORT_ERROR(collform->collprovider);
+ }
datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
&isnull);
@@ -1481,7 +1490,7 @@ init_database_collation(void)
{
HeapTuple tup;
Form_pg_database dbform;
- pg_locale_t result;
+ pg_locale_t result = NULL;
Assert(default_locale == NULL);
@@ -1491,15 +1500,21 @@ 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 = dat_create_locale_builtin(tup);
- else if (dbform->datlocprovider == COLLPROVIDER_ICU)
- result = dat_create_locale_icu(tup);
- else if (dbform->datlocprovider == COLLPROVIDER_LIBC)
- result = dat_create_locale_libc(tup);
- else
- /* shouldn't happen */
- PGLOCALE_SUPPORT_ERROR(dbform->datlocprovider);
+ if (default_pg_locale_hook != NULL)
+ result = default_pg_locale_hook(tup);
+
+ if (result == NULL)
+ {
+ if (dbform->datlocprovider == COLLPROVIDER_BUILTIN)
+ result = dat_create_locale_builtin(tup);
+ else if (dbform->datlocprovider == COLLPROVIDER_ICU)
+ result = dat_create_locale_icu(tup);
+ else if (dbform->datlocprovider == COLLPROVIDER_LIBC)
+ result = dat_create_locale_libc(tup);
+ else
+ /* shouldn't happen */
+ PGLOCALE_SUPPORT_ERROR(dbform->datlocprovider);
+ }
ReleaseSysCache(tup);
diff --git a/src/include/utils/pg_locale.h b/src/include/utils/pg_locale.h
index 3e5f625f661..65ae2dbd078 100644
--- a/src/include/utils/pg_locale.h
+++ b/src/include/utils/pg_locale.h
@@ -174,6 +174,22 @@ struct pg_locale_struct
typedef struct pg_locale_struct *pg_locale_t;
+/*
+ * Hooks to allow creating a custom pg_locale_t.
+ *
+ * default_pg_locale_hook should allocate the object in TopMemoryContext, and
+ * create_pg_locale_hook should allocate in the provided context.
+ *
+ * Accept a HeapTuple to avoid an extra catalog lookup.
+ */
+struct HeapTupleData;
+typedef pg_locale_t (*default_pg_locale_hook_type)(struct HeapTupleData *dattuple);
+typedef pg_locale_t (*create_pg_locale_hook_type)(struct HeapTupleData *colltuple,
+ MemoryContext context);
+
+extern PGDLLIMPORT default_pg_locale_hook_type default_pg_locale_hook;
+extern PGDLLIMPORT create_pg_locale_hook_type create_pg_locale_hook;
+
extern void init_database_collation(void);
extern pg_locale_t pg_newlocale_from_collation(Oid collid);
--
2.34.1