]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Cleaner separation of the STAT4-specific logic in the implementation of
authordrh <drh@noemail.net>
Mon, 9 Mar 2020 18:26:11 +0000 (18:26 +0000)
committerdrh <drh@noemail.net>
Mon, 9 Mar 2020 18:26:11 +0000 (18:26 +0000)
ANALYZE.

FossilOrigin-Name: 3df07e5a9a3781a4cf866fc6ee0e5c6f9cd7ca35ce0a6eb3aa7f5f3502e0ffae

manifest
manifest.uuid
src/analyze.c

index 04435eea739ea16c013a219e2e1e3f924e8fd919..9f3c8dd408a1894b95b989f7eee90f7629b99bf5 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Enhancements\sto\sthe\s".import"\scommand\sof\sthe\sCLI.
-D 2020-03-09T15:39:39.029
+C Cleaner\sseparation\sof\sthe\sSTAT4-specific\slogic\sin\sthe\simplementation\sof\nANALYZE.
+D 2020-03-09T18:26:11.821
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -466,7 +466,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
 F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
 F src/alter.c f48a4423c8f198d7f1ae4940f74b606707d05384ac79fb219be8e3323af2a2de
-F src/analyze.c b3ceec3fc052df8a96ca8a8c858d455dc5029ba681b4be98bb5c5a9162cfa58c
+F src/analyze.c 831bb090988477a00d3b4c000746e1b0454dcc93b10b793e6ebe1c47f25d193a
 F src/attach.c fa5addce233a2bb2dfdefeee3b37000e154c47214d3269cab1bb331416e330db
 F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06
 F src/backup.c 5e617c087f1c2d6005c2ec694ce80d6e16bc68d906e1b1c556d7c7c2228b636b
@@ -1860,7 +1860,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 86465c08f4d629a296332a7985937326ac43ea2822c5651bf03862cd79d370fc
-R 59ca84b4f9c863c565a73d91cc01fad5
+P cab1834cfc71f71bfed3c5170a0ba40a39385c3b2c50b7c6b6f09cc830dd1b1e
+R c62e646df7b5e5719c4a0602837bf1ef
 U drh
-Z ca4df02a4f4403d62ad30a31c55381b8
+Z 8147aa7ce1e35e16be35124cd1704d38
index 39e7d10901d5270a48e0dd749af9e54d75f80d0e..e08451b6b24e5a2833cbebe49753a2d444c7cfef 100644 (file)
@@ -1 +1 @@
-cab1834cfc71f71bfed3c5170a0ba40a39385c3b2c50b7c6b6f09cc830dd1b1e
\ No newline at end of file
+3df07e5a9a3781a4cf866fc6ee0e5c6f9cd7ca35ce0a6eb3aa7f5f3502e0ffae
\ No newline at end of file
index 2a071ef126b3844f85ee8a51b90f82df87f1987d..eee71fbbde481612e8e329eb492474aaf98dfb86 100644 (file)
@@ -256,9 +256,9 @@ static void openStatTable(
 ** share an instance of the following structure to hold their state
 ** information.
 */
-typedef struct Stat4Accum Stat4Accum;
-typedef struct Stat4Sample Stat4Sample;
-struct Stat4Sample {
+typedef struct StatAccum StatAccum;
+typedef struct StatSample StatSample;
+struct StatSample {
   tRowcnt *anEq;                  /* sqlite_stat4.nEq */
   tRowcnt *anDLt;                 /* sqlite_stat4.nDLt */
 #ifdef SQLITE_ENABLE_STAT4
@@ -273,27 +273,29 @@ struct Stat4Sample {
   u32 iHash;                      /* Tiebreaker hash */
 #endif
 };                                                    
-struct Stat4Accum {
+struct StatAccum {
+  sqlite3 *db;              /* Database connection, for malloc() */
   tRowcnt nRow;             /* Number of rows in the entire table */
-  tRowcnt nPSample;         /* How often to do a periodic sample */
   int nCol;                 /* Number of columns in index + pk/rowid */
   int nKeyCol;              /* Number of index columns w/o the pk/rowid */
+  StatSample current;       /* Current row as a StatSample */
+#ifdef SQLITE_ENABLE_STAT4
+  tRowcnt nPSample;         /* How often to do a periodic sample */
   int mxSample;             /* Maximum number of samples to accumulate */
-  Stat4Sample current;      /* Current row as a Stat4Sample */
   u32 iPrn;                 /* Pseudo-random number used for sampling */
-  Stat4Sample *aBest;       /* Array of nCol best samples */
+  StatSample *aBest;        /* Array of nCol best samples */
   int iMin;                 /* Index in a[] of entry with minimum score */
   int nSample;              /* Current number of samples */
   int nMaxEqZero;           /* Max leading 0 in anEq[] for any a[] entry */
   int iGet;                 /* Index of current sample accessed by stat_get() */
-  Stat4Sample *a;           /* Array of mxSample Stat4Sample objects */
-  sqlite3 *db;              /* Database connection, for malloc() */
+  StatSample *a;            /* Array of mxSample StatSample objects */
+#endif
 };
 
-/* Reclaim memory used by a Stat4Sample
+/* Reclaim memory used by a StatSample
 */
 #ifdef SQLITE_ENABLE_STAT4
-static void sampleClear(sqlite3 *db, Stat4Sample *p){
+static void sampleClear(sqlite3 *db, StatSample *p){
   assert( db!=0 );
   if( p->nRowid ){
     sqlite3DbFree(db, p->u.aRowid);
@@ -305,7 +307,7 @@ static void sampleClear(sqlite3 *db, Stat4Sample *p){
 /* Initialize the BLOB value of a ROWID
 */
 #ifdef SQLITE_ENABLE_STAT4
-static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){
+static void sampleSetRowid(sqlite3 *db, StatSample *p, int n, const u8 *pData){
   assert( db!=0 );
   if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
   p->u.aRowid = sqlite3DbMallocRawNN(db, n);
@@ -321,7 +323,7 @@ static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){
 /* Initialize the INTEGER value of a ROWID.
 */
 #ifdef SQLITE_ENABLE_STAT4
-static void sampleSetRowidInt64(sqlite3 *db, Stat4Sample *p, i64 iRowid){
+static void sampleSetRowidInt64(sqlite3 *db, StatSample *p, i64 iRowid){
   assert( db!=0 );
   if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
   p->nRowid = 0;
@@ -334,7 +336,7 @@ static void sampleSetRowidInt64(sqlite3 *db, Stat4Sample *p, i64 iRowid){
 ** Copy the contents of object (*pFrom) into (*pTo).
 */
 #ifdef SQLITE_ENABLE_STAT4
-static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
+static void sampleCopy(StatAccum *p, StatSample *pTo, StatSample *pFrom){
   pTo->isPSample = pFrom->isPSample;
   pTo->iCol = pFrom->iCol;
   pTo->iHash = pFrom->iHash;
@@ -350,10 +352,10 @@ static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
 #endif
 
 /*
-** Reclaim all memory of a Stat4Accum structure.
+** Reclaim all memory of a StatAccum structure.
 */
-static void stat4Destructor(void *pOld){
-  Stat4Accum *p = (Stat4Accum*)pOld;
+static void statAccumDestructor(void *pOld){
+  StatAccum *p = (StatAccum*)pOld;
 #ifdef SQLITE_ENABLE_STAT4
   int i;
   for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+i);
@@ -381,9 +383,9 @@ static void stat4Destructor(void *pOld){
 ** PRIMARY KEY of the table.  The covering index that implements the
 ** original WITHOUT ROWID table as N==K as a special case.
 **
-** This routine allocates the Stat4Accum object in heap memory. The return 
-** value is a pointer to the Stat4Accum object.  The datatype of the
-** return value is BLOB, but it is really just a pointer to the Stat4Accum
+** This routine allocates the StatAccum object in heap memory. The return 
+** value is a pointer to the StatAccum object.  The datatype of the
+** return value is BLOB, but it is really just a pointer to the StatAccum
 ** object.
 */
 static void statInit(
@@ -391,7 +393,7 @@ static void statInit(
   int argc,
   sqlite3_value **argv
 ){
-  Stat4Accum *p;
+  StatAccum *p;
   int nCol;                       /* Number of columns in index being sampled */
   int nKeyCol;                    /* Number of key columns */
   int nColUp;                     /* nCol rounded up for alignment */
@@ -410,13 +412,13 @@ static void statInit(
   assert( nKeyCol<=nCol );
   assert( nKeyCol>0 );
 
-  /* Allocate the space required for the Stat4Accum object */
+  /* Allocate the space required for the StatAccum object */
   n = sizeof(*p) 
-    + sizeof(tRowcnt)*nColUp                  /* Stat4Accum.anEq */
-    + sizeof(tRowcnt)*nColUp                  /* Stat4Accum.anDLt */
+    + sizeof(tRowcnt)*nColUp                  /* StatAccum.anEq */
+    + sizeof(tRowcnt)*nColUp                  /* StatAccum.anDLt */
 #ifdef SQLITE_ENABLE_STAT4
-    + sizeof(tRowcnt)*nColUp                  /* Stat4Accum.anLt */
-    + sizeof(Stat4Sample)*(nCol+mxSample)     /* Stat4Accum.aBest[], a[] */
+    + sizeof(tRowcnt)*nColUp                  /* StatAccum.anLt */
+    + sizeof(StatSample)*(nCol+mxSample)      /* StatAccum.aBest[], a[] */
     + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample)
 #endif
   ;
@@ -445,8 +447,8 @@ static void statInit(
     p->current.anLt = &p->current.anEq[nColUp];
     p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]);
   
-    /* Set up the Stat4Accum.a[] and aBest[] arrays */
-    p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
+    /* Set up the StatAccum.a[] and aBest[] arrays */
+    p->a = (struct StatSample*)&p->current.anLt[nColUp];
     p->aBest = &p->a[mxSample];
     pSpace = (u8*)(&p->a[mxSample+nCol]);
     for(i=0; i<(mxSample+nCol); i++){
@@ -466,7 +468,7 @@ static void statInit(
   ** only the pointer (the 2nd parameter) matters.  The size of the object
   ** (given by the 3rd parameter) is never used and can be any positive
   ** value. */
-  sqlite3_result_blob(context, p, sizeof(*p), stat4Destructor);
+  sqlite3_result_blob(context, p, sizeof(*p), statAccumDestructor);
 }
 static const FuncDef statInitFuncdef = {
   2+IsStat4,       /* nArg */
@@ -493,9 +495,9 @@ static const FuncDef statInitFuncdef = {
 ** the anEq[] array from pSample->anEq[pSample->iCol+1] onwards are valid. 
 */
 static int sampleIsBetterPost(
-  Stat4Accum *pAccum, 
-  Stat4Sample *pNew, 
-  Stat4Sample *pOld
+  StatAccum *pAccum, 
+  StatSample *pNew, 
+  StatSample *pOld
 ){
   int nCol = pAccum->nCol;
   int i;
@@ -517,9 +519,9 @@ static int sampleIsBetterPost(
 ** the anEq[] array from pSample->anEq[pSample->iCol] onwards are valid. 
 */
 static int sampleIsBetter(
-  Stat4Accum *pAccum, 
-  Stat4Sample *pNew, 
-  Stat4Sample *pOld
+  StatAccum *pAccum, 
+  StatSample *pNew, 
+  StatSample *pOld
 ){
   tRowcnt nEqNew = pNew->anEq[pNew->iCol];
   tRowcnt nEqOld = pOld->anEq[pOld->iCol];
@@ -539,21 +541,21 @@ static int sampleIsBetter(
 ** Copy the contents of sample *pNew into the p->a[] array. If necessary,
 ** remove the least desirable sample from p->a[] to make room.
 */
-static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
-  Stat4Sample *pSample = 0;
+static void sampleInsert(StatAccum *p, StatSample *pNew, int nEqZero){
+  StatSample *pSample = 0;
   int i;
 
   assert( IsStat4 || nEqZero==0 );
 
-  /* Stat4Accum.nMaxEqZero is set to the maximum number of leading 0
-  ** values in the anEq[] array of any sample in Stat4Accum.a[]. In
+  /* StatAccum.nMaxEqZero is set to the maximum number of leading 0
+  ** values in the anEq[] array of any sample in StatAccum.a[]. In
   ** other words, if nMaxEqZero is n, then it is guaranteed that there
-  ** are no samples with Stat4Sample.anEq[m]==0 for (m>=n). */
+  ** are no samples with StatSample.anEq[m]==0 for (m>=n). */
   if( nEqZero>p->nMaxEqZero ){
     p->nMaxEqZero = nEqZero;
   }
   if( pNew->isPSample==0 ){
-    Stat4Sample *pUpgrade = 0;
+    StatSample *pUpgrade = 0;
     assert( pNew->anEq[pNew->iCol]>0 );
 
     /* This sample is being added because the prefix that ends in column 
@@ -562,7 +564,7 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
     ** this one. Instead, upgrade the priority of the highest priority
     ** existing sample that shares this prefix.  */
     for(i=p->nSample-1; i>=0; i--){
-      Stat4Sample *pOld = &p->a[i];
+      StatSample *pOld = &p->a[i];
       if( pOld->anEq[pNew->iCol]==0 ){
         if( pOld->isPSample ) return;
         assert( pOld->iCol>pNew->iCol );
@@ -581,7 +583,7 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
 
   /* If necessary, remove sample iMin to make room for the new sample. */
   if( p->nSample>=p->mxSample ){
-    Stat4Sample *pMin = &p->a[p->iMin];
+    StatSample *pMin = &p->a[p->iMin];
     tRowcnt *anEq = pMin->anEq;
     tRowcnt *anLt = pMin->anLt;
     tRowcnt *anDLt = pMin->anDLt;
@@ -624,20 +626,20 @@ find_new_min:
 }
 #endif /* SQLITE_ENABLE_STAT4 */
 
+#ifdef SQLITE_ENABLE_STAT4
 /*
 ** Field iChng of the index being scanned has changed. So at this point
 ** p->current contains a sample that reflects the previous row of the
 ** index. The value of anEq[iChng] and subsequent anEq[] elements are
 ** correct at this point.
 */
-static void samplePushPrevious(Stat4Accum *p, int iChng){
-#ifdef SQLITE_ENABLE_STAT4
+static void samplePushPrevious(StatAccum *p, int iChng){
   int i;
 
   /* Check if any samples from the aBest[] array should be pushed
   ** into IndexSample.a[] at this point.  */
   for(i=(p->nCol-2); i>=iChng; i--){
-    Stat4Sample *pBest = &p->aBest[i];
+    StatSample *pBest = &p->aBest[i];
     pBest->anEq[i] = p->current.anEq[i];
     if( p->nSample<p->mxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){
       sampleInsert(p, pBest, i);
@@ -661,25 +663,20 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){
     }
     p->nMaxEqZero = iChng;
   }
-#endif
-
-#ifndef SQLITE_ENABLE_STAT4
-  UNUSED_PARAMETER( p );
-  UNUSED_PARAMETER( iChng );
-#endif
 }
+#endif /* SQLITE_ENABLE_STAT4 */
 
 /*
 ** Implementation of the stat_push SQL function:  stat_push(P,C,R)
 ** Arguments:
 **
-**    P     Pointer to the Stat4Accum object created by stat_init()
+**    P     Pointer to the StatAccum object created by stat_init()
 **    C     Index of left-most column to differ from previous row
 **    R     Rowid for the current row.  Might be a key record for
 **          WITHOUT ROWID tables.
 **
 ** This SQL function always returns NULL.  It's purpose it to accumulate
-** statistical data and/or samples in the Stat4Accum object about the
+** statistical data and/or samples in the StatAccum object about the
 ** index being analyzed.  The stat_get() SQL function will later be used to
 ** extract relevant information for constructing the sqlite_statN tables.
 **
@@ -693,7 +690,7 @@ static void statPush(
   int i;
 
   /* The three function arguments */
-  Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
+  StatAccum *p = (StatAccum*)sqlite3_value_blob(argv[0]);
   int iChng = sqlite3_value_int(argv[1]);
 
   UNUSED_PARAMETER( argc );
@@ -706,7 +703,9 @@ static void statPush(
     for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
   }else{
     /* Second and subsequent calls get processed here */
+#ifdef SQLITE_ENABLE_STAT4
     samplePushPrevious(p, iChng);
+#endif
 
     /* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
     ** to the current row of the index. */
@@ -775,15 +774,15 @@ static const FuncDef statPushFuncdef = {
 /*
 ** Implementation of the stat_get(P,J) SQL function.  This routine is
 ** used to query statistical information that has been gathered into
-** the Stat4Accum object by prior calls to stat_push().  The P parameter
-** has type BLOB but it is really just a pointer to the Stat4Accum object.
+** the StatAccum object by prior calls to stat_push().  The P parameter
+** has type BLOB but it is really just a pointer to the StatAccum object.
 ** The content to returned is determined by the parameter J
 ** which is one of the STAT_GET_xxxx values defined above.
 **
 ** The stat_get(P,J) function is not available to generic SQL.  It is
 ** inserted as part of a manually constructed bytecode program.  (See
 ** the callStatGet() routine below.)  It is guaranteed that the P
-** parameter will always be a poiner to a Stat4Accum object, never a
+** parameter will always be a pointer to a StatAccum object, never a
 ** NULL.
 **
 ** If STAT4 is not enabled, then J is always
@@ -796,7 +795,7 @@ static void statGet(
   int argc,
   sqlite3_value **argv
 ){
-  Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
+  StatAccum *p = (StatAccum*)sqlite3_value_blob(argv[0]);
 #ifdef SQLITE_ENABLE_STAT4
   /* STAT4 has a parameter on this routine. */
   int eCall = sqlite3_value_int(argv[1]);
@@ -817,7 +816,7 @@ static void statGet(
     ** the index. The first integer in the list is the total number of 
     ** entries in the index. There is one additional integer in the list 
     ** for each indexed column. This additional integer is an estimate of
-    ** the number of rows matched by a stabbing query on the index using
+    ** the number of rows matched by a equality query on the index using
     ** a key with the corresponding number of fields. In other words,
     ** if the index is on columns (a,b) and the sqlite_stat1 value is 
     ** "100 10 2", then SQLite estimates that:
@@ -860,7 +859,7 @@ static void statGet(
       p->iGet = 0;
     }
     if( p->iGet<p->nSample ){
-      Stat4Sample *pS = p->a + p->iGet;
+      StatSample *pS = p->a + p->iGet;
       if( pS->nRowid==0 ){
         sqlite3_result_int64(context, pS->u.iRowid);
       }else{
@@ -951,7 +950,7 @@ static void analyzeOneTable(
   int iDb;                     /* Index of database containing pTab */
   u8 needTableCnt = 1;         /* True to count the table */
   int regNewRowid = iMem++;    /* Rowid for the inserted record */
-  int regStat4 = iMem++;       /* Register to hold Stat4Accum object */
+  int regStat4 = iMem++;       /* Register to hold StatAccum object */
   int regChng = iMem++;        /* Index of changed index field */
 #ifdef SQLITE_ENABLE_STAT4
   int regRowid = iMem++;       /* Rowid argument passed to stat_push() */