]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Consider explicit collate clauses when matching WHERE constraints to indices. Fix...
authordanielk1977 <danielk1977@noemail.net>
Tue, 29 May 2007 12:11:29 +0000 (12:11 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Tue, 29 May 2007 12:11:29 +0000 (12:11 +0000)
FossilOrigin-Name: f9a95e92dfaaa61ec0a44b9b7017b07929c94d26

manifest
manifest.uuid
src/expr.c
src/sqliteInt.h
src/where.c
test/tkt2391.test [new file with mode: 0644]

index e522445125be7d8b227f08ff3455335308ae8a23..dfb4ad9e361ab6120ade00ba1c3e90bf87ab38c0 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\ssome\stests\sto\sverify\sthat\sthe\sparameter\sto\sthe\sincremental_vacuum\spragma\sis\sworking.\sIt\sis.\s(CVS\s4039)
-D 2007-05-24T10:18:22
+C Consider\sexplicit\scollate\sclauses\swhen\smatching\sWHERE\sconstraints\sto\sindices.\sFix\sfor\s#2391.\s(CVS\s4040)
+D 2007-05-29T12:11:30
 F Makefile.in a42354804b50c2708ce72cf79e4daa30f50191b5
 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -71,7 +71,7 @@ F src/complete.c 7d1a44be8f37de125fcafd3d3a018690b3799675
 F src/date.c 6049db7d5a8fdf2c677ff7d58fa31d4f6593c988
 F src/delete.c 5c0d89b3ef7d48fe1f5124bfe8341f982747fe29
 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
-F src/expr.c 436f1d3e5addf95c195016b518cd2f44a6f5f081
+F src/expr.c 7243b6c01b976662873bbba397640fb4cbed76bc
 F src/func.c dfd0dd496dac46c2b14a88292cd9e141aae3ba63
 F src/hash.c 67b23e14f0257b69a3e8aa663e4eeadc1a2b6fd5
 F src/hash.h 1b3f7e2609141fd571f62199fc38687d262e9564
@@ -105,7 +105,7 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c d07ae326b3815d80f71c69b3c7584382e47f6447
 F src/sqlite.h.in b174b5508467deec4034c6c8a21f0354b498b46b
 F src/sqlite3ext.h 7d0d363ea7327e817ef0dfe1b7eee1f171b72890
-F src/sqliteInt.h 58edde37943f4f8155986f0c33735ba31fc66e9f
+F src/sqliteInt.h 853d50bfeb72586faada449061a8dcd61f8db42d
 F src/table.c a8de75bcedf84d4060d804264b067ab3b1a3561d
 F src/tclsqlite.c f425c7583665ef78dd8397b2de0b8e0028e80ce2
 F src/test1.c 0ec120a4652ee95268a5a45e1e1adee13be9ae28
@@ -142,7 +142,7 @@ F src/vdbeblob.c 96f3572fdc45eda5be06e6372b612bc30742d9f0
 F src/vdbefifo.c 3ca8049c561d5d67cbcb94dc909ae9bb68c0bf8f
 F src/vdbemem.c 332875a5fc9ac482e00701db5487ceb7f6fc1adc
 F src/vtab.c c5ebebf615b2f29499fbe97a584c4bb342632aa0
-F src/where.c f3920748cc650fc25ac916215500bdb90dee568e
+F src/where.c 1c27ddb2f19976175fecdcf8f5a0ca23596917fb
 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/all.test 93a40a7612b3c5e6efd1f5b98496a8b02a45cfdb
@@ -382,6 +382,7 @@ F test/tkt2251.test 3f0549213386ed911715665a908ff2bb7a871002
 F test/tkt2285.test c618085f0c13ec3347e607f83c34ada0721b4bfa
 F test/tkt2332.test cb1bb0ed1ae6a3b9ff412520ed4a496745f4ffa5
 F test/tkt2339.test 7016415bda86af1406a27260ac46f44885617606
+F test/tkt2391.test ab7a11be7402da8b51a5be603425367aa0684567
 F test/trace.test 75ffc1b992c780d054748a656e3e7fd674f18567
 F test/trans.test 3fe1b9e03b523482eee2b869858c5c1eca7b218b
 F test/trigger1.test b361161cf20614024cc1e52ea0bdec250776b2ae
@@ -494,7 +495,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P e8ae6214bfef4230096b6b56e688e9d4cd93f1b8
-R 114bb7154f3f00accbd22be991d205a9
+P 1abf784fe27cdc61b6b944b79d024ea98eb5289e
+R 2231e0859ae00b3b5f9f014c6b668680
 U danielk1977
-Z 3f53a4a2d46ad174a9eb3dc8ca1b824d
+Z b43a8281516bbb9de3a5fb2d18123729
index 2c4b8325e3eebdbc2459303fc8d5fa3347e73660..87643cd7e23a9da500ed57ba0dcb0f3483da2279 100644 (file)
@@ -1 +1 @@
-1abf784fe27cdc61b6b944b79d024ea98eb5289e
\ No newline at end of file
+f9a95e92dfaaa61ec0a44b9b7017b07929c94d26
\ No newline at end of file
index 921cca343577095cff90893812dc0e7c762e179a..c4f395bf8c9bd932a9e9373c6e395489a1ba7920 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.294 2007/05/15 07:00:34 danielk1977 Exp $
+** $Id: expr.c,v 1.295 2007/05/29 12:11:30 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -171,15 +171,21 @@ static int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
 ** used. Otherwise the collation sequence for the right hand expression
 ** is used, or the default (BINARY) if neither expression has a collating
 ** type.
+**
+** Argument pRight (but not pLeft) may be a null pointer. In this case,
+** it is not considered.
 */
-static CollSeq* binaryCompareCollSeq(Parse *pParse, Expr *pLeft, Expr *pRight){
+CollSeq* sqlite3BinaryCompareCollSeq(
+  Parse *pParse, 
+  Expr *pLeft, 
+  Expr *pRight
+){
   CollSeq *pColl;
   assert( pLeft );
-  assert( pRight );
   if( pLeft->flags & EP_ExpCollate ){
     assert( pLeft->pColl );
     pColl = pLeft->pColl;
-  }else if( pRight->flags & EP_ExpCollate ){
+  }else if( pRight && pRight->flags & EP_ExpCollate ){
     assert( pRight->pColl );
     pColl = pRight->pColl;
   }else{
@@ -203,7 +209,7 @@ static int codeCompare(
   int jumpIfNull    /* If true, jump if either operand is NULL */
 ){
   int p1 = binaryCompareP1(pLeft, pRight, jumpIfNull);
-  CollSeq *p3 = binaryCompareCollSeq(pParse, pLeft, pRight);
+  CollSeq *p3 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
   return sqlite3VdbeOp3(pParse->pVdbe, opcode, p1, dest, (void*)p3, P3_COLLSEQ);
 }
 
@@ -1533,7 +1539,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
         }
         pEList = pExpr->pSelect->pEList;
         if( pEList && pEList->nExpr>0 ){ 
-          keyInfo.aColl[0] = binaryCompareCollSeq(pParse, pExpr->pLeft,
+          keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
               pEList->a[0].pExpr);
         }
       }else if( pExpr->pList ){
index 3f28e145c671ba37326463ea693f6e1f6424da90..4de394aec469168613ac27d3239763399576474b 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.569 2007/05/16 17:28:43 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.570 2007/05/29 12:11:30 danielk1977 Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1569,7 +1569,7 @@ extern const unsigned char sqlite3UtfTrans1[];
 **     be encoded as a multi-byte character.  Any multi-byte character that
 **     attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd.
 **
-**  *  These macros never allow a UTF16 surragate value to be encoded.
+**  *  These macros never allow a UTF16 surrogate value to be encoded.
 **     If a multi-byte character attempts to encode a value between
 **     0xd800 and 0xe000 then it is rendered as 0xfffd.
 **
@@ -1954,6 +1954,7 @@ FuncDef *sqlite3VtabOverloadFunction(FuncDef*, int nArg, Expr*);
 void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
 int sqlite3Reprepare(Vdbe*);
 void sqlite3ExprListCheckLength(Parse*, ExprList*, int, const char*);
+CollSeq* sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
 
 #if SQLITE_MAX_EXPR_DEPTH>0
   void sqlite3ExprSetHeight(Expr *);
index dabce68b5593fbd2dae95623eb8691775d23ad24..6f48ee44e2888dac39f5fb575c11f226774954b1 100644 (file)
@@ -16,7 +16,7 @@
 ** so is applicable.  Because this module is responsible for selecting
 ** indices, you might also think of this module as the "query optimizer".
 **
-** $Id: where.c,v 1.248 2007/05/04 13:15:57 drh Exp $
+** $Id: where.c,v 1.249 2007/05/29 12:11:30 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -452,15 +452,17 @@ static WhereTerm *findTerm(
 
         idxaff = pIdx->pTable->aCol[iColumn].affinity;
         if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue;
-        pColl = sqlite3ExprCollSeq(pParse, pX->pLeft);
+
+        /* Figure out the collation sequence required from an index for
+        ** it to be useful for optimising expression pX. Store this
+        ** value in variable pColl.
+        */
+        assert(pX->pLeft);
+        pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
         if( !pColl ){
-          if( pX->pRight ){
-            pColl = sqlite3ExprCollSeq(pParse, pX->pRight);
-          }
-          if( !pColl ){
-            pColl = pParse->db->pDfltColl;
-          }
+          pColl = pParse->db->pDfltColl;
         }
+
         for(j=0; j<pIdx->nColumn && pIdx->aiColumn[j]!=iColumn; j++){}
         assert( j<pIdx->nColumn );
         if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
diff --git a/test/tkt2391.test b/test/tkt2391.test
new file mode 100644 (file)
index 0000000..d192b85
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# 2007 May 28
+#
+# 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.
+#
+#***********************************************************************
+# $Id: tkt2391.test,v 1.1 2007/05/29 12:11:30 danielk1977 Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test tkt2391.1 {
+  execsql {
+    CREATE TABLE folders(folderid, parentid, foldername COLLATE binary);
+    INSERT INTO folders VALUES(1, 3, 'FolderA');
+    INSERT INTO folders VALUES(1, 3, 'folderB');
+    INSERT INTO folders VALUES(4, 0, 'FolderC');
+  }
+} {}
+
+do_test tkt2391.2 {
+  execsql {
+    SELECT count(*) FROM folders WHERE foldername < 'FolderC';
+  }
+} {1}
+
+do_test tkt2391.3 {
+  execsql {
+    SELECT count(*) FROM folders WHERE foldername < 'FolderC' COLLATE nocase;
+  }
+} {2}
+
+# This demonstrates the bug. Creating the index causes SQLite to ignore
+# the "COLLATE nocase" clause and use the default collation sequence 
+# for column "foldername" instead (happens to be BINARY in this case).
+#
+do_test tkt2391.4 {
+  execsql {
+    CREATE INDEX f_i ON folders(foldername);
+    SELECT count(*) FROM folders WHERE foldername < 'FolderC' COLLATE nocase;
+  }
+} {2}
+
+finish_test