diff --git a/manifest b/manifest index c0d2e88fbf..b60645888e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stypo\sin\ssqlite3_close()\sfunction\sdocumentation\sreported\son\sthe\smailing\slist. -D 2013-03-12T23:03:42.781 +C Fix\sthe\sORDER\sBY\swith\sIN\sconstraint\slogic\sso\sthat\sit\sworks\swith\sall\ncombinations\sof\sDESC\son\sthe\sORDER\sBY\sclause,\son\sthe\sRHS\sof\sthe\sIN\soperator,\nand\sin\sthe\sindex\sused\sby\sORDER\sBY\sand\sIN.\s\s\nFix\sfor\sticket\s[4dd95f6943fbd18]. +D 2013-03-13T00:13:25.181 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 9a804abbd3cae82d196e4d33aba13239e32522a5 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -130,7 +130,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 72a70dcfda75d3a1f81041ce4573e7afddcd8e4e F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4 F src/delete.c aeabdabeeeaa0584127f291baa9617153d334778 -F src/expr.c a23b4aac2a455b2e76b55bef5dcfbe62b665375c +F src/expr.c d488bb60e54c9305d9fca1fa6fcc7bfbd23b13a2 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c e16942bd5c8a868ac53287886464a5ed0e72b179 F src/func.c 48987c025d69399f59a1c2a553cea5da41bf105d @@ -179,7 +179,7 @@ F src/shell.c 7c41bfcd9e5bf9d96b9215f79b03a5b2b44a3bca F src/sqlite.h.in f2fa32f440dda59ca47e22889966b2a6eb3b491c F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3ext.h 7183ab832e23db0f934494f16928da127a571d75 -F src/sqliteInt.h 59477c6ddb25e7ed8d8b67f4c58ded254371182e +F src/sqliteInt.h 0f8f05ee4db4ba9120b38f7a3992b325698f6e8a F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -252,7 +252,7 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83 F src/wal.c f5c7b5027d0ed0e9bc9afeb4a3a8dfea762ec7d2 F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6 F src/walker.c 3d75ba73de15e0f8cd0737643badbeb0e002f07b -F src/where.c 8b7690cae8700b385d8a53a39387cf8054d8cc47 +F src/where.c bdbbfa7ef4ea04c8d9b09585b45d4717a72f980a F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -376,7 +376,7 @@ F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab F test/descidx1.test 533dcbda614b0463b0ea029527fd27e5a9ab2d66 F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d -F test/descidx3.test fe720e8b37d59f4cef808b0bf4e1b391c2e56b6f +F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2 F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e F test/distinct.test 84da1414b2e6887fffd5ed571311b344c5b082ce F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376 @@ -778,6 +778,7 @@ F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7 F test/tkt-3a77c9714e.test 32bb28afa8c63fc76e972e996193139b63551ed9 F test/tkt-3fe897352e.test 10de1a67bd5c66b238a4c96abe55531b37bb4f00 F test/tkt-4a03edc4c8.test 2865e4edbc075b954daa82f8da7cc973033ec76e +F test/tkt-4dd95f6943.test b7fad82ce61a2650fa4861f903ee002c253730c3 F test/tkt-54844eea3f.test a12b851128f46a695e4e378cca67409b9b8f5894 F test/tkt-5d863f876e.test c9f36ca503fa154a3655f92a69d2c30da1747bfa F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84 @@ -1037,7 +1038,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P f9027cb47bdec8dcebf1f038921b28d9e9928c18 7232093d6c6871a9f4ea155ab215e3b39c1c322d -R 2b8e011f63f1ea6b304ed54d625b070b -U mistachkin -Z 320a77c87d730beccb243f9b6f174c49 +P c9a75d890f06cf3806d7b8879824a11d3a8e7016 7e7356f1552cd53ea363d1ded3b2c221c9d0be01 +R cf70d6af777786d8b14ff574243c0031 +U drh +Z ef3fb703f5f65c616953904db1b81e9f diff --git a/manifest.uuid b/manifest.uuid index fe6c431274..31a34e8a08 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c9a75d890f06cf3806d7b8879824a11d3a8e7016 \ No newline at end of file +839aa91faf1db7025d90fa3c65e50efb829b053b \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 4f38ab0a46..ed5451b1c5 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1456,10 +1456,11 @@ int sqlite3CodeOnce(Parse *pParse){ ** ** The returned value of this function indicates the b-tree type, as follows: ** -** IN_INDEX_ROWID - The cursor was opened on a database table. -** IN_INDEX_INDEX - The cursor was opened on a database index. -** IN_INDEX_EPH - The cursor was opened on a specially created and -** populated epheremal table. +** IN_INDEX_ROWID - The cursor was opened on a database table. +** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index. +** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index. +** IN_INDEX_EPH - The cursor was opened on a specially created and +** populated epheremal table. ** ** An existing b-tree might be used if the RHS expression pX is a simple ** subquery such as: @@ -1582,7 +1583,8 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb, pKey,P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIdx->zName)); - eType = IN_INDEX_INDEX; + assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); + eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; sqlite3VdbeJumpHere(v, iAddr); if( prNotFound && !pTab->aCol[iCol].notNull ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index e5b4ccac4b..129c4c5ea5 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3263,7 +3263,8 @@ const char *sqlite3JournalModename(int); #define IN_INDEX_ROWID 1 #define IN_INDEX_EPH 2 -#define IN_INDEX_INDEX 3 +#define IN_INDEX_INDEX_ASC 3 +#define IN_INDEX_INDEX_DESC 4 int sqlite3FindInIndex(Parse *, Expr *, int*); #ifdef SQLITE_ENABLE_ATOMIC_WRITE diff --git a/src/where.c b/src/where.c index aa81dabd47..25f3d4c54d 100644 --- a/src/where.c +++ b/src/where.c @@ -3775,7 +3775,8 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){ static int codeEqualityTerm( Parse *pParse, /* The parsing context */ WhereTerm *pTerm, /* The term of the WHERE clause to be coded */ - WhereLevel *pLevel, /* When level of the FROM clause we are working on */ + WhereLevel *pLevel, /* The level of the FROM clause we are working on */ + int iEq, /* Index of the equality term within this level */ int iTarget /* Attempt to leave results in this register */ ){ Expr *pX = pTerm->pExpr; @@ -3795,9 +3796,22 @@ static int codeEqualityTerm( struct InLoop *pIn; u8 bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0; + if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 + && pLevel->plan.u.pIdx->aSortOrder[iEq] + ){ + testcase( iEq==0 ); + testcase( iEq==pLevel->plan.u.pIdx->nColumn-1 ); + testcase( iEq>0 && iEq+1plan.u.pIdx->nColumn ); + testcase( bRev ); + bRev = !bRev; + } assert( pX->op==TK_IN ); iReg = iTarget; eType = sqlite3FindInIndex(pParse, pX, 0); + if( eType==IN_INDEX_INDEX_DESC ){ + testcase( bRev ); + bRev = !bRev; + } iTab = pX->iTable; sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); assert( pLevel->plan.wsFlags & WHERE_IN_ABLE ); @@ -3912,7 +3926,7 @@ static int codeAllEqualityTerms( ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */ testcase( (pTerm->wtFlags & TERM_CODED)!=0 ); testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ - r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase+j); + r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, regBase+j); if( r1!=regBase+j ){ if( nReg==1 ){ sqlite3ReleaseTempReg(pParse, regBase); @@ -4189,7 +4203,7 @@ static Bitmask codeOneLoopStart( int iTarget = iReg+j+1; pTerm = &pWC->a[aConstraint[k].iTermOffset]; if( pTerm->eOperator & WO_IN ){ - codeEqualityTerm(pParse, pTerm, pLevel, iTarget); + codeEqualityTerm(pParse, pTerm, pLevel, k, iTarget); addrNotFound = pLevel->addrNxt; }else{ sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget); @@ -4230,7 +4244,7 @@ static Bitmask codeOneLoopStart( assert( pTerm->pExpr!=0 ); assert( omitTable==0 ); testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ - iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, iReleaseReg); + iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, iReleaseReg); addrNxt = pLevel->addrNxt; sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg); diff --git a/test/descidx3.test b/test/descidx3.test index 3cc87afa5f..c375acc705 100644 --- a/test/descidx3.test +++ b/test/descidx3.test @@ -132,11 +132,11 @@ ifcapable subquery { # the IN(...) operator is not available. Hence these tests cannot be # run. do_test descidx3-4.1 { - execsql { + lsort [execsql { UPDATE t1 SET a=2 WHERE i<6; SELECT i FROM t1 WHERE a IN (1,2) AND b>0 AND b<'zzz'; - } - } {8 6 2 4 3} + }] + } {2 3 4 6 8} do_test descidx3-4.2 { execsql { UPDATE t1 SET a=1; diff --git a/test/tkt-4dd95f6943.test b/test/tkt-4dd95f6943.test new file mode 100644 index 0000000000..6590118370 --- /dev/null +++ b/test/tkt-4dd95f6943.test @@ -0,0 +1,101 @@ +# 2013 March 13 +# +# 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. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set ::testprefix tkt-4dd95f6943 + +do_execsql_test 1.0 { + CREATE TABLE t1(x); + INSERT INTO t1 VALUES (3), (4), (2), (1), (5), (6); +} + +foreach {tn1 idx} { + 1 { CREATE INDEX i1 ON t1(x ASC) } + 2 { CREATE INDEX i1 ON t1(x DESC) } +} { + do_execsql_test 1.$tn1.1 { DROP INDEX IF EXISTS i1; } + do_execsql_test 1.$tn1.2 $idx + + do_execsql_test 1.$tn1.3 { + SELECT x FROM t1 WHERE x IN(2, 4, 5) ORDER BY x ASC; + } {2 4 5} + + do_execsql_test 1.$tn1.4 { + SELECT x FROM t1 WHERE x IN(2, 4, 5) ORDER BY x DESC; + } {5 4 2} +} + + +do_execsql_test 2.0 { + CREATE TABLE t2(x, y); + INSERT INTO t2 VALUES (5, 3), (5, 4), (5, 2), (5, 1), (5, 5), (5, 6); + INSERT INTO t2 VALUES (1, 3), (1, 4), (1, 2), (1, 1), (1, 5), (1, 6); + INSERT INTO t2 VALUES (3, 3), (3, 4), (3, 2), (3, 1), (3, 5), (3, 6); + INSERT INTO t2 VALUES (2, 3), (2, 4), (2, 2), (2, 1), (2, 5), (2, 6); + INSERT INTO t2 VALUES (4, 3), (4, 4), (4, 2), (4, 1), (4, 5), (4, 6); + INSERT INTO t2 VALUES (6, 3), (6, 4), (6, 2), (6, 1), (6, 5), (6, 6); + + CREATE TABLE t3(a, b); + INSERT INTO t3 VALUES (2, 2), (4, 4), (5, 5); + CREATE INDEX t3i1 ON t3(a ASC); + CREATE INDEX t3i2 ON t3(b DESC); +} + +foreach {tn1 idx} { + 1 { CREATE INDEX i1 ON t2(x ASC, y ASC) } + 2 { CREATE INDEX i1 ON t2(x ASC, y DESC) } + 3 { CREATE INDEX i1 ON t2(x DESC, y ASC) } + 4 { CREATE INDEX i1 ON t2(x DESC, y DESC) } + + 5 { CREATE INDEX i1 ON t2(y ASC, x ASC) } + 6 { CREATE INDEX i1 ON t2(y ASC, x DESC) } + 7 { CREATE INDEX i1 ON t2(y DESC, x ASC) } + 8 { CREATE INDEX i1 ON t2(y DESC, x DESC) } +} { + do_execsql_test 2.$tn1.1 { DROP INDEX IF EXISTS i1; } + do_execsql_test 2.$tn1.2 $idx + + foreach {tn2 inexpr} { + 1 "(2, 4, 5)" + 2 "(SELECT a FROM t3)" + 3 "(SELECT b FROM t3)" + } { + do_execsql_test 2.$tn1.3 " + SELECT x, y FROM t2 WHERE x = 1 AND y IN $inexpr ORDER BY x ASC, y ASC; + " {1 2 1 4 1 5} + do_execsql_test 2.$tn1.4 " + SELECT x, y FROM t2 WHERE x = 2 AND y IN $inexpr ORDER BY x ASC, y DESC; + " {2 5 2 4 2 2} + do_execsql_test 2.$tn1.5 " + SELECT x, y FROM t2 WHERE x = 3 AND y IN $inexpr ORDER BY x DESC, y ASC; + " {3 2 3 4 3 5} + do_execsql_test 2.$tn1.6 " + SELECT x, y FROM t2 WHERE x = 4 AND y IN $inexpr ORDER BY x DESC, y DESC; + " {4 5 4 4 4 2} + } +} + +do_execsql_test 3.0 { + CREATE TABLE t7(x); + INSERT INTO t7 VALUES (1), (2), (3); + CREATE INDEX i7 ON t7(x); + + CREATE TABLE t8(y); + INSERT INTO t8 VALUES (1), (2), (3); + + CREATE UNIQUE INDEX i8 ON t8(y DESC); + SELECT x FROM t7 WHERE x IN (SELECT y FROM t8) ORDER BY x ASC; +} {1 2 3} + +finish_test