aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2019-06-14 12:28:21 +0000
committerdrh <drh@noemail.net>2019-06-14 12:28:21 +0000
commit060b7fa9745e1439ce1d9be96bb921b98b0a6da3 (patch)
tree0738531ef57d7578060ed206c959f346ba800f4f /src
parent4eb4e4fe7e1e60bbcb5009a43bb6278e0a81edff (diff)
downloadsqlite-060b7fa9745e1439ce1d9be96bb921b98b0a6da3.tar.gz
sqlite-060b7fa9745e1439ce1d9be96bb921b98b0a6da3.zip
Refactor the LIKE optimization decision logic so that it uses
sqlite3AtoF() on both boundary keys to determine if the optimization can be used when the LHS is something that might not have TEXT affinity. Ticket [ce8717f0885af975]. See also [c94369cae9b561b1], [b043a54c3de54b28], [fd76310a5e843e07], and [158290c0abafde67]. FossilOrigin-Name: b4a9e09e60213ccff925d09f0b6e549e2a3e3862856c710f108779e2867dec76
Diffstat (limited to 'src')
-rw-r--r--src/whereexpr.c41
1 files changed, 22 insertions, 19 deletions
diff --git a/src/whereexpr.c b/src/whereexpr.c
index db460652c..9ac940c5a 100644
--- a/src/whereexpr.c
+++ b/src/whereexpr.c
@@ -264,28 +264,31 @@ static int isLikeOrGlob(
zNew[iTo] = 0;
assert( iTo>0 );
- /* If the RHS begins with a digit, a +/- sign or whitespace, then the
- ** LHS must be an ordinary column (not a virtual table column) with
- ** TEXT affinity. Otherwise the LHS might be numeric and "lhs >= rhs"
- ** would be false even though "lhs LIKE rhs" is true. But if the RHS
- ** does not start with a digit or +/-, then "lhs LIKE rhs" will always
- ** be false if the LHS is numeric and so the optimization still works.
+ /* If the LHS is not an ordinary column with TEXT affinity, then the
+ ** pattern prefix boundaries (both the start and end boundaries) must
+ ** not look like a number. Otherwise the pattern might be treated as
+ ** a number, which will invalidate the LIKE optimization.
**
- ** 2018-09-10 ticket c94369cae9b561b1f996d0054bfab11389f9d033
- ** The RHS pattern must not be '/%' because the termination condition
- ** will then become "x<'0'" and if the affinity is numeric, will then
- ** be converted into "x<0", which is incorrect.
+ ** Getting this right has been a persistent source of bugs in the
+ ** LIKE optimization. See, for example:
+ ** 2018-09-10 https://sqlite.org/src/info/c94369cae9b561b1
+ ** 2019-05-02 https://sqlite.org/src/info/b043a54c3de54b28
+ ** 2019-06-10 https://sqlite.org/src/info/fd76310a5e843e07
+ ** 2019-06-14 https://sqlite.org/src/info/ce8717f0885af975
*/
- if( sqlite3Isdigit(zNew[0])
- || sqlite3Isspace(zNew[0])
- || zNew[0]=='-'
- || zNew[0]=='+'
- || zNew[iTo-1]=='0'-1
+ if( pLeft->op!=TK_COLUMN
+ || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
+ || IsVirtual(pLeft->y.pTab) /* Value might be numeric */
){
- if( pLeft->op!=TK_COLUMN
- || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
- || IsVirtual(pLeft->y.pTab) /* Value might be numeric */
- ){
+ int isNum;
+ double rDummy;
+ isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
+ if( isNum<=0 ){
+ zNew[iTo-1]++;
+ isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
+ zNew[iTo-1]--;
+ }
+ if( isNum>0 ){
sqlite3ExprDelete(db, pPrefix);
sqlite3ValueFree(pVal);
return 0;