From 3f82ad436deaf81218dc4b4898f6d6edb3005c78 Mon Sep 17 00:00:00 2001 From: jian he Date: Mon, 18 Nov 2024 11:06:17 +0800 Subject: [PATCH v8 1/1] LIKE with nondeterministic collations no trailing wild cards optimize where there is no trailing wildcards. --- src/backend/utils/adt/like_match.c | 38 ++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/backend/utils/adt/like_match.c b/src/backend/utils/adt/like_match.c index f3ca4d3082..dd1b136255 100644 --- a/src/backend/utils/adt/like_match.c +++ b/src/backend/utils/adt/like_match.c @@ -212,6 +212,7 @@ MatchText(const char *t, int tlen, const char *p, int plen, pg_locale_t locale) const char *t1; size_t t1len; bool found_escape; + bool trailing_wildcards = false; const char *subpat; size_t subpatlen; char *buf = NULL; @@ -279,7 +280,33 @@ MatchText(const char *t, int tlen, const char *p, int plen, pg_locale_t locale) CHECK_FOR_INTERRUPTS(); - cmp = pg_strncoll(subpat, subpatlen, t, (t1 - t), locale); + if (!trailing_wildcards) + { + /* we check subpatlen and next character is wild-card or + * not. if subpatlen == 1, then we don't have to check the + * next char. if we didn't found trailing_wildcards then we can + * safely compare whole subpat with t. if cmp != 0 we return + * LIKE_FALSE. + */ + if (subpatlen == 1 && (subpat[0] == '%' || subpat[0] == '_')) + { + trailing_wildcards = true; + break; + } + for (int i = 0; i <=subpatlen; i++) + { + if (subpat[i] == '%' || subpat[i] == '_') + { + trailing_wildcards = true; + break; + } + } + } + + if (!trailing_wildcards) + cmp = pg_strncoll(subpat, subpatlen, t, tlen, locale); + else + cmp = pg_strncoll(subpat, subpatlen, t, (t1 - t), locale); /* * If we found a match, we have to test if the rest of pattern @@ -299,7 +326,12 @@ MatchText(const char *t, int tlen, const char *p, int plen, pg_locale_t locale) */ if (cmp == 0) { - int matched = MatchText(t1, t1len, p1, p1len, locale); + int matched; + + if (!trailing_wildcards) + return LIKE_TRUE; + + matched = MatchText(t1, t1len, p1, p1len, locale); if (matched == LIKE_TRUE) { @@ -308,6 +340,8 @@ MatchText(const char *t, int tlen, const char *p, int plen, pg_locale_t locale) return matched; } } + else if (!trailing_wildcards) + return LIKE_FALSE; /* * Didn't match. If we used up the whole text, then the match -- 2.34.1