staticint
MatchText(constchar *t, int tlen, constchar *p, int plen, pg_locale_t locale)
{ /* Fast path for match-everything pattern */ if (plen == 1 && *p == '%') return LIKE_TRUE;
/* Since this function recurses, it could be driven to stack overflow */
check_stack_depth();
/* *Inthisloop,weadvancebycharwhenmatchingwildcards(andthuson *recursiveentrytothisfunctionweareproperlychar-synced).Onother *occasionsitissafetoadvancebybyte,asthetextandpatternwill *beinlockstep.Thisallowsustoperformallcomparisonsbetweenthe *textandpatternonabytebybytebasis,evenformulti-byte *encodings.
*/ while (tlen > 0 && plen > 0)
{ if (*p == '\\')
{ /* Next pattern byte must match literally, whatever it is */
NextByte(p, plen); /* ... and there had better be one, per SQL standard */ if (plen <= 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE),
errmsg("LIKE pattern must not end with escape character"))); if (GETCHAR(*p, locale) != GETCHAR(*t, locale)) return LIKE_FALSE;
} elseif (*p == '%')
{ char firstpat;
while (plen > 0)
{ if (*p == '%')
NextByte(p, plen); elseif (*p == '_')
{ /* If not enough text left to match the pattern, ABORT */ if (tlen <= 0) return LIKE_ABORT;
NextChar(t, tlen);
NextByte(p, plen);
} else break; /* Reached a non-wildcard pattern char */
}
/* *Ifwe'reatendofpattern,match:wehaveatrailing%which *matchesanyremainingtextstring.
*/ if (plen <= 0) return LIKE_TRUE;
/* *Otherwise,scanforatextpositionatwhichwecanmatchthe *restofthepattern.Thefirstremainingpatterncharisknown *tobearegularorescapedliteralcharacter,sowecancompare *thefirstpatternbytetoeachtextbytetoavoidrecursing *morethanwehaveto.Thisfactalsoguaranteesthatwedon't *havetoconsideramatchtothezero-lengthsubstringatthe *endofthetext.Withanondeterministiccollation,wecan't *relyonthefirstbytesbeingequal,sowehavetorecursein *anycase.
*/ if (*p == '\\')
{ if (plen < 2)
ereport(ERROR,
(errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE),
errmsg("LIKE pattern must not end with escape character")));
firstpat = GETCHAR(p[1], locale);
} else
firstpat = GETCHAR(*p, locale);
while (tlen > 0)
{ if (GETCHAR(*t, locale) == firstpat || (locale && !locale->deterministic))
{ int matched = MatchText(t, tlen, p, plen, locale);
if (matched != LIKE_FALSE) return matched; /* TRUE or ABORT */
}
NextChar(t, tlen);
}
/* *Endoftextwithnomatch,sonopointintryinglaterplaces *tostartmatchingthispattern.
*/ return LIKE_ABORT;
} elseif (*p == '_')
{ /* _ matches any single character, and we know there is one */
NextChar(t, tlen);
NextByte(p, plen); continue;
} elseif (locale && !locale->deterministic)
{ /* *Fornondeterministiclocales,wefindthenextsubstringofthe *patternthatdoesnotcontainwildcardsandtrytofinda *matchingsubstringinthetext.Crucially,wecannotdothis *characterbycharacter,asinthenormalcase,butmustdoit *substringbysubstring,partitionedbythewildcardcharacters. *(ThisisperSQLstandard.)
*/ constchar *p1;
size_t p1len; constchar *t1;
size_t t1len; bool found_escape; constchar *subpat;
size_t subpatlen; char *buf = NULL;
/* *Determinenextsubstringofpatternwithoutwildcards.pis *thestartofthesubpattern,p1isonepastthelastbyte.Also *trackifwefoundanescapecharacter.
*/
p1 = p;
p1len = plen;
found_escape = false; while (p1len > 0)
{ if (*p1 == '\\')
{
found_escape = true;
NextByte(p1, p1len); if (p1len == 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE),
errmsg("LIKE pattern must not end with escape character")));
} elseif (*p1 == '_' || *p1 == '%') break;
NextByte(p1, p1len);
}
/* *Ifwefoundanescapecharacter,thenmakeanunescapedcopyof *thesubpattern.
*/ if (found_escape)
{ char *b;
b = buf = palloc(p1 - p); for (constchar *c = p; c < p1; c++)
{ if (*c == '\\')
; else
*(b++) = *c;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.