]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Allow the sqlite_stat2 table to contain a number of samples other than
authordrh <drh@noemail.net>
Fri, 5 Aug 2011 01:09:49 +0000 (01:09 +0000)
committerdrh <drh@noemail.net>
Fri, 5 Aug 2011 01:09:49 +0000 (01:09 +0000)
the default of 10.

FossilOrigin-Name: b9d41c3490bf325915227a32b612e6772fb62fa9

manifest
manifest.uuid
src/analyze.c
src/sqliteInt.h
src/where.c

index c1ecf5c6a5a4380169cb304733629d131f5797a8..7cbd6538006ce57903a3acbe54a0a077e307702b 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Adjust\sthe\soutput\srow\sestimating\slogic\swhen\susing\sSTAT2.
-D 2011-08-03T01:07:25.236
+C Allow\sthe\ssqlite_stat2\stable\sto\scontain\sa\snumber\sof\ssamples\sother\sthan\nthe\sdefault\sof\s10.
+D 2011-08-05T01:09:49.877
 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 ddc492c18b9caf6daf654fe5a3b1efc185e29a7b
 F src/attach.c 12c6957996908edc31c96d7c68d4942c2474405f
 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
 F src/backup.c 986c15232757f2873dff35ee3b35cbf935fc573c
@@ -183,7 +183,7 @@ F src/select.c d219c4b68d603cc734b6f9b1e2780fee12a1fa0d
 F src/shell.c bbe7818ff5bc8614105ceb81ad67b8bdc0b671dd
 F src/sqlite.h.in 0b3cab7b2ea51f58396e8871fa5f349cfece5330
 F src/sqlite3ext.h 1a1a4f784aa9c3b00edd287940197de52487cd93
-F src/sqliteInt.h 8a7ca32a1563d25629073c3be8d0e3560d46e2fa
+F src/sqliteInt.h be1ab8bc2c295a1bf0ddc9241ea879f455b72df6
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -250,7 +250,7 @@ F src/vtab.c 901791a47318c0562cd0c676a2c6ff1bc530e582
 F src/wal.c 3154756177d6219e233d84291d5b05f4e06ff5e9
 F src/wal.h 66b40bd91bc29a5be1c88ddd1f5ade8f3f48728a
 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
-F src/where.c e169242225ff4742da34e7d8a20243adbf4664e5
+F src/where.c b8ebb50b82578761e5e764c5c16d7693049a523f
 F test/8_3_names.test b93687beebd17f6ebf812405a6833bae5d1f4199
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
@@ -954,10 +954,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5
 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings.sh 2ebae31e1eb352696f3c2f7706a34c084b28c262
-P 78fc94c8d1229a8bdc9390e98b53c57aeef7fc46
-R 274804d4319047cf711d8a55ade8888e
-T *branch * query-planner-tweaks
-T *sym-query-planner-tweaks *
-T -sym-trunk *
+P c8ba8855d8e93cd1e7dbbc9398a5f850fed5a382
+R bebd47644403e6f2ebc393eb54e2f9ac
 U drh
-Z 278da4b2a2802cf77ca6054afa34f6c4
+Z b87fb16f7b3449ea6f690e5d66519d60
index e60dc911be382b67315de97ab46a48e593f8b753..0e29e8359d95cd6e0ba2c630d1d351e1c5f322f5 100644 (file)
@@ -1 +1 @@
-c8ba8855d8e93cd1e7dbbc9398a5f850fed5a382
\ No newline at end of file
+b9d41c3490bf325915227a32b612e6772fb62fa9
\ No newline at end of file
index 17c1de83a98bdec3bb98c917a5bbdec2927bc0fc..2bf1beb8f003fc091745929ff854b1ffdde8ec4a 100644 (file)
@@ -564,7 +564,7 @@ void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
 #ifdef SQLITE_ENABLE_STAT2
   if( pIdx->aSample ){
     int j;
-    for(j=0; j<SQLITE_INDEX_SAMPLES; j++){
+    for(j=0; j<pIdx->nSample; j++){
       IndexSample *p = &pIdx->aSample[j];
       if( p->eType==SQLITE_TEXT || p->eType==SQLITE_BLOB ){
         sqlite3DbFree(db, p->u.z);
@@ -614,6 +614,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
     sqlite3DefaultRowEst(pIdx);
     sqlite3DeleteIndexSamples(db, pIdx);
     pIdx->aSample = 0;
+    pIdx->nSample = 0;
   }
 
   /* Check to make sure the sqlite_stat1 table exists */
@@ -643,7 +644,8 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
     sqlite3_stmt *pStmt = 0;
 
     zSql = sqlite3MPrintf(db, 
-        "SELECT idx,sampleno,sample FROM %Q.sqlite_stat2", sInfo.zDatabase);
+        "SELECT idx, sampleno, sample FROM %Q.sqlite_stat2"
+        " ORDER BY rowid DESC", sInfo.zDatabase);
     if( !zSql ){
       rc = SQLITE_NOMEM;
     }else{
@@ -655,51 +657,48 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
       while( sqlite3_step(pStmt)==SQLITE_ROW ){
         char *zIndex;   /* Index name */
         Index *pIdx;    /* Pointer to the index object */
+        int iSample;
+        int eType;
+        IndexSample *pSample;
 
         zIndex = (char *)sqlite3_column_text(pStmt, 0);
-        pIdx = zIndex ? sqlite3FindIndex(db, zIndex, sInfo.zDatabase) : 0;
-        if( pIdx ){
-          int iSample = sqlite3_column_int(pStmt, 1);
-          if( iSample<SQLITE_INDEX_SAMPLES && iSample>=0 ){
-            int eType = sqlite3_column_type(pStmt, 2);
-
-            if( pIdx->aSample==0 ){
-              static const int sz = sizeof(IndexSample)*SQLITE_INDEX_SAMPLES;
-              pIdx->aSample = (IndexSample *)sqlite3DbMallocRaw(0, sz);
-              if( pIdx->aSample==0 ){
-                db->mallocFailed = 1;
-                break;
-              }
-             memset(pIdx->aSample, 0, sz);
-            }
-
-            assert( pIdx->aSample );
-            {
-              IndexSample *pSample = &pIdx->aSample[iSample];
-              pSample->eType = (u8)eType;
-              if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
-                pSample->u.r = sqlite3_column_double(pStmt, 2);
-              }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
-                const char *z = (const char *)(
-                    (eType==SQLITE_BLOB) ?
-                    sqlite3_column_blob(pStmt, 2):
-                    sqlite3_column_text(pStmt, 2)
-                );
-                int n = sqlite3_column_bytes(pStmt, 2);
-                if( n>24 ){
-                  n = 24;
-                }
-                pSample->nByte = (u8)n;
-                if( n < 1){
-                  pSample->u.z = 0;
-                }else{
-                  pSample->u.z = sqlite3DbStrNDup(0, z, n);
-                  if( pSample->u.z==0 ){
-                    db->mallocFailed = 1;
-                    break;
-                  }
-                }
-              }
+        if( zIndex==0 ) continue;
+        pIdx = sqlite3FindIndex(db, zIndex, sInfo.zDatabase);
+        if( pIdx==0 ) continue;
+        iSample = sqlite3_column_int(pStmt, 1);
+        if( iSample>=SQLITE_MAX_SAMPLES || iSample<0 ) continue;
+        if( pIdx->nSample<=iSample ){
+          IndexSample *pNew;
+          int sz = sizeof(IndexSample)*(iSample+1);
+          pNew = (IndexSample*)sqlite3Realloc(pIdx->aSample, sz);
+          if( pNew==0 ){
+            db->mallocFailed = 1;
+            break;
+          }
+          pIdx->aSample = pNew;
+          pIdx->nSample = iSample+1;
+        }
+        eType = sqlite3_column_type(pStmt, 2);
+        pSample = &pIdx->aSample[iSample];
+        pSample->eType = (u8)eType;
+        if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
+          pSample->u.r = sqlite3_column_double(pStmt, 2);
+        }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
+          const char *z = (const char *)(
+             (eType==SQLITE_BLOB) ?
+              sqlite3_column_blob(pStmt, 2):
+              sqlite3_column_text(pStmt, 2)
+          );
+          int n = sqlite3_column_bytes(pStmt, 2);
+          if( n>24 ) n = 24;
+          pSample->nByte = (u8)n;
+          if( n < 1){
+            pSample->u.z = 0;
+          }else{
+            pSample->u.z = sqlite3DbStrNDup(0, z, n);
+            if( pSample->u.z==0 ){
+              db->mallocFailed = 1;
+              break;
             }
           }
         }
index 9d1c07f0a9cde96d33ad468a752842077b677ae0..9c341292c55798c8808d1d2f01fd6200873a76c6 100644 (file)
@@ -84,6 +84,7 @@
 #ifndef SQLITE_INDEX_SAMPLES
 # define SQLITE_INDEX_SAMPLES 10
 #endif
+#define SQLITE_MAX_SAMPLES 100
 
 /*
 ** The following macros are used to cast pointers to integers and
@@ -1485,6 +1486,7 @@ struct Index {
   u8 onError;      /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
   u8 autoIndex;    /* True if is automatically created (ex: by UNIQUE) */
   u8 bUnordered;   /* Use this index for == or IN queries only */
+  u8 nSample;      /* Number of slots in aSample[] */
   char *zColAff;   /* String defining the affinity of each column */
   Index *pNext;    /* The next index associated with the same table */
   Schema *pSchema; /* Schema containing this index */
index 1f7b709d86c8a4a5daf0237621748a6a362a4af8..dbe6ed2ea0917dd2d2c93bdd02d8e51a3a165079 100644 (file)
@@ -2422,12 +2422,12 @@ static void bestVirtualIndex(
 
 /*
 ** Argument pIdx is a pointer to an index structure that has an array of
-** SQLITE_INDEX_SAMPLES evenly spaced samples of the first indexed column
+** pIdx->nSample evenly spaced samples of the first indexed column
 ** stored in Index.aSample. These samples divide the domain of values stored
-** the index into (SQLITE_INDEX_SAMPLES+1) regions.
+** the index into (pIdx->nSample+1) regions.
 ** Region 0 contains all values less than the first sample value. Region
 ** 1 contains values between the first and second samples.  Region 2 contains
-** values between samples 2 and 3.  And so on.  Region SQLITE_INDEX_SAMPLES
+** values between samples 2 and 3.  And so on.  Region pIdx->nSample
 ** contains values larger than the last sample.
 **
 ** If the index contains many duplicates of a single value, then it is
@@ -2438,7 +2438,7 @@ static void bestVirtualIndex(
 **
 ** If successful, this function determines which of the regions value 
 ** pVal lies in, sets *piRegion to the region index (a value between 0
-** and SQLITE_INDEX_SAMPLES+1, inclusive) and returns SQLITE_OK.
+** and S+1, inclusive) and returns SQLITE_OK.
 ** Or, if an OOM occurs while converting text values between encodings,
 ** SQLITE_NOMEM is returned and *piRegion is undefined.
 */
@@ -2453,12 +2453,14 @@ static int whereRangeRegion(
   assert( roundUp==0 || roundUp==1 );
   if( ALWAYS(pVal) ){
     IndexSample *aSample = pIdx->aSample;
+    int nSample = pIdx->nSample;
     int i = 0;
     int eType = sqlite3_value_type(pVal);
 
+    assert( nSample>0 );
     if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
       double r = sqlite3_value_double(pVal);
-      for(i=0; i<SQLITE_INDEX_SAMPLES; i++){
+      for(i=0; i<nSample; i++){
         if( aSample[i].eType==SQLITE_NULL ) continue;
         if( aSample[i].eType>=SQLITE_TEXT ) break;
         if( roundUp ){
@@ -2470,7 +2472,7 @@ static int whereRangeRegion(
     }else if( eType==SQLITE_NULL ){
       i = 0;
       if( roundUp ){
-        while( i<SQLITE_INDEX_SAMPLES && aSample[i].eType==SQLITE_NULL ) i++;
+        while( i<nSample && aSample[i].eType==SQLITE_NULL ) i++;
       }
     }else{ 
       sqlite3 *db = pParse->db;
@@ -2500,7 +2502,7 @@ static int whereRangeRegion(
       }
       n = sqlite3ValueBytes(pVal, pColl->enc);
 
-      for(i=0; i<SQLITE_INDEX_SAMPLES; i++){
+      for(i=0; i<nSample; i++){
         int c;
         int eSampletype = aSample[i].eType;
         if( eSampletype==SQLITE_NULL || eSampletype<eType ) continue;
@@ -2526,7 +2528,7 @@ static int whereRangeRegion(
       }
     }
 
-    assert( i>=0 && i<=SQLITE_INDEX_SAMPLES );
+    assert( i>=0 && i<=pIdx->nSample );
     *piRegion = i;
   }
   return SQLITE_OK;
@@ -2626,7 +2628,8 @@ static int whereRangeScanEst(
     sqlite3_value *pUpperVal = 0;
     int iEst;
     int iLower = 0;
-    int iUpper = SQLITE_INDEX_SAMPLES;
+    int nSample = p->nSample;
+    int iUpper = p->nSample;
     int roundUpUpper = 0;
     int roundUpLower = 0;
     u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;
@@ -2653,7 +2656,7 @@ static int whereRangeScanEst(
       if( pLower ) iLower = iUpper/2;
     }else if( pUpperVal==0 ){
       rc = whereRangeRegion(pParse, p, pLowerVal, roundUpLower, &iLower);
-      if( pUpper ) iUpper = (iLower + SQLITE_INDEX_SAMPLES + 1)/2;
+      if( pUpper ) iUpper = (iLower + p->nSample + 1)/2;
     }else{
       rc = whereRangeRegion(pParse, p, pUpperVal, roundUpUpper, &iUpper);
       if( rc==SQLITE_OK ){
@@ -2663,12 +2666,13 @@ static int whereRangeScanEst(
     WHERETRACE(("range scan regions: %d..%d\n", iLower, iUpper));
 
     iEst = iUpper - iLower;
-    testcase( iEst==SQLITE_INDEX_SAMPLES );
-    assert( iEst<=SQLITE_INDEX_SAMPLES );
+    testcase( iEst==nSample );
+    assert( iEst<=nSample );
+    assert( nSample>0 );
     if( iEst<1 ){
-      *piEst = 50/SQLITE_INDEX_SAMPLES;
+      *piEst = 50/nSample;
     }else{
-      *piEst = (iEst*100)/SQLITE_INDEX_SAMPLES;
+      *piEst = (iEst*100)/nSample;
     }
     sqlite3ValueFree(pLowerVal);
     sqlite3ValueFree(pUpperVal);
@@ -2718,6 +2722,7 @@ static int whereEqualScanEst(
   double nRowEst;           /* New estimate of the number of rows */
 
   assert( p->aSample!=0 );
+  assert( p->nSample>0 );
   aff = p->pTable->aCol[p->aiColumn[0]].affinity;
   if( pExpr ){
     rc = valueFromExpr(pParse, pExpr, aff, &pRhs);
@@ -2732,10 +2737,10 @@ static int whereEqualScanEst(
   if( rc ) goto whereEqualScanEst_cancel;
   WHERETRACE(("equality scan regions: %d..%d\n", iLower, iUpper));
   if( iLower>=iUpper ){
-    nRowEst = p->aiRowEst[0]/(SQLITE_INDEX_SAMPLES*3);
+    nRowEst = p->aiRowEst[0]/(p->nSample*3);
     if( nRowEst<*pnRow ) *pnRow = nRowEst;
   }else{
-    nRowEst = (iUpper-iLower)*p->aiRowEst[0]/SQLITE_INDEX_SAMPLES;
+    nRowEst = (iUpper-iLower)*p->aiRowEst[0]/p->nSample;
     *pnRow = nRowEst;
   }
 
@@ -2776,14 +2781,16 @@ static int whereInScanEst(
   int nSpan = 0;            /* Number of histogram regions spanned */
   int nSingle = 0;          /* Histogram regions hit by a single value */
   int nNotFound = 0;        /* Count of values that are not constants */
-  int i;                               /* Loop counter */
-  u8 aSpan[SQLITE_INDEX_SAMPLES+1];    /* Histogram regions that are spanned */
-  u8 aSingle[SQLITE_INDEX_SAMPLES+1];  /* Histogram regions hit once */
+  int i;                             /* Loop counter */
+  int nSample = p->nSample;          /* Number of samples */
+  u8 aSpan[SQLITE_MAX_SAMPLES+1];    /* Histogram regions that are spanned */
+  u8 aSingle[SQLITE_MAX_SAMPLES+1];  /* Histogram regions hit once */
 
   assert( p->aSample!=0 );
+  assert( nSample>0 );
   aff = p->pTable->aCol[p->aiColumn[0]].affinity;
-  memset(aSpan, 0, sizeof(aSpan));
-  memset(aSingle, 0, sizeof(aSingle));
+  memset(aSpan, 0, nSample+1);
+  memset(aSingle, 0, nSample+1);
   for(i=0; i<pList->nExpr; i++){
     sqlite3ValueFree(pVal);
     rc = valueFromExpr(pParse, pList->a[i].pExpr, aff, &pVal);
@@ -2799,19 +2806,19 @@ static int whereInScanEst(
     if( iLower>=iUpper ){
       aSingle[iLower] = 1;
     }else{
-      assert( iLower>=0 && iUpper<=SQLITE_INDEX_SAMPLES );
+      assert( iLower>=0 && iUpper<=nSample );
       while( iLower<iUpper ) aSpan[iLower++] = 1;
     }
   }
   if( rc==SQLITE_OK ){
-    for(i=nSpan=0; i<=SQLITE_INDEX_SAMPLES; i++){
+    for(i=nSpan=0; i<=nSample; i++){
       if( aSpan[i] ){
         nSpan++;
       }else if( aSingle[i] ){
         nSingle++;
       }
     }
-    nRowEst = (nSpan*3+nSingle)*p->aiRowEst[0]/(3*SQLITE_INDEX_SAMPLES)
+    nRowEst = (nSpan*3+nSingle)*p->aiRowEst[0]/(3*nSample)
                + nNotFound*p->aiRowEst[1];
     if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0];
     *pnRow = nRowEst;