]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Cherrypick the changes for enhancement requests [e090183531fc27474]
authordrh <drh@noemail.net>
Tue, 17 Aug 2010 23:13:41 +0000 (23:13 +0000)
committerdrh <drh@noemail.net>
Tue, 17 Aug 2010 23:13:41 +0000 (23:13 +0000)
(use indices on LIKE with no wildcards) and [4711020446da7d93d993]
(use nocase index for LIKE even if the column is binary) into the
3.6.23.1 release of the Apple-OSX branch.

FossilOrigin-Name: 220cca50da08c5166afa3d2364fdf7f8e7308836

manifest
manifest.uuid
src/expr.c
src/parse.y
src/sqliteInt.h
src/where.c
test/analyze3.test
test/like.test

index eaa5aa7a3be50304acc13794ed721c44fda8250d..09ff4bd59068e1beab8891ac995b60a37534b058 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,8 +1,8 @@
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
-C Merge\sin\schanges\sup\sto\sand\sincluding\sthe\s3.6.23.1\srelease.
-D 2010-06-16T19:48:57
+C Cherrypick\sthe\schanges\sfor\senhancement\srequests\s[e090183531fc27474]\s\n(use\sindices\son\sLIKE\swith\sno\swildcards)\sand\s[4711020446da7d93d993]\n(use\snocase\sindex\sfor\sLIKE\seven\sif\sthe\scolumn\sis\sbinary)\sinto\sthe\n3.6.23.1\srelease\sof\sthe\sApple-OSX\sbranch.
+D 2010-08-17T23:13:42
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in b12be4429b75eca982a5646752652efde58e8f29
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -124,7 +124,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
 F src/ctime.c ceb247eb31620bba66a94c3f697db489a1652353
 F src/date.c 485a4409a384310e6d93fd1104a9d0a8658becd9
 F src/delete.c 610dc008e88a9599f905f5cbe9577ac9c36e0581
-F src/expr.c 6baed2a0448d494233d9c0a610eea018ab386a32
+F src/expr.c 6bb1f6a7213061c325b679c3aa0aa2358094ad7f
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
 F src/fkey.c e2116672a6bd610dc888e27df292ebc7999c9bb0
 F src/func.c cc68e721c25b9ad0d5c2d9e173298cfc1818fe4c
@@ -160,7 +160,7 @@ F src/os_unix.c fdeb37c703243141470396acf32331674b905e55
 F src/os_win.c bc65553f911439a6b1aa3cf22f34e5ea1c4aa394
 F src/pager.c e39ac887694a6644135f5e4151fe293b5397dd64
 F src/pager.h 1b32faf2e578ac3e7bcf9c9d11217128261c5c54
-F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e
+F src/parse.y 07fdc757efdb43bac77120f3b50db15d5fe7f5db
 F src/pcache.c 4956b41d6ba913f7a8a56fbf32be78caed0e45c2
 F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
 F src/pcache1.c 2bb2261190b42a348038f5b1c285c8cef415fcc8
@@ -174,7 +174,7 @@ F src/select.c 4113ef360430ed4e7533690ef46d06c20204adce
 F src/shell.c c40427c7245535a04a9cb4a417b6cc05c022e6a4
 F src/sqlite.h.in f9a9be1bce911669a259f7c747bf05635cb360b5
 F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
-F src/sqliteInt.h 6873f7f4c24fcdceece8777f2a1cbec049df77a0
+F src/sqliteInt.h 4ac68f515068deb0435b8e4de46844368e95018a
 F src/sqliteLimit.h 3afab2291762b5d09ae20c18feb8e9fa935a60a6
 F src/status.c d329385a2cba3ea49d9d68af0ad84b22d46b4f40
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -227,7 +227,7 @@ F src/vdbemem.c 2a82f455f6ca6f78b59fb312f96054c04ae0ead1
 F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
 F src/vtab.c 606adf51cd6d4ba51a8c6dccede06a6f7b0dd72d
 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
-F src/where.c 399ea4c090284c9d16f76d685b9b44e8b9b4442b
+F src/where.c 0777e1f8f1cd88ce37da41d6bbd54b8307705ee4
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
 F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45
@@ -238,7 +238,7 @@ F test/alter4.test 9386ffd1e9c7245f43eca412b2058d747509cc1f
 F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
 F test/analyze.test ad5329098fe4de4a96852231d53e3e9e6283ad4b
 F test/analyze2.test a2ad7b0a4e13801ee3968fe70f22aff52326569c
-F test/analyze3.test 506203875258ffd8ffa879b9c3c5432022d2b6d8
+F test/analyze3.test 535bf0762f49fa96885efe8568738276c2204a2a
 F test/async.test 8c75d31b8330f8b70cf2571b014d4476a063efdb
 F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
 F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
@@ -468,7 +468,7 @@ F test/jrnlmode3.test cfcdb12b90e640a23b92785a002d96c0624c8710
 F test/keyword1.test a2400977a2e4fde43bf33754c2929fda34dbca05
 F test/lastinsert.test 474d519c68cb79d07ecae56a763aa7f322c72f51
 F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
-F test/like.test 4b594af9eddfd01018df1e9b1d18721aff619fa7
+F test/like.test 565d240313f15a8afa8d7098dc9fe303c1e2a496
 F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
 F test/limit.test 2db7b3b34fb925b8e847d583d2eb67531d0ce67e
 F test/loadext.test 0393ce12d9616aa87597dd0ec88181de181f6db0
@@ -799,14 +799,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 5c0afe70a5ee2b378896bf30426823dc5ae4e95c 776679af588625f13307369770979bccae7cf03a
-R 90e27fcea4f7f54474c3a0fb8671dd73
+P 21ca87f69125a9e7124c6ddc566d17f64661b0d3
+R 746b72865ced8034924c2cc1c718a49c
 U drh
-Z b8746f44feb03a04fe1e2272410b2363
+Z bb87ab062eae07f981b513eb1b914158
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.6 (GNU/Linux)
 
-iD8DBQFMGSqsoxKgR168RlERAtaeAJwOjCShd/QM6A+bZt7Sd1NRZQnhYgCdEZRm
-OPl6AbsNdGPQiQAPLtVWZiQ=
-=hX2q
+iD8DBQFMaxeqoxKgR168RlERAsD4AJ9c9h3cETIYGap5CjJMrATUO3T+cACgjLkN
+T2aAsvx2yasC+G+Gv6NOb3E=
+=s+Bg
 -----END PGP SIGNATURE-----
index c09111da5920b69831e0dd16919023a53d973273..0c2661ac3874a7262da2096e4ccff6a524a16185 100644 (file)
@@ -1 +1 @@
-21ca87f69125a9e7124c6ddc566d17f64661b0d3
\ No newline at end of file
+220cca50da08c5166afa3d2364fdf7f8e7308836
\ No newline at end of file
index 034088fafcefb70be2b0f4040b0d9c261c372200..97a589b5574d9ab79af343c577318284a925fb2c 100644 (file)
@@ -55,6 +55,18 @@ char sqlite3ExprAffinity(Expr *pExpr){
   return pExpr->affinity;
 }
 
+/*
+** Set the explicit collating sequence for an expression to the
+** collating sequence supplied in the second argument.
+*/
+Expr *sqlite3ExprSetColl(Expr *pExpr, CollSeq *pColl){
+  if( pExpr && pColl ){
+    pExpr->pColl = pColl;
+    pExpr->flags |= EP_ExpCollate;
+  }
+  return pExpr;
+}
+
 /*
 ** Set the collating sequence for expression pExpr to be the collating
 ** sequence named by pToken.   Return a pointer to the revised expression.
@@ -62,18 +74,13 @@ char sqlite3ExprAffinity(Expr *pExpr){
 ** flag.  An explicit collating sequence will override implicit
 ** collating sequences.
 */
-Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pCollName){
+Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr *pExpr, Token *pCollName){
   char *zColl = 0;            /* Dequoted name of collation sequence */
   CollSeq *pColl;
   sqlite3 *db = pParse->db;
   zColl = sqlite3NameFromToken(db, pCollName);
-  if( pExpr && zColl ){
-    pColl = sqlite3LocateCollSeq(pParse, zColl);
-    if( pColl ){
-      pExpr->pColl = pColl;
-      pExpr->flags |= EP_ExpCollate;
-    }
-  }
+  pColl = sqlite3LocateCollSeq(pParse, zColl);
+  sqlite3ExprSetColl(pExpr, pColl);
   sqlite3DbFree(db, zColl);
   return pExpr;
 }
index 98714ee343ab7092f4a43c67d86d3a321928777f..deac2a214c2850841ca081321e938d07be7ebacc 100644 (file)
@@ -780,7 +780,7 @@ expr(A) ::= VARIABLE(X).     {
   spanSet(&A, &X, &X);
 }
 expr(A) ::= expr(E) COLLATE ids(C). {
-  A.pExpr = sqlite3ExprSetColl(pParse, E.pExpr, &C);
+  A.pExpr = sqlite3ExprSetCollByToken(pParse, E.pExpr, &C);
   A.zStart = E.zStart;
   A.zEnd = &C.z[C.n];
 }
@@ -1091,7 +1091,7 @@ idxlist(A) ::= idxlist(X) COMMA nm(Y) collate(C) sortorder(Z).  {
   Expr *p = 0;
   if( C.n>0 ){
     p = sqlite3Expr(pParse->db, TK_COLUMN, 0);
-    sqlite3ExprSetColl(pParse, p, &C);
+    sqlite3ExprSetCollByToken(pParse, p, &C);
   }
   A = sqlite3ExprListAppend(pParse,X, p);
   sqlite3ExprListSetName(pParse,A,&Y,1);
@@ -1102,7 +1102,7 @@ idxlist(A) ::= nm(Y) collate(C) sortorder(Z). {
   Expr *p = 0;
   if( C.n>0 ){
     p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
-    sqlite3ExprSetColl(pParse, p, &C);
+    sqlite3ExprSetCollByToken(pParse, p, &C);
   }
   A = sqlite3ExprListAppend(pParse,0, p);
   sqlite3ExprListSetName(pParse, A, &Y, 1);
index 5720b9cf5cf2bb0687cb0437cbdc4e652cb305e2..5b718e26b244dc18f1d2d7d7b63494ef2c9efa2f 100644 (file)
@@ -2847,7 +2847,8 @@ int sqlite3ReadSchema(Parse *pParse);
 CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
 CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
 CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
-Expr *sqlite3ExprSetColl(Parse *pParse, Expr *, Token *);
+Expr *sqlite3ExprSetColl(Expr*, CollSeq*);
+Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr*, Token*);
 int sqlite3CheckCollSeq(Parse *, CollSeq *);
 int sqlite3CheckObjectName(Parse *, const char *);
 void sqlite3VdbeSetChanges(sqlite3 *, int);
index 5f81ce07686754dbdc4e90bb16576342f51cdd9e..d52b1dbf1d8bc732f4bda58736d7725c3030afb2 100644 (file)
@@ -633,7 +633,6 @@ static int isLikeOrGlob(
   int c;                     /* One character in z[] */
   int cnt;                   /* Number of non-wildcard prefix characters */
   char wc[3];                /* Wildcard characters */
-  CollSeq *pColl;            /* Collating sequence for LHS */
   sqlite3 *db = pParse->db;  /* Database connection */
   sqlite3_value *pVal = 0;
   int op;                    /* Opcode of pRight */
@@ -652,19 +651,6 @@ static int isLikeOrGlob(
     return 0;
   }
   assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */
-  pColl = sqlite3ExprCollSeq(pParse, pLeft);
-  if( pColl==0 ) return 0;  /* Happens when LHS has an undefined collation */
-  if( (pColl->type!=SQLITE_COLL_BINARY || *pnoCase) &&
-      (pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){
-    /* IMP: R-09003-32046 For the GLOB operator, the column must use the
-    ** default BINARY collating sequence.
-    ** IMP: R-41408-28306 For the LIKE operator, if case_sensitive_like mode
-    ** is enabled then the column must use the default BINARY collating
-    ** sequence, or if case_sensitive_like mode is disabled then the column
-    ** must use the built-in NOCASE collating sequence.
-    */
-    return 0;
-  }
 
   pRight = pList->a[0].pExpr;
   op = pRight->op;
@@ -687,9 +673,9 @@ static int isLikeOrGlob(
     while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
       cnt++;
     }
-    if( cnt!=0 && c!=0 && 255!=(u8)z[cnt-1] ){
+    if( cnt!=0 && 255!=(u8)z[cnt-1] ){
       Expr *pPrefix;
-      *pisComplete = z[cnt]==wc[0] && z[cnt+1]==0;
+      *pisComplete = c==wc[0] && z[cnt+1]==0;
       pPrefix = sqlite3Expr(db, TK_STRING, z);
       if( pPrefix ) pPrefix->u.zToken[cnt] = 0;
       *ppPrefix = pPrefix;
@@ -1244,6 +1230,7 @@ static void exprAnalyze(
     Expr *pNewExpr2;
     int idxNew1;
     int idxNew2;
+    CollSeq *pColl;    /* Collating sequence to use */
 
     pLeft = pExpr->x.pList->a[1].pExpr;
     pStr2 = sqlite3ExprDup(db, pStr1, 0);
@@ -1264,11 +1251,16 @@ static void exprAnalyze(
       }
       *pC = c + 1;
     }
-    pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprDup(db,pLeft,0),pStr1,0);
+    pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, noCase ? "NOCASE" : "BINARY",0);
+    pNewExpr1 = sqlite3PExpr(pParse, TK_GE, 
+                     sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
+                     pStr1, 0);
     idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
     testcase( idxNew1==0 );
     exprAnalyze(pSrc, pWC, idxNew1);
-    pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprDup(db,pLeft,0),pStr2,0);
+    pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
+                     sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
+                     pStr2, 0);
     idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
     testcase( idxNew2==0 );
     exprAnalyze(pSrc, pWC, idxNew2);
index 438ecd7b2b71218f35acb1eed873cbd68fab6c64..6fc70d99c5c2f246a5a9342f06c7c5d91abbe005 100644 (file)
@@ -268,6 +268,22 @@ do_test analyze3-2.5 {
   set like "%a"
   sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
 } {999 999 100}
+do_test analyze3-2.6 {
+  set like "a"
+  sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
+} {101 0 0}
+do_test analyze3-2.7 {
+  set like "ab"
+  sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
+} {11 0 0}
+do_test analyze3-2.8 {
+  set like "abc"
+  sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
+} {2 0 1}
+do_test analyze3-2.9 {
+  set like "a_c"
+  sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
+} {101 0 10}
 
 
 #-------------------------------------------------------------------------
index a2de6866b5cc09ace6c21ea0ab4b7f357b9a6066..229f3868809a8dac68af212ac3a6b5761793aab2 100644 (file)
@@ -194,6 +194,31 @@ do_test like-3.4 {
   set sqlite_like_count
 } 0
 
+# The LIKE optimization still works when the RHS is a string with no
+# wildcard.  Ticket [e090183531fc2747]
+#
+do_test like-3.4.2 {
+  queryplan {
+    SELECT x FROM t1 WHERE x LIKE 'a' ORDER BY 1;
+  }
+} {a nosort {} i1}
+do_test like-3.4.3 {
+  queryplan {
+    SELECT x FROM t1 WHERE x LIKE 'ab' ORDER BY 1;
+  }
+} {ab nosort {} i1}
+do_test like-3.4.4 {
+  queryplan {
+    SELECT x FROM t1 WHERE x LIKE 'abcd' ORDER BY 1;
+  }
+} {abcd nosort {} i1}
+do_test like-3.4.5 {
+  queryplan {
+    SELECT x FROM t1 WHERE x LIKE 'abcde' ORDER BY 1;
+  }
+} {nosort {} i1}
+
+
 # Partial optimization when the pattern does not end in '%'
 #
 do_test like-3.5 {
@@ -309,6 +334,26 @@ do_test like-3.24 {
   set sqlite_like_count
 } 6
 
+# GLOB optimization when there is no wildcard.  Ticket [e090183531fc2747]
+#
+do_test like-3.25 {
+  queryplan {
+    SELECT x FROM t1 WHERE x GLOB 'a' ORDER BY 1;
+  }
+} {a nosort {} i1}
+do_test like-3.26 {
+  queryplan {
+    SELECT x FROM t1 WHERE x GLOB 'abcd' ORDER BY 1;
+  }
+} {abcd nosort {} i1}
+do_test like-3.27 {
+  queryplan {
+    SELECT x FROM t1 WHERE x GLOB 'abcde' ORDER BY 1;
+  }
+} {nosort {} i1}
+
+
+
 # No optimization if the LHS of the LIKE is not a column name or
 # if the RHS is not a string.
 #
@@ -733,5 +778,94 @@ do_test like-10.15 {
   }
 } {12 123 scan 5 like 6}
 
+# LIKE and GLOB where the default collating sequence is not appropriate
+# but an index with the appropriate collating sequence exists.
+#
+do_test like-11.0 {
+  execsql {
+    CREATE TABLE t11(
+      a INTEGER PRIMARY KEY,
+      b TEXT COLLATE nocase,
+      c TEXT COLLATE binary
+    );
+    INSERT INTO t11 VALUES(1, 'a','a');
+    INSERT INTO t11 VALUES(2, 'ab','ab');
+    INSERT INTO t11 VALUES(3, 'abc','abc');
+    INSERT INTO t11 VALUES(4, 'abcd','abcd');
+    INSERT INTO t11 VALUES(5, 'A','A');
+    INSERT INTO t11 VALUES(6, 'AB','AB');
+    INSERT INTO t11 VALUES(7, 'ABC','ABC');
+    INSERT INTO t11 VALUES(8, 'ABCD','ABCD');
+    INSERT INTO t11 VALUES(9, 'x','x');
+    INSERT INTO t11 VALUES(10, 'yz','yz');
+    INSERT INTO t11 VALUES(11, 'X','X');
+    INSERT INTO t11 VALUES(12, 'YZ','YZ');
+    SELECT count(*) FROM t11;
+  }
+} {12}
+do_test like-11.1 {
+  queryplan {
+    PRAGMA case_sensitive_like=OFF;
+    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
+  }
+} {abc abcd ABC ABCD nosort t11 *}
+do_test like-11.2 {
+  queryplan {
+    PRAGMA case_sensitive_like=ON;
+    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
+  }
+} {abc abcd nosort t11 *}
+do_test like-11.3 {
+  queryplan {
+    PRAGMA case_sensitive_like=OFF;
+    CREATE INDEX t11b ON t11(b);
+    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
+  }
+} {abc abcd ABC ABCD sort {} t11b}
+do_test like-11.4 {
+  queryplan {
+    PRAGMA case_sensitive_like=ON;
+    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
+  }
+} {abc abcd nosort t11 *}
+do_test like-11.5 {
+  queryplan {
+    PRAGMA case_sensitive_like=OFF;
+    DROP INDEX t11b;
+    CREATE INDEX t11bnc ON t11(b COLLATE nocase);
+    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
+  }
+} {abc abcd ABC ABCD sort {} t11bnc}
+do_test like-11.6 {
+  queryplan {
+    CREATE INDEX t11bb ON t11(b COLLATE binary);
+    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
+  }
+} {abc abcd ABC ABCD sort {} t11bnc}
+do_test like-11.7 {
+  queryplan {
+    PRAGMA case_sensitive_like=ON;
+    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
+  }
+} {abc abcd sort {} t11bb}
+do_test like-11.8 {
+  queryplan {
+    PRAGMA case_sensitive_like=OFF;
+    SELECT b FROM t11 WHERE b GLOB 'abc*' ORDER BY a;
+  }
+} {abc abcd sort {} t11bb}
+do_test like-11.9 {
+  queryplan {
+    CREATE INDEX t11cnc ON t11(c COLLATE nocase);
+    CREATE INDEX t11cb ON t11(c COLLATE binary);
+    SELECT c FROM t11 WHERE c LIKE 'abc%' ORDER BY a;
+  }
+} {abc abcd ABC ABCD sort {} t11cnc}
+do_test like-11.10 {
+  queryplan {
+    SELECT c FROM t11 WHERE c GLOB 'abc*' ORDER BY a;
+  }
+} {abc abcd sort {} t11cb}
+
 
 finish_test