-C Fix\sthe\sLIKE\soptimization\seven\swhen\scomparing\smixed-case\sBLOBs.
-D 2015-03-06T19:47:38.505
+C Test\scases\sadded.\s\sComments\sfixed.\s\sProposed\ssolution\sfor\nticket\s[05f43be8fdda9fbd9].
+D 2015-03-06T20:49:52.770
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2f643d6968dfc0b82d2e546a0525a39079f9e928
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e
F src/vacuum.c 9460b9de7b2d4e34b0d374894aa6c8a0632be8ec
-F src/vdbe.c 6bee3b85a2f013a8fdc496996089d3b6bedfb525
+F src/vdbe.c c9f4ad2c62bccebed38b1fd253064ed2a2c659ae
F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3
F src/vdbeInt.h bb56fd199d8af1a2c1b9639ee2f70724b4338e3a
F src/vdbeapi.c dac0d0d8009a8aa549cd77d9c29da44c0344f0c4
F src/wal.c 39303f2c9db02a4e422cd8eb2c8760420c6a51fe
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
-F src/where.c cace7eef1838ea22f549e824236eaaa4195b83e6
+F src/where.c 8cd4fc29addda0945b28b1f849a7998e3749d8b9
F src/whereInt.h cbe4aa57326998d89e7698ca65bb7c28541d483c
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
F test/analyze.test 1772936d66471c65221e437b6d1999c3a03166c4
-F test/analyze3.test bf41f0f680dd1e0d44eed5e769531e93a5320275
+F test/analyze3.test 75b9e42ea1e4edc919250450dc5762186965d4e6
F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213
F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
-F test/like.test e191e536d0fcd722a6b965e7cd1ee0bfd12a5991
+F test/like.test 4f2a71d36a536233727f71995fef900756705e56
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
+F test/like3.test 9c85587224f739c81b51d8cdd2727c11ec678526
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
F test/loadext.test 648cb95f324d1775c54a55c12271b2d1156b633b
F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
F test/where7.test 5a4b0abc207d71da4deecd734ad8579e8dd40aa8
-F test/where8.test 806f1dcec4088be2b826b33f757fe6e17c3236a1
+F test/where8.test 2eafe74e01cc10355985874e1ff868ac03dbae5e
F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739
F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2
F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 5757e803cb5759b476bbc6453c58340089611420
-R 1a18426c5e280ce5513288eef4bf379e
+P a58aafdb4e1422b6a8ffc07a67984928bbedf919
+R d75eaf03976986bf457292a7b369e1ff
U drh
-Z 4902bd060fa099614e1fc5278ee9e5b6
+Z 9b58e75e5227e2cbfcfb68532871937f
-a58aafdb4e1422b6a8ffc07a67984928bbedf919
\ No newline at end of file
+6b993bd54035b67f4d84941e3f444ca79b7feee1
\ No newline at end of file
** The string value P4 of length P1 (bytes) is stored in register P2.
**
** If P5!=0 and the content of register P3 is greater than zero, then
-** the datatype of the register P2 is convert to BLOB. The content is
-** the same string text, it is merely interpreted as a BLOB as if it
-** had been CAST.
+** the datatype of the register P2 is converted to BLOB. The content is
+** the same sequence of bytes, it is merely interpreted as a BLOB instead
+** of a string, as if it had been CAST.
*/
case OP_String: { /* out2-prerelease */
assert( pOp->p4.z!=0 );
Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */
Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */
int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */
- int noCase = 0; /* LIKE/GLOB distinguishes case */
+ int noCase = 0; /* uppercase equivalent to lowercase */
int op; /* Top-level operator. pExpr->op */
Parse *pParse = pWInfo->pParse; /* Parsing context */
sqlite3 *db = pParse->db; /* Database connection */
/* Add constraints to reduce the search space on a LIKE or GLOB
** operator.
**
- ** A like pattern of the form "x LIKE 'abc%'" is changed into constraints
+ ** A like pattern of the form "x LIKE 'aBc%'" is changed into constraints
**
- ** x>='abc' AND x<'abd' AND x LIKE 'abc%'
+ ** x>='ABC' AND x<'abd' AND x LIKE 'aBc%'
**
** The last character of the prefix "abc" is incremented to form the
- ** termination condition "abd".
+ ** termination condition "abd". If case is not significant (the default
+ ** for LIKE) then the lower-bound is made all uppercase and the upper-
+ ** bound is made all lowercase so that the bounds also work when comparing
+ ** BLOBs.
*/
if( pWC->op==TK_AND
&& isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
Token sCollSeqName; /* Name of collating sequence */
const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC;
- pTerm->wtFlags |= TERM_LIKE;
pLeft = pExpr->x.pList->a[1].pExpr;
pStr2 = sqlite3ExprDup(db, pStr1, 0);
if( noCase && !pParse->db->mallocFailed ){
int i;
char c;
+ pTerm->wtFlags |= TERM_LIKE;
for(i=0; (c = pStr1->u.zToken[i])!=0; i++){
pStr1->u.zToken[i] = sqlite3Toupper(c);
pStr2->u.zToken[i] = sqlite3Tolower(c);
** and child2 terms were added by the LIKE optimization. If both of
** the virtual child terms are valid, then testing of the parent can be
** skipped.
+**
+** Usually the parent term is marked as TERM_CODED. But if the parent
+** term was originally TERM_LIKE, then the parent gets TERM_LIKECOND instead.
+** The TERM_LIKECOND marking indicates that the term should be coded inside
+** a conditional such that is only evaluated on the second pass of a
+** LIKE-optimization loop, when scanning BLOBs instead of strings.
*/
static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
int nLoop = 0;
do_test analyze3-2.4 {
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE 'a%' }
-} {101 0 100}
+} {102 0 100}
do_test analyze3-2.5 {
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE '%a' }
} {999 999 100}
-do_test analyze3-2.4 {
+do_test analyze3-2.6 {
set like "a%"
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
-} {101 0 100}
-do_test analyze3-2.5 {
+} {102 0 100}
+do_test analyze3-2.7 {
set like "%a"
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
} {999 999 100}
-do_test analyze3-2.6 {
+do_test analyze3-2.8 {
set like "a"
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
-} {101 0 0}
-do_test analyze3-2.7 {
+} {102 0 0}
+do_test analyze3-2.9 {
set like "ab"
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
-} {11 0 0}
-do_test analyze3-2.8 {
+} {12 0 0}
+do_test analyze3-2.10 {
set like "abc"
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
-} {2 0 1}
-do_test analyze3-2.9 {
+} {3 0 1}
+do_test analyze3-2.11 {
set like "a_c"
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
-} {101 0 10}
+} {102 0 10}
#-------------------------------------------------------------------------
count {
SELECT a FROM t10 WHERE f LIKE '12%' ORDER BY +a;
}
- } {12 123 scan 3 like 0}
+ } {12 123 scan 4 like 0}
do_test like-10.6 {
count {
SELECT a FROM t10 WHERE a LIKE '12%' ORDER BY +a;
count {
SELECT a FROM t10b WHERE f GLOB '12*' ORDER BY +a;
}
- } {12 123 scan 3 like 0}
+ } {12 123 scan 4 like 0}
do_test like-10.15 {
count {
SELECT a FROM t10b WHERE a GLOB '12*' ORDER BY +a;
--- /dev/null
+# 2015-03-06
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# This file implements regression tests for SQLite library. The
+# focus of this file is testing the LIKE and GLOB operators and
+# in particular the optimizations that occur to help those operators
+# run faster and that those optimizations work correctly when there
+# are both strings and blobs being tested.
+#
+# Ticket 05f43be8fdda9fbd948d374319b99b054140bc36 shows that the following
+# SQL was not working correctly:
+#
+# CREATE TABLE t1(x TEXT UNIQUE COLLATE nocase);
+# INSERT INTO t1(x) VALUES(x'616263');
+# SELECT 'query-1', x FROM t1 WHERE x LIKE 'a%';
+# SELECT 'query-2', x FROM t1 WHERE +x LIKE 'a%';
+#
+# This script verifies that it works right now.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_execsql_test like3-1.1 {
+ PRAGMA encoding=UTF8;
+ CREATE TABLE t1(a,b TEXT COLLATE nocase);
+ INSERT INTO t1(a,b)
+ VALUES(1,'abc'),
+ (2,'ABX'),
+ (3,'BCD'),
+ (4,x'616263'),
+ (5,x'414258'),
+ (6,x'424344');
+ CREATE INDEX t1ba ON t1(b,a);
+
+ SELECT a, b FROM t1 WHERE b LIKE 'aB%' ORDER BY +a;
+} {1 abc 2 ABX 4 abc 5 ABX}
+do_execsql_test like3-1.2 {
+ SELECT a, b FROM t1 WHERE +b LIKE 'aB%' ORDER BY +a;
+} {1 abc 2 ABX 4 abc 5 ABX}
+
+do_execsql_test like3-1.3 {
+ CREATE TABLE t2(a, b TEXT);
+ INSERT INTO t2 SELECT a, b FROM t1;
+ CREATE INDEX t2ba ON t2(b,a);
+ SELECT a, b FROM t2 WHERE b GLOB 'ab*' ORDER BY +a;
+} {1 abc 4 abc}
+do_execsql_test like3-1.4 {
+ SELECT a, b FROM t2 WHERE +b GLOB 'ab*' ORDER BY +a;
+} {1 abc 4 abc}
+
+finish_test
do_test where8-1.4 {
execsql_status2 { SELECT c FROM t1 WHERE a > 8 OR b GLOB 't*' }
-} {IX X III II 0 0 9}
+} {IX X III II 0 0 10}
do_test where8-1.5 {
execsql_status2 { SELECT c FROM t1 WHERE a > 8 OR b GLOB 'f*' }
-} {IX X V IV 0 0 9}
+} {IX X V IV 0 0 10}
do_test where8-1.6 {
execsql_status { SELECT c FROM t1 WHERE a = 1 OR b = 'three' ORDER BY rowid }