From: drh Date: Fri, 5 Aug 2011 22:31:19 +0000 (+0000) Subject: Bug fixes to the sample-count logic for STAT2. A few test cases added. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=78183ce13fbf95c85e619f9376f437edd47b2211;p=thirdparty%2Fsqlite.git Bug fixes to the sample-count logic for STAT2. A few test cases added. FossilOrigin-Name: e93c248c8470622944cf7f9e5af4f10c4e4809e3 --- diff --git a/manifest b/manifest index f6dbb1f52f..5d9c6e64e3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\scolumn\sto\sthe\ssqlite_stat2\stable\sthat\scontains\sthe\snumber\sof\sentries\nwith\sexactly\sthe\ssame\skey\sas\sthe\ssample.\s\sWe\sdo\snot\syet\sdo\sanything\swith\sthis\nextra\svalue.\s\sSome\stests\sin\sanalyze2.test\sare\sfailing. -D 2011-08-05T21:13:42.594 +C Bug\sfixes\sto\sthe\ssample-count\slogic\sfor\sSTAT2.\s\sA\sfew\stest\scases\sadded. +D 2011-08-05T22:31:19.378 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 1e6988b3c11dee9bd5edc0c804bd4468d74a9cdc F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -118,7 +118,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad F src/alter.c ac80a0f31189f8b4a524ebf661e47e84536ee7f5 -F src/analyze.c dcac3850e746071a631ac01cfeeb2a050624258a +F src/analyze.c 533077e1a96a9a33464edb35573b2a80a043e0f4 F src/attach.c 12c6957996908edc31c96d7c68d4942c2474405f F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 986c15232757f2873dff35ee3b35cbf935fc573c @@ -238,7 +238,7 @@ F src/update.c 74a6cfb34e9732c1e2a86278b229913b4b51eeec F src/utf.c c53eb7404b3eb5c1cbb5655c6a7a0e0ce6bd50f0 F src/util.c 06302ffd2b80408d4f6c7af71f7090e0cf8d8ff7 F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e -F src/vdbe.c 1215ce453650a69bdab7f39eee94bb38d5d0d55a +F src/vdbe.c b46e0dde62b62ada9988ae4478fd06eb393be067 F src/vdbe.h 5cf09e7ee8a3f7d93bc51f196a96550786afe7a1 F src/vdbeInt.h ad84226cc0adcb1185c22b70696b235a1678bb45 F src/vdbeapi.c 11dc47987abacb76ad016dcf5abc0dc422482a98 @@ -267,6 +267,7 @@ F test/analyze4.test 757b37875cf9bb528d46f74497bc789c88365045 F test/analyze5.test 1de8d66b11aae5a1453aa042d62e834a476bac9c F test/analyze6.test c125622a813325bba1b4999040ddc213773c2290 F test/analyze7.test 5508e7828164ea0b518ed219bed7320a481863d4 +F test/analyze8.test e78fb00274ca3c4eb9dc906a83bd13d5793d4641 F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7 @@ -955,7 +956,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh 2ebae31e1eb352696f3c2f7706a34c084b28c262 -P b90c28be3840169651022ef36cd7cf416bc22305 -R 0f788d1f52f6bfe1349b8a107eceb976 +P eb434228277c4bbbb1ad153ed3e6e3eeffe799a4 +R 5e934c2ca6d03f0d8b0d9f4d06ff655c U drh -Z 9cf20af92454c5c2c49374f6b1c17d00 +Z 98e2c68261b7b8ef26e19fbc93ef8bb3 diff --git a/manifest.uuid b/manifest.uuid index 614b811128..078676bf98 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -eb434228277c4bbbb1ad153ed3e6e3eeffe799a4 \ No newline at end of file +e93c248c8470622944cf7f9e5af4f10c4e4809e3 \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index b78a32d84a..43a337664d 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -267,28 +267,6 @@ static void analyzeOneTable( CollSeq *pColl; sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regCol); if( i==0 ){ -#ifdef SQLITE_ENABLE_STAT2 - /* Check if the record that cursor iIdxCur points to contains a - ** value that should be stored in the sqlite_stat2 table. If so, - ** store it. */ - int ne = sqlite3VdbeAddOp3(v, OP_Ne, iMem, 0, regNext); - VdbeComment((v, "jump if not a sample")); - sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrStoreStat2); - sqlite3VdbeAddOp2(v, OP_Copy, regCol, regSample); - sqlite3VdbeAddOp2(v, OP_AddImm, regReady, 1); - - /* Calculate new values for regNextSample. Where N is the number - ** of rows in the table and S is the number of samples to take: - ** - ** nextSample = (sampleNumber*N*2 + N)/(2*S) - */ - sqlite3VdbeAddOp2(v, OP_AddImm, regSampleIdx, 1); - sqlite3VdbeAddOp3(v, OP_Multiply, regSampleIdx, regCount2, regNext); - sqlite3VdbeAddOp3(v, OP_Add, regNext, regCount, regNext); - sqlite3VdbeAddOp3(v, OP_Divide, regSample2, regNext, regNext); - sqlite3VdbeJumpHere(v, ne); -#endif - /* Always record the very first row */ addrIfNot = sqlite3VdbeAddOp1(v, OP_IfNot, iMem+1); } @@ -321,8 +299,33 @@ static void analyzeOneTable( } sqlite3DbFree(db, aChngAddr); - /* End of the analysis loop. */ + /* Always jump here after updating the iMem+1...iMem+1+nCol counters */ sqlite3VdbeResolveLabel(v, endOfLoop); + +#ifdef SQLITE_ENABLE_STAT2 + /* Check if the record that cursor iIdxCur points to contains a + ** value that should be stored in the sqlite_stat2 table. If so, + ** store it. + */ + int ne = sqlite3VdbeAddOp3(v, OP_Le, regNext, 0, iMem); + VdbeComment((v, "jump if not a sample")); + shortJump = sqlite3VdbeAddOp1(v, OP_If, regReady); + sqlite3VdbeAddOp2(v, OP_Copy, iMem+nCol+1, regSample); + sqlite3VdbeJumpHere(v, shortJump); + sqlite3VdbeAddOp2(v, OP_AddImm, regReady, 1); + + /* Calculate new values for regNextSample. Where N is the number + ** of rows in the table and S is the number of samples to take: + ** + ** nextSample = (sampleNumber*N*2 + N)/(2*S) + */ + sqlite3VdbeAddOp2(v, OP_AddImm, regSampleIdx, 1); + sqlite3VdbeAddOp3(v, OP_Multiply, regSampleIdx, regCount2, regNext); + sqlite3VdbeAddOp3(v, OP_Add, regNext, regCount, regNext); + sqlite3VdbeAddOp3(v, OP_Divide, regSample2, regNext, regNext); + sqlite3VdbeJumpHere(v, ne); +#endif + sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop); sqlite3VdbeAddOp1(v, OP_Close, iIdxCur); #ifdef SQLITE_ENABLE_STAT2 diff --git a/src/vdbe.c b/src/vdbe.c index c4367e0aa0..d64b552a03 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2468,6 +2468,7 @@ case OP_MakeRecord: { */ for(pRec=pData0; pRec<=pLast; pRec++){ assert( memIsValid(pRec) ); + REGISTER_TRACE((pRec-pData0)+pOp->p1, pRec); if( zAffinity ){ applyAffinity(pRec, zAffinity[pRec-pData0], encoding); } diff --git a/test/analyze8.test b/test/analyze8.test new file mode 100644 index 0000000000..bad2a8285a --- /dev/null +++ b/test/analyze8.test @@ -0,0 +1,90 @@ +# 2011 August 5 +# +# 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. +# This file implements tests for the ANALYZE command under STAT2. +# Testing the logic that computes the number of copies of each sample. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# There is nothing to test if ANALYZE is disable for this build. +# +ifcapable {!analyze||!vtab||!stat2} { + finish_test + return +} + +# Generate some test data +# +do_test analyze8-1.0 { + set x 100 + set y 1 + set ycnt 0 + set yinc 10 + execsql { + CREATE TABLE t1(x,y); + ANALYZE; + BEGIN; + CREATE INDEX t1x ON t1(x); + CREATE INDEX t1y ON t1(y); + } + for {set i 0} {$i<20} {incr i} { + for {set j 0} {$j<300} {incr j} { + execsql {INSERT INTO t1 VALUES($x,$y)} + incr ycnt + if {$ycnt>=$yinc} {set ycnt 0; incr y} + } + for {set j 0} {$j<100} {incr j} { + incr x + execsql {INSERT INTO t1 VALUES($x,$y)} + incr ycnt + if {$ycnt>=$yinc} {set ycnt 0; incr y} + } + } + execsql { + COMMIT; + ANALYZE; + SELECT sample, cnt FROM sqlite_stat2 WHERE idx='t1x' ORDER BY sampleno; + } +} {200 301 400 301 600 301 800 301 1000 301 1200 301 1400 301 1600 301 1800 301 2000 301} +do_test analyze8-1.1 { + execsql { + SELECT count(*) FROM t1 WHERE x=200; + } +} {301} + +do_test analyze8-2.0 { + execsql { + BEGIN; + DELETE FROM t1; + } + for {set x 1} {$x<200} {incr x} { + execsql {INSERT INTO t1 VALUES($x,$x)} + } + for {set i 0} {$i<200} {incr i} { + execsql {INSERT INTO t1 VALUES(999,999)} + } + execsql { + COMMIT; + ANALYZE; + SELECT sample, cnt FROM sqlite_stat2 WHERE idx='t1x' ORDER BY sampleno; + } +} {20 1 60 1 100 1 140 1 180 1 999 200 999 200 999 200 999 200 999 200} +do_test analyze8-2.1 { + for {set i 0} {$i<200} {incr i} { + execsql {INSERT INTO t1 VALUES(0,999)} + } + execsql { + ANALYZE; + SELECT sample, cnt FROM sqlite_stat2 WHERE idx='t1x' ORDER BY sampleno; + } +} {0 200 0 200 0 200 10 1 70 1 130 1 190 1 999 200 999 200 999 200}