From bad3b3068d97c8acf68958176fa017d5033fe773 Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Mon, 7 Jun 1999 14:28:26 +0000 Subject: [PATCH] Repair recently-introduced error in makeIndexable for LIKE: a non-leading % would be put into the >=/<= patterns. Also, repair longstanding confusion about whether %% means a literal %%. The SQL92 doesn't say any such thing, and textlike() knows that, but gram.y didn't. --- src/backend/parser/gram.y | 37 ++++++++++++++++++++++++------------ src/backend/utils/adt/like.c | 6 ++++-- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index c038f43caae..bb36c6f0422 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.83 1999/05/22 05:06:43 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.84 1999/06/07 14:28:25 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -5357,6 +5357,7 @@ static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr) int pos, match_pos=0; bool found_special = false; + /* Cannot optimize if unquoted | { } is present in pattern */ for (pos = 1; n->val.val.str[pos]; pos++) { if (n->val.val.str[pos] == '|' || @@ -5367,12 +5368,16 @@ static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr) break; } if (n->val.val.str[pos] == '\\') + { pos++; + if (n->val.val.str[pos] == '\0') + break; + } } - /* skip leading ^ */ if (!found_special) { + /* note start at pos 1 to skip leading ^ */ for (pos = 1; n->val.val.str[pos]; pos++) { if (n->val.val.str[pos] == '.' || @@ -5383,9 +5388,11 @@ static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr) (strcmp(opname,"~*") == 0 && isalpha(n->val.val.str[pos]))) break; if (n->val.val.str[pos] == '\\') + { pos++; - if (n->val.val.str[pos] == '\0') - break; + if (n->val.val.str[pos] == '\0') + break; + } match_least[match_pos] = n->val.val.str[pos]; match_most[match_pos++] = n->val.val.str[pos]; } @@ -5430,16 +5437,22 @@ static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr) for (pos = 0; n->val.val.str[pos]; pos++) { - if (n->val.val.str[pos] == '%' && - n->val.val.str[pos+1] != '%') - break; - if(n->val.val.str[pos] == '_') + /* % and _ are wildcard characters in LIKE */ + if (n->val.val.str[pos] == '%' || + n->val.val.str[pos] == '_') break; - if (n->val.val.str[pos] == '\\' || - n->val.val.str[pos+1] == '%') + /* Backslash quotes the next character */ + if (n->val.val.str[pos] == '\\') + { pos++; - if (n->val.val.str[pos] == '\0') - break; + if (n->val.val.str[pos] == '\0') + break; + } + /* + * NOTE: this code used to think that %% meant a literal %, + * but textlike() itself does not think that, and the SQL92 + * spec doesn't say any such thing either. + */ match_least[match_pos] = n->val.val.str[pos]; match_most[match_pos++] = n->val.val.str[pos]; } diff --git a/src/backend/utils/adt/like.c b/src/backend/utils/adt/like.c index 14fc5314d0c..2d35bfabaca 100644 --- a/src/backend/utils/adt/like.c +++ b/src/backend/utils/adt/like.c @@ -111,7 +111,7 @@ textnlike(struct varlena * s, struct varlena * p) } -/* $Revision: 1.24 $ +/* $Revision: 1.25 $ ** "like.c" A first attempt at a LIKE operator for Postgres95. ** ** Originally written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986. @@ -191,7 +191,9 @@ DoMatch(pg_wchar * text, pg_wchar * p) else { /* End of input string. Do we have matching string remaining? */ - if (p[0] == '\0' || (p[0] == '%' && p[1] == '\0')) + while (*p == '%') /* allow multiple %'s at end of pattern */ + p++; + if (*p == '\0') return LIKE_TRUE; else return LIKE_ABORT; -- GitLab