From: drh Date: Thu, 1 Aug 2013 15:09:57 +0000 (+0000) Subject: More test cases and corresponding bug fixes. X-Git-Tag: version-3.8.0~55^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=66518ca71f739cc2830b18ffd57b888b284df4b3;p=thirdparty%2Fsqlite.git More test cases and corresponding bug fixes. FossilOrigin-Name: 0c8cfdfae215c95cf167f404a1d346690b28e972 --- diff --git a/manifest b/manifest index aa35525505..9ab30e629b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fill\sout\san\sinitial\simplementation\sof\sthe\ssqlite3ExprImpliesExpr()\sfunction. -D 2013-08-01T13:04:46.842 +C More\stest\scases\sand\scorresponding\sbug\sfixes. +D 2013-08-01T15:09:57.772 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -172,7 +172,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 4262c227bc91cecc61ae37ed3a40f08069cfa267 F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4 F src/delete.c 2317c814866d9aa71fea16b3faf4fdd4d6a49b94 -F src/expr.c 27a451dc75c8f2498199ddbd76e941f60fc31c73 +F src/expr.c b873f60585cb851963fd8059f8d26c578e8448f6 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 914a6bbd987d857c41ac9d244efa6641f36faadb F src/func.c 5c50c1ea31fd864b0fe921fe1a8d4c55acd609ef @@ -210,7 +210,7 @@ F src/parse.y 599bc6338f3a6a7e1d656669a5667b9d77aea86b F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c d23d07716de96c7c0c2503ec5051a4384c3fb938 -F src/pragma.c aca37128da044cc4e41e1cea49a5e3cf6159df43 +F src/pragma.c 590c75750d93ec5a1f903e4bb0dc6d2a0845bf8b F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f F src/printf.c 41c49dac366a3a411190001a8ab495fa8887974e F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 @@ -290,7 +290,7 @@ F src/vtab.c 2e8b489db47e20ae36cd247932dc671c9ded0624 F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 -F src/where.c bad23a54820dd7f4c0ec5048d3cdaed28d7e4a52 +F src/where.c 5642a0f1d7c45a0f0eb6006e783916a8a715089a F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -589,7 +589,7 @@ F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6 F test/index3.test 423a25c789fc8cc51aaf2a4370bbdde2d9e9eed7 F test/index4.test 2983216eb8c86ee62d9ed7cb206b5cc3331c0026 F test/index5.test fc07c14193c0430814e7a08b5da46888ee795c33 -F test/index6.test 9db2067dc06bfa4f664193d860297d50775d31e7 +F test/index6.test 203633042a116d98932f3c750c5d2bb60de7bd56 F test/indexedby.test 0e959308707c808515c3a51363f7a9835027108c F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 @@ -1104,7 +1104,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 81834c3023876487a1188390aae850cf71683701 -R 97f0c54b3f7128423bcbfe2828fbdcb2 +P 8e07aa2ad5579aeb82174ce5bd432ddb9c058bc1 +R b61a938ce818e9ac097fb2a064b3215f U drh -Z 2652ffb0448810ae6b88d2be09f88047 +Z 381062f7cdfdb23ad88f9994e93f96ef diff --git a/manifest.uuid b/manifest.uuid index 021a483570..9b8e98a9fd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8e07aa2ad5579aeb82174ce5bd432ddb9c058bc1 \ No newline at end of file +0c8cfdfae215c95cf167f404a1d346690b28e972 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 6fa34443a3..8d6b90dd2f 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3801,6 +3801,9 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ ** If any subelement of pB has Expr.iTable==(-1) then it is allowed ** to compare equal to an equivalent element in pA with Expr.iTable==iTab. ** +** The pA side might be using TK_REGISTER. If that is the case and pB is +** not using TK_REGISTER but is otherwise equivalent, then still return 0. +** ** Sometimes this routine will return 2 even if the two expressions ** really are equivalent. If we cannot prove that the expressions are ** identical, we return 2 just to be safe. So if this routine @@ -3821,7 +3824,7 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){ return 2; } if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; - if( pA->op!=pB->op ){ + if( pA->op!=pB->op && (pA->op!=TK_REGISTER || pA->op2!=pB->op) ){ if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB, iTab)<2 ){ return 1; } @@ -3834,7 +3837,9 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){ if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2; if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; if( pA->iColumn!=pB->iColumn ) return 2; - if( pA->iTable!=pB->iTable && (pA->iTable!=iTab || pB->iTable>=0) ) return 2; + if( pA->iTable!=pB->iTable + && pA->op!=TK_REGISTER + && (pA->iTable!=iTab || pB->iTable>=0) ) return 2; if( ExprHasProperty(pA, EP_IntValue) ){ if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ return 2; diff --git a/src/pragma.c b/src/pragma.c index 4462799db7..f152220d40 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1400,7 +1400,7 @@ void sqlite3Pragma( } /* Make sure sufficient number of registers have been allocated */ - pParse->nMem = MAX( pParse->nMem, cnt+4 ); + pParse->nMem = MAX( pParse->nMem, cnt+7 ); /* Do the b-tree integrity checks */ sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1); @@ -1425,6 +1425,7 @@ void sqlite3Pragma( addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */ sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeJumpHere(v, addr); + sqlite3ExprCacheClear(pParse); sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ sqlite3VdbeAddOp2(v, OP_Integer, 0, 7+j); /* index entries counter */ diff --git a/src/where.c b/src/where.c index bcf52ee823..51edc8ec39 100644 --- a/src/where.c +++ b/src/where.c @@ -5556,7 +5556,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){ pLoop->rRun = 33; /* 33==whereCost(10) */ }else{ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->onError==OE_None ) continue; + if( pIdx->onError==OE_None || pIdx->pPartIdxWhere!=0 ) continue; for(j=0; jnColumn; j++){ pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx); if( pTerm==0 ) break; diff --git a/test/index6.test b/test/index6.test index d283d924c5..0b6a9365dc 100644 --- a/test/index6.test +++ b/test/index6.test @@ -18,6 +18,7 @@ source $testdir/tester.tcl load_static_extension db wholenumber; do_test index6-1.1 { + # Able to parse and manage partial indices execsql { CREATE TABLE t1(a,b,c); CREATE INDEX t1a ON t1(a) WHERE a IS NOT NULL; @@ -27,9 +28,12 @@ do_test index6-1.1 { SELECT CASE WHEN value%3!=0 THEN value END, value, value FROM nums WHERE value<=20; SELECT count(a), count(b) FROM t1; + PRAGMA integrity_check; } -} {14 20} +} {14 20 ok} +# Error conditions during parsing... +# do_test index6-1.2 { catchsql { CREATE INDEX bad1 ON t1(a,b) WHERE x IS NOT NULL; @@ -64,6 +68,9 @@ do_test index6-1.10 { } } {{} 20 t1a {14 1} t1b {10 1} ok} +# STAT1 shows the partial indices have a reduced number of +# rows. +# do_test index6-1.11 { execsql { UPDATE t1 SET a=b; @@ -120,4 +127,89 @@ do_test index6-1.15 { } } {t1a {10 1} t1b {8 1} t1c {15 1} ok} +# Queries use partial indices as appropriate times. +# +do_test index6-2.1 { + execsql { + CREATE TABLE t2(a,b); + INSERT INTO t2(a,b) SELECT value, value FROM nums WHERE value<1000; + UPDATE t2 SET a=NULL WHERE b%5==0; + CREATE INDEX t2a1 ON t2(a) WHERE a IS NOT NULL; + SELECT count(*) FROM t2 WHERE a IS NOT NULL; + } +} {800} +do_test index6-2.2 { + execsql { + EXPLAIN QUERY PLAN + SELECT * FROM t2 WHERE a=5; + } +} {/.* TABLE t2 USING INDEX t2a1 .*/} +do_test index6-2.3 { + execsql { + EXPLAIN QUERY PLAN + SELECT * FROM t2 WHERE a IS NOT NULL; + } +} {/.* TABLE t2 USING INDEX t2a1 .*/} +do_test index6-2.4 { + execsql { + EXPLAIN QUERY PLAN + SELECT * FROM t2 WHERE a IS NULL; + } +} {~/.*INDEX t2a1.*/} + +do_execsql_test index6-2.101 { + DROP INDEX t2a1; + UPDATE t2 SET a=b, b=b+10000; + SELECT b FROM t2 WHERE a=15; +} {10015} +do_execsql_test index6-2.102 { + CREATE INDEX t2a2 ON t2(a) WHERE a<100 OR a>200; + SELECT b FROM t2 WHERE a=15; + PRAGMA integrity_check; +} {10015 ok} +do_execsql_test index6-2.102eqp { + EXPLAIN QUERY PLAN + SELECT b FROM t2 WHERE a=15; +} {~/.*INDEX t2a2.*/} +do_execsql_test index6-2.103 { + SELECT b FROM t2 WHERE a=15 AND a<100; +} {10015} +do_execsql_test index6-2.103eqp { + EXPLAIN QUERY PLAN + SELECT b FROM t2 WHERE a=15 AND a<100; +} {/.*INDEX t2a2.*/} +do_execsql_test index6-2.104 { + SELECT b FROM t2 WHERE a=515 AND a>200; +} {10515} +do_execsql_test index6-2.104eqp { + EXPLAIN QUERY PLAN + SELECT b FROM t2 WHERE a=515 AND a>200; +} {/.*INDEX t2a2.*/} + +# Partial UNIQUE indices +# +do_execsql_test index6-3.1 { + CREATE TABLE t3(a,b); + INSERT INTO t3 SELECT value, value FROM nums WHERE value<200; + UPDATE t3 SET a=999 WHERE b%5!=0; + CREATE UNIQUE INDEX t3a ON t3(a) WHERE a<>999; +} {} +do_test index6-3.2 { + # unable to insert a duplicate row a-value that is not 999. + catchsql { + INSERT INTO t3(a,b) VALUES(150, 'test1'); + } +} {1 {column a is not unique}} +do_test index6-3.3 { + # can insert multiple rows with a==999 because such rows are not + # part of the unique index. + catchsql { + INSERT INTO t3(a,b) VALUES(999, 'test1'), (999, 'test2'); + } +} {0 {}} +do_execsql_test index6-3.4 { + SELECT count(*) FROM t3 WHERE a=999; +} {162} +integrity_check index6-3.5 + finish_test