diff --git a/manifest b/manifest index e522445125..dfb4ad9e36 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 2c4b8325e3..87643cd7e2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1abf784fe27cdc61b6b944b79d024ea98eb5289e \ No newline at end of file +f9a95e92dfaaa61ec0a44b9b7017b07929c94d26 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 921cca3435..c4f395bf8c 100644 --- a/src/expr.c +++ b/src/expr.c @@ -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 @@ -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 ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 3f28e145c6..4de394aec4 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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 *); diff --git a/src/where.c b/src/where.c index dabce68b55..6f48ee44e2 100644 --- a/src/where.c +++ b/src/where.c @@ -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; jnColumn && pIdx->aiColumn[j]!=iColumn; j++){} assert( jnColumn ); if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue; diff --git a/test/tkt2391.test b/test/tkt2391.test new file mode 100644 index 0000000000..d192b85bd7 --- /dev/null +++ b/test/tkt2391.test @@ -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