From ca71131eebba63809ceb86be033a264a5f0a1d79 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 6 Oct 2022 11:08:56 -0400 Subject: [PATCH] Introduce t_isalnum() to replace t_isalpha() || t_isdigit() tests. ts_locale.c omitted support for "isalnum" tests, perhaps on the grounds that there were initially no use-cases for that. However, both ltree and pg_trgm need such tests, and we do also have one use-case now in the core backend. The workaround of testing isalpha and isdigit separately seems quite inefficient, especially when dealing with multibyte characters; so let's fill in the missing support. Discussion: https://postgr.es/m/2548310.1664999615@sss.pgh.pa.us --- contrib/ltree/ltree.h | 2 +- contrib/pg_trgm/trgm.h | 2 +- src/backend/tsearch/ts_locale.c | 16 ++++++++++++++++ src/backend/utils/adt/tsquery.c | 2 +- src/include/tsearch/ts_locale.h | 1 + 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/contrib/ltree/ltree.h b/contrib/ltree/ltree.h index 40aed0ca0c..6939d7349a 100644 --- a/contrib/ltree/ltree.h +++ b/contrib/ltree/ltree.h @@ -126,7 +126,7 @@ typedef struct #define LQUERY_HASNOT 0x01 -#define ISALNUM(x) ( t_isalpha(x) || t_isdigit(x) || ( pg_mblen(x) == 1 && t_iseq((x), '_') ) ) +#define ISALNUM(x) ( t_isalnum(x) || ( pg_mblen(x) == 1 && t_iseq((x), '_') ) ) /* full text query */ diff --git a/contrib/pg_trgm/trgm.h b/contrib/pg_trgm/trgm.h index 405a1d9552..afb0adb222 100644 --- a/contrib/pg_trgm/trgm.h +++ b/contrib/pg_trgm/trgm.h @@ -52,7 +52,7 @@ typedef char trgm[3]; } while(0) #ifdef KEEPONLYALNUM -#define ISWORDCHR(c) (t_isalpha(c) || t_isdigit(c)) +#define ISWORDCHR(c) (t_isalnum(c)) #define ISPRINTABLECHAR(a) ( isascii( *(unsigned char*)(a) ) && (isalnum( *(unsigned char*)(a) ) || *(unsigned char*)(a)==' ') ) #else #define ISWORDCHR(c) (!t_isspace(c)) diff --git a/src/backend/tsearch/ts_locale.c b/src/backend/tsearch/ts_locale.c index e0aa570bf5..fc21bf9ee8 100644 --- a/src/backend/tsearch/ts_locale.c +++ b/src/backend/tsearch/ts_locale.c @@ -81,6 +81,22 @@ t_isalpha(const char *ptr) return iswalpha((wint_t) character[0]); } +int +t_isalnum(const char *ptr) +{ + int clen = pg_mblen(ptr); + wchar_t character[WC_BUF_LEN]; + Oid collation = DEFAULT_COLLATION_OID; /* TODO */ + pg_locale_t mylocale = 0; /* TODO */ + + if (clen == 1 || lc_ctype_is_c(collation)) + return isalnum(TOUCHAR(ptr)); + + char2wchar(character, WC_BUF_LEN, ptr, clen, mylocale); + + return iswalnum((wint_t) character[0]); +} + int t_isprint(const char *ptr) { diff --git a/src/backend/utils/adt/tsquery.c b/src/backend/utils/adt/tsquery.c index f49e6bb157..a206926042 100644 --- a/src/backend/utils/adt/tsquery.c +++ b/src/backend/utils/adt/tsquery.c @@ -248,7 +248,7 @@ parse_or_operator(TSQueryParserState pstate) return false; /* it shouldn't be a part of any word */ - if (t_iseq(ptr, '-') || t_iseq(ptr, '_') || t_isalpha(ptr) || t_isdigit(ptr)) + if (t_iseq(ptr, '-') || t_iseq(ptr, '_') || t_isalnum(ptr)) return false; for (;;) diff --git a/src/include/tsearch/ts_locale.h b/src/include/tsearch/ts_locale.h index d14cb4ed26..10887290dc 100644 --- a/src/include/tsearch/ts_locale.h +++ b/src/include/tsearch/ts_locale.h @@ -42,6 +42,7 @@ typedef struct extern int t_isdigit(const char *ptr); extern int t_isspace(const char *ptr); extern int t_isalpha(const char *ptr); +extern int t_isalnum(const char *ptr); extern int t_isprint(const char *ptr); extern char *lowerstr(const char *str);