From 07e8347221da207a6aeee86238af2aaf731ae358 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 11 Jan 2016 03:48:18 +0000 Subject: [PATCH] Slightly smaller and faster LIKE/GLOB comparison implementation. FossilOrigin-Name: 5dddcc78eec5bcd0c7e8fe1b70875ce775488f0c --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/func.c | 37 +++++++++++++++---------------------- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/manifest b/manifest index 45e5e88c6f..7a565aecb3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Typo\sfix\sin\sthe\sprevious\scommit. -D 2016-01-08T22:31:00.176 +C Slightly\ssmaller\sand\sfaster\sLIKE/GLOB\scomparison\simplementation. +D 2016-01-11T03:48:18.694 F Makefile.in 7c8cc4c2f0179efc6fa9492141d1fb65f4807054 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e45d8b9b56dfa3f2cd860b2c28bd9d304513b042 @@ -289,7 +289,7 @@ F src/delete.c 00af9f08a15ddc5cba5962d3d3e5bf2d67b2e7da F src/expr.c fe55c489362d1429c364e98c877514f4455f45a6 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c e18b3dff7d47c7bcac5ac4fc178a89b9fd322b44 -F src/func.c cf5e10af9125b245f1b962e8ba4d520a37818795 +F src/func.c ccaf46fa98f795673afbfab73dff7c18db88f3cd F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 @@ -1406,7 +1406,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 122c111e360761de8166e16ca151cb7260ee9bf8 -R 459dbc63e3c56e9f1bc36ac4dabf3593 +P 52c166039831cc8423e2252019ef64a21b9d7c2a +R b3c3f3b7322fc6b535d7f3bde12a066b U drh -Z 6b54e5c713520cd21bd942bd06142b38 +Z 4530f1ebb856a62f721161bd7860507a diff --git a/manifest.uuid b/manifest.uuid index 50a7a74425..fe0beaab78 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -52c166039831cc8423e2252019ef64a21b9d7c2a \ No newline at end of file +5dddcc78eec5bcd0c7e8fe1b70875ce775488f0c \ No newline at end of file diff --git a/src/func.c b/src/func.c index ad4cf73c31..45bbb35cd8 100644 --- a/src/func.c +++ b/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)); } }