v1-0004-tsearch-use-CASEFOLD-rather-than-LOWER.patch
text/x-patch
Filename: v1-0004-tsearch-use-CASEFOLD-rather-than-LOWER.patch
Type: text/x-patch
Part: 3
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-0004
Subject: tsearch: use CASEFOLD() rather than LOWER().
| File | + | − |
|---|---|---|
| src/backend/snowball/dict_snowball.c | 2 | 2 |
| src/backend/tsearch/dict_ispell.c | 2 | 2 |
| src/backend/tsearch/dict_simple.c | 2 | 2 |
| src/backend/tsearch/dict_synonym.c | 3 | 3 |
| src/backend/tsearch/spell.c | 3 | 3 |
From 7dfcc58e48baf9aa9a8fa6f41c0c94b1d6d16bae Mon Sep 17 00:00:00 2001
From: Jeff Davis <jeff@j-davis.com>
Date: Mon, 12 Jan 2026 09:24:16 -0800
Subject: [PATCH v1 4/4] tsearch: use CASEFOLD() rather than LOWER().
CASEFOLD() is better for case-insensitive matching in edge cases.
---
src/backend/snowball/dict_snowball.c | 4 ++--
src/backend/tsearch/dict_ispell.c | 4 ++--
src/backend/tsearch/dict_simple.c | 4 ++--
src/backend/tsearch/dict_synonym.c | 6 +++---
src/backend/tsearch/spell.c | 6 +++---
5 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/src/backend/snowball/dict_snowball.c b/src/backend/snowball/dict_snowball.c
index 182bd156995..cb2d3061953 100644
--- a/src/backend/snowball/dict_snowball.c
+++ b/src/backend/snowball/dict_snowball.c
@@ -251,7 +251,7 @@ dsnowball_init(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("multiple StopWords parameters")));
- readstoplist(defGetString(defel), &d->stoplist, str_tolower);
+ readstoplist(defGetString(defel), &d->stoplist, str_casefold);
stoploaded = true;
}
else if (strcmp(defel->defname, "language") == 0)
@@ -287,7 +287,7 @@ dsnowball_lexize(PG_FUNCTION_ARGS)
DictSnowball *d = (DictSnowball *) PG_GETARG_POINTER(0);
char *in = (char *) PG_GETARG_POINTER(1);
int32 len = PG_GETARG_INT32(2);
- char *txt = str_tolower(in, len, DEFAULT_COLLATION_OID);
+ char *txt = str_casefold(in, len, DEFAULT_COLLATION_OID);
TSLexeme *res = palloc0_array(TSLexeme, 2);
/*
diff --git a/src/backend/tsearch/dict_ispell.c b/src/backend/tsearch/dict_ispell.c
index ad5c26ebccb..bdcfc836e80 100644
--- a/src/backend/tsearch/dict_ispell.c
+++ b/src/backend/tsearch/dict_ispell.c
@@ -79,7 +79,7 @@ dispell_init(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("multiple StopWords parameters")));
- readstoplist(defGetString(defel), &(d->stoplist), str_tolower);
+ readstoplist(defGetString(defel), &(d->stoplist), str_casefold);
stoploaded = true;
}
else
@@ -128,7 +128,7 @@ dispell_lexize(PG_FUNCTION_ARGS)
if (len <= 0)
PG_RETURN_POINTER(NULL);
- txt = str_tolower(in, len, DEFAULT_COLLATION_OID);
+ txt = str_casefold(in, len, DEFAULT_COLLATION_OID);
res = NINormalizeWord(&(d->obj), txt);
if (res == NULL)
diff --git a/src/backend/tsearch/dict_simple.c b/src/backend/tsearch/dict_simple.c
index 44d945b2be8..52df5251e20 100644
--- a/src/backend/tsearch/dict_simple.c
+++ b/src/backend/tsearch/dict_simple.c
@@ -48,7 +48,7 @@ dsimple_init(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("multiple StopWords parameters")));
- readstoplist(defGetString(defel), &d->stoplist, str_tolower);
+ readstoplist(defGetString(defel), &d->stoplist, str_casefold);
stoploaded = true;
}
else if (strcmp(defel->defname, "accept") == 0)
@@ -81,7 +81,7 @@ dsimple_lexize(PG_FUNCTION_ARGS)
char *txt;
TSLexeme *res;
- txt = str_tolower(in, len, DEFAULT_COLLATION_OID);
+ txt = str_casefold(in, len, DEFAULT_COLLATION_OID);
if (*txt == '\0' || searchstoplist(&(d->stoplist), txt))
{
diff --git a/src/backend/tsearch/dict_synonym.c b/src/backend/tsearch/dict_synonym.c
index 6dee28ae525..b5ff8c23cab 100644
--- a/src/backend/tsearch/dict_synonym.c
+++ b/src/backend/tsearch/dict_synonym.c
@@ -185,8 +185,8 @@ dsynonym_init(PG_FUNCTION_ARGS)
}
else
{
- d->syn[cur].in = str_tolower(starti, strlen(starti), DEFAULT_COLLATION_OID);
- d->syn[cur].out = str_tolower(starto, strlen(starto), DEFAULT_COLLATION_OID);
+ d->syn[cur].in = str_casefold(starti, strlen(starti), DEFAULT_COLLATION_OID);
+ d->syn[cur].out = str_casefold(starto, strlen(starto), DEFAULT_COLLATION_OID);
}
d->syn[cur].outlen = strlen(starto);
@@ -226,7 +226,7 @@ dsynonym_lexize(PG_FUNCTION_ARGS)
if (d->case_sensitive)
key.in = pnstrdup(in, len);
else
- key.in = str_tolower(in, len, DEFAULT_COLLATION_OID);
+ key.in = str_casefold(in, len, DEFAULT_COLLATION_OID);
key.out = NULL;
diff --git a/src/backend/tsearch/spell.c b/src/backend/tsearch/spell.c
index e3436dbddd2..e946b88f38b 100644
--- a/src/backend/tsearch/spell.c
+++ b/src/backend/tsearch/spell.c
@@ -170,7 +170,7 @@ cpstrdup(IspellDict *Conf, const char *str)
/*
- * Apply str_tolower(), producing a temporary result (in the buildCxt).
+ * Apply str_casefold(), producing a temporary result (in the buildCxt).
*/
static char *
lowerstr_ctx(IspellDict *Conf, const char *src)
@@ -179,7 +179,7 @@ lowerstr_ctx(IspellDict *Conf, const char *src)
char *dst;
saveCtx = MemoryContextSwitchTo(Conf->buildCxt);
- dst = str_tolower(src, strlen(src), DEFAULT_COLLATION_OID);
+ dst = str_casefold(src, strlen(src), DEFAULT_COLLATION_OID);
MemoryContextSwitchTo(saveCtx);
return dst;
@@ -1453,7 +1453,7 @@ NIImportAffixes(IspellDict *Conf, const char *filename)
while ((recoded = tsearch_readline(&trst)) != NULL)
{
- pstr = str_tolower(recoded, strlen(recoded), DEFAULT_COLLATION_OID);
+ pstr = str_casefold(recoded, strlen(recoded), DEFAULT_COLLATION_OID);
/* Skip comments and empty lines */
if (*pstr == '#' || *pstr == '\n')
--
2.43.0