]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add a column to the sqlite_stat2 table that contains the number of entries
authordrh <drh@noemail.net>
Fri, 5 Aug 2011 21:13:42 +0000 (21:13 +0000)
committerdrh <drh@noemail.net>
Fri, 5 Aug 2011 21:13:42 +0000 (21:13 +0000)
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

manifest
manifest.uuid
src/analyze.c
src/vdbe.c
test/analyze2.test

index 6ca37535c3ade413cfd9007e20658fc17548515b..f6dbb1f52fe8086b72330a825b8f3eeadef8216f 100644 (file)
--- 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
index c95e7309932e76e8b171968cad4d63451fa44058..614b811128d7e6b247746e11940c7552805db641 100644 (file)
@@ -1 +1 @@
-b90c28be3840169651022ef36cd7cf416bc22305
\ No newline at end of file
+eb434228277c4bbbb1ad153ed3e6e3eeffe799a4
\ No newline at end of file
index 17c1de83a98bdec3bb98c917a5bbdec2927bc0fc..b78a32d84a045a87010d84ca7230f8ea8fc24709 100644 (file)
@@ -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; i<nCol; i++){
       CollSeq *pColl;
@@ -246,65 +271,63 @@ static void analyzeOneTable(
         /* 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, regRecno, 0, regSamplerecno);
-        assert( regTabname+1==regIdxname 
-             && regTabname+2==regSampleno
-             && regTabname+3==regCol
-        );
-        sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
-        sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 4, regRec, "aaab", 0);
-        sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regRowid);
-        sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regRec, regRowid);
-
-        /* Calculate new values for regSamplerecno and regSampleno.
+        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:
         **
-        **   sampleno = sampleno + 1
-        **   samplerecno = samplerecno+(remaining records)/(remaining samples)
+        **   nextSample = (sampleNumber*N*2 + N)/(2*S)
         */
-        sqlite3VdbeAddOp2(v, OP_AddImm, regSampleno, 1);
-        sqlite3VdbeAddOp3(v, OP_Subtract, regRecno, regLast, regTemp);
-        sqlite3VdbeAddOp2(v, OP_AddImm, regTemp, -1);
-        sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_INDEX_SAMPLES, regTemp2);
-        sqlite3VdbeAddOp3(v, OP_Subtract, regSampleno, regTemp2, regTemp2);
-        sqlite3VdbeAddOp3(v, OP_Divide, regTemp2, regTemp, regTemp);
-        sqlite3VdbeAddOp3(v, OP_Add, regSamplerecno, regTemp, regSamplerecno);
-
+        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);
-        sqlite3VdbeAddOp2(v, OP_AddImm, regRecno, 1);
 #endif
 
         /* Always record the very first row */
-        sqlite3VdbeAddOp1(v, OP_IfNot, iMem+1);
+        addrIfNot = sqlite3VdbeAddOp1(v, OP_IfNot, iMem+1);
       }
       assert( pIdx->azColl!=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; i<nCol; i++){
-      int addr2 = sqlite3VdbeCurrentAddr(v) - (nCol*2);
+      sqlite3VdbeJumpHere(v, aChngAddr[i]);  /* Set jump dest for the OP_Ne */
       if( i==0 ){
-        sqlite3VdbeJumpHere(v, addr2-1);  /* Set jump dest for the OP_IfNot */
+        sqlite3VdbeJumpHere(v, addrIfNot);   /* Jump dest for OP_IfNot */
+#ifdef SQLITE_ENABLE_STAT2
+        sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrStoreStat2);
+        sqlite3VdbeAddOp2(v, OP_Integer, 1, regSampleCnt);
+#endif        
       }
-      sqlite3VdbeJumpHere(v, addr2);      /* Set jump dest for the OP_Ne */
       sqlite3VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1);
       sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1);
     }
+    sqlite3DbFree(db, aChngAddr);
 
     /* End of the analysis loop. */
     sqlite3VdbeResolveLabel(v, endOfLoop);
     sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop);
     sqlite3VdbeAddOp1(v, OP_Close, iIdxCur);
+#ifdef SQLITE_ENABLE_STAT2
+    sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrStoreStat2);
+#endif        
 
     /* Store the results in sqlite_stat1.
     **
index 6b817ab6d671e7c79f66b3d33b7d86b7f620f766..c4367e0aa08aa442f0b6357dc43bd9fb8dddba44 100644 (file)
@@ -1053,7 +1053,6 @@ case OP_Copy: {             /* in1, out2 */
   assert( pOut!=pIn1 );
   sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
   Deephemeralize(pOut);
-  REGISTER_TRACE(pOp->p2, 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;
 }
 
index de2567bb6f704094f7c6920e033252a73755c531..3e48a42239cd85643cc2bd5390d2b68053deada3 100644 (file)
@@ -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'