From: drh Date: Fri, 5 Aug 2011 21:13:42 +0000 (+0000) Subject: Add a column to the sqlite_stat2 table that contains the number of entries X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=37c5858fbaad3bd36e4dc95a3682daf1c4ec3c4a;p=thirdparty%2Fsqlite.git Add a column to the sqlite_stat2 table that contains the number of entries with exactly the same key as the sample. We do not yet do anything with this extra value. Some tests in analyze2.test are failing. FossilOrigin-Name: eb434228277c4bbbb1ad153ed3e6e3eeffe799a4 --- diff --git a/manifest b/manifest index 6ca37535c3..f6dbb1f52f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\swinopen-retry-logic\sbranch\sinto\strunk.\s\sThe\sbiggest\schange\shere\nis\sto\stest\sscripts,\swhich\sshould\snow\suse\ssuch\sas\scopy_file\sand\ndelete_file\sfrom\stester.tcl\srather\sthan\sthe\sraw\sfile\scommands\sof\sTCL. -D 2011-08-03T22:06:39.312 +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 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 a425d62e8fa9ebcb4359ab84ff0c62c6563d2e2a +F src/analyze.c dcac3850e746071a631ac01cfeeb2a050624258a 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 49d834f0fe49d305e07f9c212e94007fda2028e9 +F src/vdbe.c 1215ce453650a69bdab7f39eee94bb38d5d0d55a F src/vdbe.h 5cf09e7ee8a3f7d93bc51f196a96550786afe7a1 F src/vdbeInt.h ad84226cc0adcb1185c22b70696b235a1678bb45 F src/vdbeapi.c 11dc47987abacb76ad016dcf5abc0dc422482a98 @@ -261,7 +261,7 @@ F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d F test/alter4.test b2debc14d8cbe4c1d12ccd6a41eef88a8c1f15d5 F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc F test/analyze.test c8cb89e8736336f1f0646c8123e6028a14c7b55e -F test/analyze2.test 8f2b1534d43f5547ce9a6b736c021d4192c75be3 +F test/analyze2.test 6a5c1420bdbfadd47556fcd88deeb27ab3853a36 F test/analyze3.test d61f55d8b472fc6e713160b1e577f7a68e63f38b F test/analyze4.test 757b37875cf9bb528d46f74497bc789c88365045 F test/analyze5.test 1de8d66b11aae5a1453aa042d62e834a476bac9c @@ -955,7 +955,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh 2ebae31e1eb352696f3c2f7706a34c084b28c262 -P a2135ad13049c170b33315a949b1544e6a136183 4cb17881d9676fa3359394391b9ba53f08e5809a -R 69e73a0d833d24111d142317de3be42c +P b90c28be3840169651022ef36cd7cf416bc22305 +R 0f788d1f52f6bfe1349b8a107eceb976 U drh -Z e1999267404d37fe86d90d3e80b00531 +Z 9cf20af92454c5c2c49374f6b1c17d00 diff --git a/manifest.uuid b/manifest.uuid index c95e730993..614b811128 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b90c28be3840169651022ef36cd7cf416bc22305 \ No newline at end of file +eb434228277c4bbbb1ad153ed3e6e3eeffe799a4 \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 17c1de83a9..b78a32d84a 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -43,7 +43,7 @@ static void openStatTable( } aTable[] = { { "sqlite_stat1", "tbl,idx,stat" }, #ifdef SQLITE_ENABLE_STAT2 - { "sqlite_stat2", "tbl,idx,sampleno,sample" }, + { "sqlite_stat2", "tbl,idx,sampleno,sample,cnt" }, #endif }; @@ -94,6 +94,7 @@ static void openStatTable( sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb); sqlite3VdbeChangeP4(v, -1, (char *)3, P4_INT32); sqlite3VdbeChangeP5(v, aCreateTbl[i]); + VdbeComment((v, "%s", aTable[i].zName)); } } @@ -119,20 +120,26 @@ static void analyzeOneTable( int iDb; /* Index of database containing pTab */ int regTabname = iMem++; /* Register containing table name */ int regIdxname = iMem++; /* Register containing index name */ - int regSampleno = iMem++; /* Register containing next sample number */ - int regCol = iMem++; /* Content of a column analyzed table */ + int regSampleno = iMem++; /* Sampleno (stat2) or stat (stat1) */ +#ifdef SQLITE_ENABLE_STAT2 + int regSample = iMem++; /* The next sample value */ + int regSampleCnt = iMem++; /* Number of occurrances of regSample value */ + int shortJump = 0; /* Instruction address */ + int addrStoreStat2 = 0; /* Address of subroutine to wrote to stat2 */ + int regNext = iMem++; /* Index of next sample to record */ + int regSampleIdx = iMem++; /* Index of next sample */ + int regReady = iMem++; /* True if ready to store a stat2 entry */ + int regGosub = iMem++; /* Register holding subroutine return addr */ + int regSample2 = iMem++; /* Number of samples to acquire times 2 */ + int regCount = iMem++; /* Number of rows in the table */ + int regCount2 = iMem++; /* regCount*2 */ +#endif + int regCol = iMem++; /* Content of a column in analyzed table */ int regRec = iMem++; /* Register holding completed record */ int regTemp = iMem++; /* Temporary use register */ int regRowid = iMem++; /* Rowid for the inserted record */ + int once = 1; /* One-time initialization */ -#ifdef SQLITE_ENABLE_STAT2 - int addr = 0; /* Instruction address */ - int regTemp2 = iMem++; /* Temporary use register */ - int regSamplerecno = iMem++; /* Index of next sample to record */ - int regRecno = iMem++; /* Current sample index */ - int regLast = iMem++; /* Index of last sample to record */ - int regFirst = iMem++; /* Index of first sample to record */ -#endif v = sqlite3GetVdbe(pParse); if( v==0 || NEVER(pTab==0) ){ @@ -165,13 +172,18 @@ static void analyzeOneTable( for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int nCol; KeyInfo *pKey; + int addrIfNot; /* address of OP_IfNot */ + int *aChngAddr; /* Array of jump instruction addresses */ if( pOnlyIdx && pOnlyIdx!=pIdx ) continue; + VdbeNoopComment((v, "Begin analysis of %s", pIdx->zName)); nCol = pIdx->nColumn; pKey = sqlite3IndexKeyinfo(pParse, pIdx); if( iMem+1+(nCol*2)>pParse->nMem ){ pParse->nMem = iMem+1+(nCol*2); } + aChngAddr = sqlite3DbMallocRaw(db, sizeof(int)*pIdx->nColumn); + if( aChngAddr==0 ) continue; /* Open a cursor to the index to be analyzed. */ assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) ); @@ -187,26 +199,39 @@ static void analyzeOneTable( /* If this iteration of the loop is generating code to analyze the ** first index in the pTab->pIndex list, then register regLast has ** not been populated. In this case populate it now. */ - if( pTab->pIndex==pIdx ){ - sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_INDEX_SAMPLES, regSamplerecno); - sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_INDEX_SAMPLES*2-1, regTemp); - sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_INDEX_SAMPLES*2, regTemp2); - - sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regLast); - sqlite3VdbeAddOp2(v, OP_Null, 0, regFirst); - addr = sqlite3VdbeAddOp3(v, OP_Lt, regSamplerecno, 0, regLast); - sqlite3VdbeAddOp3(v, OP_Divide, regTemp2, regLast, regFirst); - sqlite3VdbeAddOp3(v, OP_Multiply, regLast, regTemp, regLast); - sqlite3VdbeAddOp2(v, OP_AddImm, regLast, SQLITE_INDEX_SAMPLES*2-2); - sqlite3VdbeAddOp3(v, OP_Divide, regTemp2, regLast, regLast); - sqlite3VdbeJumpHere(v, addr); + if( once ){ + once = 0; + sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_INDEX_SAMPLES*2, regSample2); + + sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regCount); + sqlite3VdbeAddOp3(v, OP_Add, regCount, regCount, regCount2); + + + /* Generate code for a subroutine that store the most recent sample + ** in the sqlite_stat2 table + */ + shortJump = sqlite3VdbeAddOp0(v, OP_Goto); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 5, regRec, "aaaba", 0); + VdbeComment((v, "begin stat2 write subroutine")); + sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regRowid); + sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regRec, regRowid); + sqlite3VdbeAddOp2(v, OP_AddImm, regSampleno, 1); + sqlite3VdbeAddOp2(v, OP_AddImm, regReady, -1); + addrStoreStat2 = sqlite3VdbeAddOp2(v, OP_IfPos, regReady, shortJump+1); + sqlite3VdbeAddOp1(v, OP_Return, regGosub); + VdbeComment((v, "end stat2 write subroutine")); + sqlite3VdbeJumpHere(v, shortJump); } - - /* Zero the regSampleno and regRecno registers. */ + /* Reset state registers */ + sqlite3VdbeAddOp2(v, OP_Copy, regCount2, regNext); + shortJump = sqlite3VdbeAddOp3(v, OP_Lt, regSample2, 0, regCount); + sqlite3VdbeAddOp3(v, OP_Divide, regSample2, regCount, regNext); + sqlite3VdbeJumpHere(v, shortJump); sqlite3VdbeAddOp2(v, OP_Integer, 0, regSampleno); - sqlite3VdbeAddOp2(v, OP_Integer, 0, regRecno); - sqlite3VdbeAddOp2(v, OP_Copy, regFirst, regSamplerecno); -#endif + sqlite3VdbeAddOp2(v, OP_Integer, 0, regSampleIdx); + sqlite3VdbeAddOp2(v, OP_Integer, 0, regReady); + +#endif /* SQLITE_ENABLE_STAT2 */ /* The block of memory cells initialized here is used as follows. ** @@ -236,7 +261,7 @@ static void analyzeOneTable( endOfLoop = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp2(v, OP_Rewind, iIdxCur, endOfLoop); topOfLoop = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_AddImm, iMem, 1); + sqlite3VdbeAddOp2(v, OP_AddImm, iMem, 1); /* Increment row counter */ for(i=0; iazColl!=0 ); assert( pIdx->azColl[i]!=0 ); pColl = sqlite3LocateCollSeq(pParse, pIdx->azColl[i]); - sqlite3VdbeAddOp4(v, OP_Ne, regCol, 0, iMem+nCol+i+1, - (char*)pColl, P4_COLLSEQ); + aChngAddr[i] = sqlite3VdbeAddOp4(v, OP_Ne, regCol, 0, iMem+nCol+i+1, + (char*)pColl, P4_COLLSEQ); sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); - } - if( db->mallocFailed ){ - /* If a malloc failure has occurred, then the result of the expression - ** passed as the second argument to the call to sqlite3VdbeJumpHere() - ** below may be negative. Which causes an assert() to fail (or an - ** out-of-bounds write if SQLITE_DEBUG is not defined). */ - return; + VdbeComment((v, "jump if column %d changed", i)); +#ifdef SQLITE_ENABLE_STAT2 + if( i==0 && addrStoreStat2 ){ + sqlite3VdbeAddOp2(v, OP_AddImm, regSampleCnt, 1); + VdbeComment((v, "incr repeat count")); + } +#endif } sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop); for(i=0; ip2, pOut); break; } @@ -1540,6 +1539,7 @@ case OP_AddImm: { /* in1 */ memAboutToChange(p, pIn1); sqlite3VdbeMemIntegerify(pIn1); pIn1->u.i += pOp->p2; + REGISTER_TRACE(pOp->p1, pIn1); break; } diff --git a/test/analyze2.test b/test/analyze2.test index de2567bb6f..3e48a42239 100644 --- a/test/analyze2.test +++ b/test/analyze2.test @@ -71,9 +71,9 @@ do_test analyze2-1.1 { } execsql { ANALYZE; - SELECT * FROM sqlite_stat2; + SELECT tbl, idx, sampleno, sample FROM sqlite_stat2; } -} [list t1 sqlite_autoindex_t1_1 0 50 \ +} [list t1 sqlite_autoindex_t1_1 0 49 \ t1 sqlite_autoindex_t1_1 1 149 \ t1 sqlite_autoindex_t1_1 2 249 \ t1 sqlite_autoindex_t1_1 3 349 \ @@ -87,7 +87,7 @@ do_test analyze2-1.1 { do_test analyze2-1.2 { execsql { - DELETE FROM t1 WHERe x>9; + DELETE FROM t1 WHERE x>9; ANALYZE; SELECT tbl, idx, group_concat(sample, ' ') FROM sqlite_stat2; } @@ -189,7 +189,7 @@ do_test analyze2-3.1 { WHERE idx = 't1_x' GROUP BY tbl,idx } -} {t1 t1_x {100 299 499 699 899 ajj cjj ejj gjj ijj}} +} {t1 t1_x {99 299 499 699 899 ajj cjj ejj gjj ijj}} do_test analyze2-3.2 { execsql { SELECT tbl,idx,group_concat(sample,' ') @@ -197,7 +197,7 @@ do_test analyze2-3.2 { WHERE idx = 't1_y' GROUP BY tbl,idx } -} {t1 t1_y {100 299 499 699 899 ajj cjj ejj gjj ijj}} +} {t1 t1_y {99 299 499 699 899 ajj cjj ejj gjj ijj}} do_eqp_test 3.3 { SELECT * FROM t1 WHERE x BETWEEN 100 AND 500 AND y BETWEEN 'a' AND 'b'