Introduce t_isalnum() to replace t_isalpha() || t_isdigit() tests.
authorTom Lane <[email protected]>
Thu, 6 Oct 2022 15:08:56 +0000 (11:08 -0400)
committerTom Lane <[email protected]>
Thu, 6 Oct 2022 15:08:56 +0000 (11:08 -0400)
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
contrib/pg_trgm/trgm.h
src/backend/tsearch/ts_locale.c
src/backend/utils/adt/tsquery.c
src/include/tsearch/ts_locale.h

index 40aed0ca0c8a23bf32a00090d55e18699dafabb9..6939d7349a1bcb280d92df3ef7ead56a784804b1 100644 (file)
@@ -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 */
 
index 405a1d95528da0a80796810839ffa7176097f827..afb0adb222b9178fa6868c768a631699f7cfee07 100644 (file)
@@ -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))
index e0aa570bf5e60f17e05e50b4a79541662186f271..fc21bf9ee8e24879a48d10784cd39e5b278579b9 100644 (file)
@@ -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)
 {
index f49e6bb157871aa47f54556c8f28fd967fb55bf8..a206926042e35050f23bcb3284a881740027ce5e 100644 (file)
@@ -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 (;;)
index d14cb4ed26db3c50d0907696db29c80c4992832f..10887290dc27a8e2c81f577a5c6d6a038e77802f 100644 (file)
@@ -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);