From: drh Date: Thu, 1 Dec 2016 18:49:40 +0000 (+0000) Subject: Faster version of patternCompare() that uses new return values rather than X-Git-Tag: version-3.16.0~86^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Fpattern-compare-optimization;p=thirdparty%2Fsqlite.git Faster version of patternCompare() that uses new return values rather than an extra parameter to communicate wildcard information back up to parent searches. FossilOrigin-Name: a1e2b6ce3af690ae91bda3d056357205c4018da7 --- diff --git a/manifest b/manifest index 8c10ea1dbf..b0f600d002 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Modify\sthe\spatternCompare()\sfunction\s(used\sfor\sGLOB,\sLIKE)\sto\sbetter\shandle\npatterns\scontaining\smultiple\swildcard\scharacters\s("*",\s"%"). -D 2016-12-01T17:34:59.799 +C Faster\sversion\sof\spatternCompare()\sthat\suses\snew\sreturn\svalues\srather\sthan\nan\sextra\sparameter\sto\scommunicate\swildcard\sinformation\sback\sup\sto\sparent\nsearches. +D 2016-12-01T18:49:40.948 F Makefile.in 7639c6a09da11a9c7c6f2630fc981ee588d1072d F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc b8ca53350ae545e3562403d5da2a69cec79308da @@ -344,7 +344,7 @@ F src/delete.c cac97d1117a3008934da3a6a587b3608e65e1495 F src/expr.c b22e09630f874c52db0770973b7ce55ee50c1dde F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c b9ca262f6ad4d030a3cab737ebf9b0b3c8b4ac80 -F src/func.c 528e92597efe1bb80b5dfc18184bd6cbf50d0cf9 +F src/func.c 43916c1d8e6da5d107d91d2b212577d4f69a876a F src/global.c 9da4ca5d74b90715f0ec4957f3d17a4749009f34 F src/hash.c 63d0ee752a3b92d4695b2b1f5259c4621b2cfebd F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4 @@ -1536,10 +1536,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d2d30914d81022d7d4e1670caf9326524520deaf -R e10a8ca94d0faea9fbbc7bdc7c3a49de -T *branch * pattern-compare-optimization -T *sym-pattern-compare-optimization * -T -sym-trunk * -U dan -Z 02660061daf6ca9953ba412794b057ac +P c5e5614d98a752738c081fecdd1e349a1a92b0e5 +R 7fd404505e6cb7c0d4a931aa83fe2cab +U drh +Z 7c186ec4fef5aa272b546661aa8fedfc diff --git a/manifest.uuid b/manifest.uuid index 9b8ba94419..b7832d7eab 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c5e5614d98a752738c081fecdd1e349a1a92b0e5 \ No newline at end of file +a1e2b6ce3af690ae91bda3d056357205c4018da7 \ No newline at end of file diff --git a/src/func.c b/src/func.c index 54f5df46aa..5b8ed6dd2b 100644 --- a/src/func.c +++ b/src/func.c @@ -598,9 +598,19 @@ static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 }; static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 }; /* -** Compare two UTF-8 strings for equality where the first string can -** potentially be a "glob" or "like" expression. Return true (1) if they -** are the same and false (0) if they are different. +** Possible error returns from patternMatch() +*/ +#define SQLITE_MATCH 0 +#define SQLITE_NOMATCH 1 +#define SQLITE_NOWILDCARDMATCH 2 + +/* +** Compare two UTF-8 strings for equality where the first string is +** a GLOB or LIKE expression. Return values: +** +** SQLITE_MATCH: Match +** SQLITE_NOMATCH: No match +** SQLITE_NOWILDCARDMATCH: No match in spite of having * or % wildcards. ** ** Globbing rules: ** @@ -636,8 +646,7 @@ 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 matchOther, /* The escape char (LIKE) or '[' (GLOB) */ - int *pbSeenMatchAll /* OUT: True if have seen matchAll */ + u32 matchOther /* The escape char (LIKE) or '[' (GLOB) */ ){ u32 c, c2; /* Next pattern and input string chars */ u32 matchOne = pInfo->matchOne; /* "?" or "_" */ @@ -650,30 +659,27 @@ static int patternCompare( /* Skip over multiple "*" characters in the pattern. If there ** are also "?" characters, skip those as well, but consume a ** single character of the input string for each "?" skipped */ - *pbSeenMatchAll = 1; while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){ if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){ - return 0; + return SQLITE_NOWILDCARDMATCH; } } if( c==0 ){ - return 1; /* "*" at the end of the pattern matches */ + return SQLITE_MATCH; /* "*" at the end of the pattern matches */ }else if( c==matchOther ){ if( pInfo->matchSet==0 ){ c = sqlite3Utf8Read(&zPattern); - if( c==0 ) return 0; + if( c==0 ) return SQLITE_NOWILDCARDMATCH; }else{ - int bMA = 0; /* True if patternCompare sees matchAll */ /* "[...]" immediately follows the "*". We have to do a slow ** 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,matchOther,&bMA)==0 - ){ - if( bMA ) return 0; + while( *zString ){ + int bMatch = patternCompare(&zPattern[-1],zString,pInfo,matchOther); + if( bMatch!=SQLITE_NOMATCH ) return bMatch; SQLITE_SKIP_UTF8(zString); } - return *zString!=0; + return SQLITE_NOWILDCARDMATCH; } } @@ -688,7 +694,7 @@ static int patternCompare( */ if( c<=0x80 ){ u32 cx; - int bMatchAll = 0; + int bMatch; if( noCase ){ cx = sqlite3Toupper(c); c = sqlite3Tolower(c); @@ -697,34 +703,30 @@ static int patternCompare( } while( (c2 = *(zString++))!=0 ){ if( c2!=c && c2!=cx ) continue; - if( patternCompare(zPattern,zString,pInfo,matchOther, &bMatchAll) ){ - return 1; - } - if( bMatchAll ) break; + bMatch = patternCompare(zPattern,zString,pInfo,matchOther); + if( bMatch!=SQLITE_NOMATCH ) return bMatch; } }else{ - int bMatchAll = 0; + int bMatch; while( (c2 = Utf8Read(zString))!=0 ){ if( c2!=c ) continue; - if( patternCompare(zPattern,zString,pInfo,matchOther, &bMatchAll) ){ - return 1; - } - if( bMatchAll ) break; + bMatch = patternCompare(zPattern,zString,pInfo,matchOther); + if( bMatch!=SQLITE_NOMATCH ) return bMatch; } } - return 0; + return SQLITE_NOWILDCARDMATCH; } if( c==matchOther ){ if( pInfo->matchSet==0 ){ c = sqlite3Utf8Read(&zPattern); - if( c==0 ) return 0; + if( c==0 ) return SQLITE_NOMATCH; zEscaped = zPattern; }else{ u32 prior_c = 0; int seen = 0; int invert = 0; c = sqlite3Utf8Read(&zString); - if( c==0 ) return 0; + if( c==0 ) return SQLITE_NOMATCH; c2 = sqlite3Utf8Read(&zPattern); if( c2=='^' ){ invert = 1; @@ -748,7 +750,7 @@ static int patternCompare( c2 = sqlite3Utf8Read(&zPattern); } if( c2==0 || (seen ^ invert)==0 ){ - return 0; + return SQLITE_NOMATCH; } continue; } @@ -759,25 +761,25 @@ static int patternCompare( continue; } if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue; - return 0; + return SQLITE_NOMATCH; } - return *zString==0; + return *zString==0 ? SQLITE_MATCH : SQLITE_NOMATCH; } /* -** The sqlite3_strglob() interface. +** The sqlite3_strglob() interface. Return 0 on a match (like strcmp()) and +** non-zero if there is no match. */ int sqlite3_strglob(const char *zGlobPattern, const char *zString){ - int dummy = 0; - return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[', &dummy)==0; + return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '['); } /* -** The sqlite3_strlike() interface. +** The sqlite3_strlike() interface. Return 0 on a match and non-zero for +** a miss - like strcmp(). */ int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){ - int dummy = 0; - return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc, &dummy)==0; + return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc); } /* @@ -855,11 +857,10 @@ static void likeFunc( escape = pInfo->matchSet; } if( zA && zB ){ - int dummy = 0; #ifdef SQLITE_TEST sqlite3_like_count++; #endif - sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape, &dummy)); + sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH); } }