v1-0006-Use-global_lc_ctype-for-callers-of-locale-aware-f.patch
text/x-patch
Filename: v1-0006-Use-global_lc_ctype-for-callers-of-locale-aware-f.patch
Type: text/x-patch
Part: 5
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 v1-0006
Subject: Use global_lc_ctype for callers of locale-aware functions.
| File | + | − |
|---|---|---|
| contrib/fuzzystrmatch/dmetaphone.c | 2 | 1 |
| contrib/fuzzystrmatch/fuzzystrmatch.c | 11 | 8 |
| contrib/ltree/crc32.c | 1 | 1 |
| src/backend/parser/scansup.c | 2 | 1 |
| src/backend/tsearch/ts_locale.c | 2 | 2 |
| src/port/pgstrcasecmp.c | 14 | 6 |
From c4eaa408a045d0ff9baaa44571469be0ffabf2f2 Mon Sep 17 00:00:00 2001
From: Jeff Davis <jeff@j-davis.com>
Date: Fri, 6 Jun 2025 14:17:22 -0700
Subject: [PATCH v1 6/8] Use global_lc_ctype for callers of locale-aware
functions.
Rather than relying on setlocale() to set the right LC_CTYPE, use
global_lc_ctype explicitly to refer to datctype.
---
contrib/fuzzystrmatch/dmetaphone.c | 3 ++-
contrib/fuzzystrmatch/fuzzystrmatch.c | 19 +++++++++++--------
contrib/ltree/crc32.c | 2 +-
src/backend/parser/scansup.c | 3 ++-
src/backend/tsearch/ts_locale.c | 4 ++--
src/port/pgstrcasecmp.c | 20 ++++++++++++++------
6 files changed, 32 insertions(+), 19 deletions(-)
diff --git a/contrib/fuzzystrmatch/dmetaphone.c b/contrib/fuzzystrmatch/dmetaphone.c
index 6627b2b8943..07d8781cd2a 100644
--- a/contrib/fuzzystrmatch/dmetaphone.c
+++ b/contrib/fuzzystrmatch/dmetaphone.c
@@ -99,6 +99,7 @@ The remaining code is authored by Andrew Dunstan <amdunstan@ncshp.org> and
#include "postgres.h"
#include "utils/builtins.h"
+#include "utils/pg_locale.h"
/* turn off assertions for embedded function */
#define NDEBUG
@@ -284,7 +285,7 @@ MakeUpper(metastring *s)
char *i;
for (i = s->str; *i; i++)
- *i = toupper((unsigned char) *i);
+ *i = toupper_l((unsigned char) *i, global_lc_ctype);
}
diff --git a/contrib/fuzzystrmatch/fuzzystrmatch.c b/contrib/fuzzystrmatch/fuzzystrmatch.c
index e7cc314b763..b619178a1f6 100644
--- a/contrib/fuzzystrmatch/fuzzystrmatch.c
+++ b/contrib/fuzzystrmatch/fuzzystrmatch.c
@@ -41,6 +41,7 @@
#include <ctype.h>
#include "utils/builtins.h"
+#include "utils/pg_locale.h"
#include "utils/varlena.h"
#include "varatt.h"
@@ -56,13 +57,15 @@ static void _soundex(const char *instr, char *outstr);
#define SOUNDEX_LEN 4
+#define TOUPPER(x) toupper_l((unsigned char) (x), global_lc_ctype)
+
/* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
static const char *const soundex_table = "01230120022455012623010202";
static char
soundex_code(char letter)
{
- letter = toupper((unsigned char) letter);
+ letter = TOUPPER((unsigned char) letter);
/* Defend against non-ASCII letters */
if (letter >= 'A' && letter <= 'Z')
return soundex_table[letter - 'A'];
@@ -124,7 +127,7 @@ getcode(char c)
{
if (isalpha((unsigned char) c))
{
- c = toupper((unsigned char) c);
+ c = TOUPPER((unsigned char) c);
/* Defend against non-ASCII letters */
if (c >= 'A' && c <= 'Z')
return _codes[c - 'A'];
@@ -301,18 +304,18 @@ metaphone(PG_FUNCTION_ARGS)
* accessing the array directly... */
/* Look at the next letter in the word */
-#define Next_Letter (toupper((unsigned char) word[w_idx+1]))
+#define Next_Letter (TOUPPER((unsigned char) word[w_idx+1]))
/* Look at the current letter in the word */
-#define Curr_Letter (toupper((unsigned char) word[w_idx]))
+#define Curr_Letter (TOUPPER((unsigned char) word[w_idx]))
/* Go N letters back. */
#define Look_Back_Letter(n) \
- (w_idx >= (n) ? toupper((unsigned char) word[w_idx-(n)]) : '\0')
+ (w_idx >= (n) ? TOUPPER((unsigned char) word[w_idx-(n)]) : '\0')
/* Previous letter. I dunno, should this return null on failure? */
#define Prev_Letter (Look_Back_Letter(1))
/* Look two letters down. It makes sure you don't walk off the string. */
#define After_Next_Letter \
- (Next_Letter != '\0' ? toupper((unsigned char) word[w_idx+2]) : '\0')
-#define Look_Ahead_Letter(n) toupper((unsigned char) Lookahead(word+w_idx, n))
+ (Next_Letter != '\0' ? TOUPPER((unsigned char) word[w_idx+2]) : '\0')
+#define Look_Ahead_Letter(n) TOUPPER((unsigned char) Lookahead(word+w_idx, n))
/* Allows us to safely look ahead an arbitrary # of letters */
@@ -742,7 +745,7 @@ _soundex(const char *instr, char *outstr)
}
/* Take the first letter as is */
- *outstr++ = (char) toupper((unsigned char) *instr++);
+ *outstr++ = (char) TOUPPER((unsigned char) *instr++);
count = 1;
while (*instr && count < SOUNDEX_LEN)
diff --git a/contrib/ltree/crc32.c b/contrib/ltree/crc32.c
index 134f46a805e..2ea7c8a5ec0 100644
--- a/contrib/ltree/crc32.c
+++ b/contrib/ltree/crc32.c
@@ -12,7 +12,7 @@
#ifdef LOWER_NODE
#include <ctype.h>
-#define TOLOWER(x) tolower((unsigned char) (x))
+#define TOLOWER(x) tolower_l((unsigned char) (x), global_lc_ctype)
#else
#define TOLOWER(x) (x)
#endif
diff --git a/src/backend/parser/scansup.c b/src/backend/parser/scansup.c
index 2feb2b6cf5a..98c1f30d04f 100644
--- a/src/backend/parser/scansup.c
+++ b/src/backend/parser/scansup.c
@@ -18,6 +18,7 @@
#include "mb/pg_wchar.h"
#include "parser/scansup.h"
+#include "utils/pg_locale.h"
/*
@@ -68,7 +69,7 @@ downcase_identifier(const char *ident, int len, bool warn, bool truncate)
if (ch >= 'A' && ch <= 'Z')
ch += 'a' - 'A';
else if (enc_is_single_byte && IS_HIGHBIT_SET(ch) && isupper(ch))
- ch = tolower(ch);
+ ch = tolower_l(ch, global_lc_ctype);
result[i] = (char) ch;
}
result[i] = '\0';
diff --git a/src/backend/tsearch/ts_locale.c b/src/backend/tsearch/ts_locale.c
index b77d8c23d36..51ba3b41813 100644
--- a/src/backend/tsearch/ts_locale.c
+++ b/src/backend/tsearch/ts_locale.c
@@ -43,7 +43,7 @@ t_isalpha(const char *ptr)
char2wchar(character, WC_BUF_LEN, ptr, clen, mylocale);
- return iswalpha((wint_t) character[0]);
+ return iswalpha_l((wint_t) character[0], global_lc_ctype);
}
int
@@ -58,7 +58,7 @@ t_isalnum(const char *ptr)
char2wchar(character, WC_BUF_LEN, ptr, clen, mylocale);
- return iswalnum((wint_t) character[0]);
+ return iswalnum_l((wint_t) character[0], global_lc_ctype);
}
diff --git a/src/port/pgstrcasecmp.c b/src/port/pgstrcasecmp.c
index ec2b3a75c3d..f6dc6b0ff3b 100644
--- a/src/port/pgstrcasecmp.c
+++ b/src/port/pgstrcasecmp.c
@@ -28,6 +28,14 @@
#include <ctype.h>
+#ifndef FRONTEND
+extern PGDLLIMPORT locale_t global_lc_ctype;
+#define TOUPPER(x) toupper_l((unsigned char) (x), global_lc_ctype)
+#define TOLOWER(x) tolower_l((unsigned char) (x), global_lc_ctype)
+#else
+#define TOUPPER(x) toupper(x)
+#define TOLOWER(x) tolower(x)
+#endif
/*
* Case-independent comparison of two null-terminated strings.
@@ -45,12 +53,12 @@ pg_strcasecmp(const char *s1, const char *s2)
if (ch1 >= 'A' && ch1 <= 'Z')
ch1 += 'a' - 'A';
else if (IS_HIGHBIT_SET(ch1) && isupper(ch1))
- ch1 = tolower(ch1);
+ ch1 = TOLOWER(ch1);
if (ch2 >= 'A' && ch2 <= 'Z')
ch2 += 'a' - 'A';
else if (IS_HIGHBIT_SET(ch2) && isupper(ch2))
- ch2 = tolower(ch2);
+ ch2 = TOLOWER(ch2);
if (ch1 != ch2)
return (int) ch1 - (int) ch2;
@@ -78,12 +86,12 @@ pg_strncasecmp(const char *s1, const char *s2, size_t n)
if (ch1 >= 'A' && ch1 <= 'Z')
ch1 += 'a' - 'A';
else if (IS_HIGHBIT_SET(ch1) && isupper(ch1))
- ch1 = tolower(ch1);
+ ch1 = TOLOWER(ch1);
if (ch2 >= 'A' && ch2 <= 'Z')
ch2 += 'a' - 'A';
else if (IS_HIGHBIT_SET(ch2) && isupper(ch2))
- ch2 = tolower(ch2);
+ ch2 = TOLOWER(ch2);
if (ch1 != ch2)
return (int) ch1 - (int) ch2;
@@ -107,7 +115,7 @@ pg_toupper(unsigned char ch)
if (ch >= 'a' && ch <= 'z')
ch += 'A' - 'a';
else if (IS_HIGHBIT_SET(ch) && islower(ch))
- ch = toupper(ch);
+ ch = TOUPPER(ch);
return ch;
}
@@ -124,7 +132,7 @@ pg_tolower(unsigned char ch)
if (ch >= 'A' && ch <= 'Z')
ch += 'a' - 'A';
else if (IS_HIGHBIT_SET(ch) && isupper(ch))
- ch = tolower(ch);
+ ch = TOLOWER(ch);
return ch;
}
--
2.43.0