mirror of
https://github.com/sqlite/sqlite.git
synced 2025-10-22 22:13:04 +03:00
Slightly smaller and faster LIKE/GLOB comparison implementation.
FossilOrigin-Name: 5dddcc78eec5bcd0c7e8fe1b70875ce775488f0c
This commit is contained in:
37
src/func.c
37
src/func.c
@@ -567,10 +567,10 @@ static void total_changes(
|
||||
** A structure defining how to do GLOB-style comparisons.
|
||||
*/
|
||||
struct compareInfo {
|
||||
u8 matchAll;
|
||||
u8 matchOne;
|
||||
u8 matchSet;
|
||||
u8 noCase;
|
||||
u8 matchAll; /* "*" or "%" */
|
||||
u8 matchOne; /* "?" or "_" */
|
||||
u8 matchSet; /* "[" or 0 */
|
||||
u8 noCase; /* true to ignore case differences */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -633,22 +633,14 @@ static int patternCompare(
|
||||
const u8 *zPattern, /* The glob pattern */
|
||||
const u8 *zString, /* The string to compare against the glob */
|
||||
const struct compareInfo *pInfo, /* Information about how to do the compare */
|
||||
u32 esc /* The escape character */
|
||||
u32 matchOther /* The escape char (LIKE) or '[' (GLOB) */
|
||||
){
|
||||
u32 c, c2; /* Next pattern and input string chars */
|
||||
u32 matchOne = pInfo->matchOne; /* "?" or "_" */
|
||||
u32 matchAll = pInfo->matchAll; /* "*" or "%" */
|
||||
u32 matchOther; /* "[" or the escape character */
|
||||
u8 noCase = pInfo->noCase; /* True if uppercase==lowercase */
|
||||
const u8 *zEscaped = 0; /* One past the last escaped input char */
|
||||
|
||||
/* The GLOB operator does not have an ESCAPE clause. And LIKE does not
|
||||
** have the matchSet operator. So we either have to look for one or
|
||||
** the other, never both. Hence the single variable matchOther is used
|
||||
** to store the one we have to look for.
|
||||
*/
|
||||
matchOther = esc ? esc : pInfo->matchSet;
|
||||
|
||||
while( (c = Utf8Read(zPattern))!=0 ){
|
||||
if( c==matchAll ){ /* Match "*" */
|
||||
/* Skip over multiple "*" characters in the pattern. If there
|
||||
@@ -662,7 +654,7 @@ static int patternCompare(
|
||||
if( c==0 ){
|
||||
return 1; /* "*" at the end of the pattern matches */
|
||||
}else if( c==matchOther ){
|
||||
if( esc ){
|
||||
if( pInfo->matchSet==0 ){
|
||||
c = sqlite3Utf8Read(&zPattern);
|
||||
if( c==0 ) return 0;
|
||||
}else{
|
||||
@@ -670,7 +662,7 @@ static int patternCompare(
|
||||
** recursive search in this case, but it is an unusual case. */
|
||||
assert( matchOther<0x80 ); /* '[' is a single-byte character */
|
||||
while( *zString
|
||||
&& patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){
|
||||
&& patternCompare(&zPattern[-1],zString,pInfo,matchOther)==0 ){
|
||||
SQLITE_SKIP_UTF8(zString);
|
||||
}
|
||||
return *zString!=0;
|
||||
@@ -696,18 +688,18 @@ static int patternCompare(
|
||||
}
|
||||
while( (c2 = *(zString++))!=0 ){
|
||||
if( c2!=c && c2!=cx ) continue;
|
||||
if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
|
||||
if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1;
|
||||
}
|
||||
}else{
|
||||
while( (c2 = Utf8Read(zString))!=0 ){
|
||||
if( c2!=c ) continue;
|
||||
if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
|
||||
if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if( c==matchOther ){
|
||||
if( esc ){
|
||||
if( pInfo->matchSet==0 ){
|
||||
c = sqlite3Utf8Read(&zPattern);
|
||||
if( c==0 ) return 0;
|
||||
zEscaped = zPattern;
|
||||
@@ -760,7 +752,7 @@ static int patternCompare(
|
||||
** The sqlite3_strglob() interface.
|
||||
*/
|
||||
int sqlite3_strglob(const char *zGlobPattern, const char *zString){
|
||||
return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, 0)==0;
|
||||
return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[')==0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -798,9 +790,10 @@ static void likeFunc(
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const unsigned char *zA, *zB;
|
||||
u32 escape = 0;
|
||||
u32 escape;
|
||||
int nPat;
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
struct compareInfo *pInfo = sqlite3_user_data(context);
|
||||
|
||||
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_BLOB
|
||||
@@ -840,13 +833,13 @@ static void likeFunc(
|
||||
return;
|
||||
}
|
||||
escape = sqlite3Utf8Read(&zEsc);
|
||||
}else{
|
||||
escape = pInfo->matchSet;
|
||||
}
|
||||
if( zA && zB ){
|
||||
struct compareInfo *pInfo = sqlite3_user_data(context);
|
||||
#ifdef SQLITE_TEST
|
||||
sqlite3_like_count++;
|
||||
#endif
|
||||
|
||||
sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user