Cleaner separation of the STAT4-specific logic in the implementation of

ANALYZE.

FossilOrigin-Name: 3df07e5a9a3781a4cf866fc6ee0e5c6f9cd7ca35ce0a6eb3aa7f5f3502e0ffae
This commit is contained in:
drh 2020-03-09 18:26:11 +00:00
parent ccb3781673
commit afa1ecac9b
3 changed files with 68 additions and 69 deletions

View File

@ -1,5 +1,5 @@
C Enhancements\sto\sthe\s".import"\scommand\sof\sthe\sCLI. C Cleaner\sseparation\sof\sthe\sSTAT4-specific\slogic\sin\sthe\simplementation\sof\nANALYZE.
D 2020-03-09T15:39:39.029 D 2020-03-09T18:26:11.821
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -466,7 +466,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c f48a4423c8f198d7f1ae4940f74b606707d05384ac79fb219be8e3323af2a2de F src/alter.c f48a4423c8f198d7f1ae4940f74b606707d05384ac79fb219be8e3323af2a2de
F src/analyze.c b3ceec3fc052df8a96ca8a8c858d455dc5029ba681b4be98bb5c5a9162cfa58c F src/analyze.c 831bb090988477a00d3b4c000746e1b0454dcc93b10b793e6ebe1c47f25d193a
F src/attach.c fa5addce233a2bb2dfdefeee3b37000e154c47214d3269cab1bb331416e330db F src/attach.c fa5addce233a2bb2dfdefeee3b37000e154c47214d3269cab1bb331416e330db
F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06 F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06
F src/backup.c 5e617c087f1c2d6005c2ec694ce80d6e16bc68d906e1b1c556d7c7c2228b636b F src/backup.c 5e617c087f1c2d6005c2ec694ce80d6e16bc68d906e1b1c556d7c7c2228b636b
@ -1860,7 +1860,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 86465c08f4d629a296332a7985937326ac43ea2822c5651bf03862cd79d370fc P cab1834cfc71f71bfed3c5170a0ba40a39385c3b2c50b7c6b6f09cc830dd1b1e
R 59ca84b4f9c863c565a73d91cc01fad5 R c62e646df7b5e5719c4a0602837bf1ef
U drh U drh
Z ca4df02a4f4403d62ad30a31c55381b8 Z 8147aa7ce1e35e16be35124cd1704d38

View File

@ -1 +1 @@
cab1834cfc71f71bfed3c5170a0ba40a39385c3b2c50b7c6b6f09cc830dd1b1e 3df07e5a9a3781a4cf866fc6ee0e5c6f9cd7ca35ce0a6eb3aa7f5f3502e0ffae

View File

@ -256,9 +256,9 @@ static void openStatTable(
** share an instance of the following structure to hold their state ** share an instance of the following structure to hold their state
** information. ** information.
*/ */
typedef struct Stat4Accum Stat4Accum; typedef struct StatAccum StatAccum;
typedef struct Stat4Sample Stat4Sample; typedef struct StatSample StatSample;
struct Stat4Sample { struct StatSample {
tRowcnt *anEq; /* sqlite_stat4.nEq */ tRowcnt *anEq; /* sqlite_stat4.nEq */
tRowcnt *anDLt; /* sqlite_stat4.nDLt */ tRowcnt *anDLt; /* sqlite_stat4.nDLt */
#ifdef SQLITE_ENABLE_STAT4 #ifdef SQLITE_ENABLE_STAT4
@ -273,27 +273,29 @@ struct Stat4Sample {
u32 iHash; /* Tiebreaker hash */ u32 iHash; /* Tiebreaker hash */
#endif #endif
}; };
struct Stat4Accum { struct StatAccum {
sqlite3 *db; /* Database connection, for malloc() */
tRowcnt nRow; /* Number of rows in the entire table */ 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 nCol; /* Number of columns in index + pk/rowid */
int nKeyCol; /* Number of index columns w/o the 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 */ int mxSample; /* Maximum number of samples to accumulate */
Stat4Sample current; /* Current row as a Stat4Sample */
u32 iPrn; /* Pseudo-random number used for sampling */ 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 iMin; /* Index in a[] of entry with minimum score */
int nSample; /* Current number of samples */ int nSample; /* Current number of samples */
int nMaxEqZero; /* Max leading 0 in anEq[] for any a[] entry */ int nMaxEqZero; /* Max leading 0 in anEq[] for any a[] entry */
int iGet; /* Index of current sample accessed by stat_get() */ int iGet; /* Index of current sample accessed by stat_get() */
Stat4Sample *a; /* Array of mxSample Stat4Sample objects */ StatSample *a; /* Array of mxSample StatSample objects */
sqlite3 *db; /* Database connection, for malloc() */ #endif
}; };
/* Reclaim memory used by a Stat4Sample /* Reclaim memory used by a StatSample
*/ */
#ifdef SQLITE_ENABLE_STAT4 #ifdef SQLITE_ENABLE_STAT4
static void sampleClear(sqlite3 *db, Stat4Sample *p){ static void sampleClear(sqlite3 *db, StatSample *p){
assert( db!=0 ); assert( db!=0 );
if( p->nRowid ){ if( p->nRowid ){
sqlite3DbFree(db, p->u.aRowid); sqlite3DbFree(db, p->u.aRowid);
@ -305,7 +307,7 @@ static void sampleClear(sqlite3 *db, Stat4Sample *p){
/* Initialize the BLOB value of a ROWID /* Initialize the BLOB value of a ROWID
*/ */
#ifdef SQLITE_ENABLE_STAT4 #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 ); assert( db!=0 );
if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid); if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
p->u.aRowid = sqlite3DbMallocRawNN(db, n); 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. /* Initialize the INTEGER value of a ROWID.
*/ */
#ifdef SQLITE_ENABLE_STAT4 #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 ); assert( db!=0 );
if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid); if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
p->nRowid = 0; p->nRowid = 0;
@ -334,7 +336,7 @@ static void sampleSetRowidInt64(sqlite3 *db, Stat4Sample *p, i64 iRowid){
** Copy the contents of object (*pFrom) into (*pTo). ** Copy the contents of object (*pFrom) into (*pTo).
*/ */
#ifdef SQLITE_ENABLE_STAT4 #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->isPSample = pFrom->isPSample;
pTo->iCol = pFrom->iCol; pTo->iCol = pFrom->iCol;
pTo->iHash = pFrom->iHash; pTo->iHash = pFrom->iHash;
@ -350,10 +352,10 @@ static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
#endif #endif
/* /*
** Reclaim all memory of a Stat4Accum structure. ** Reclaim all memory of a StatAccum structure.
*/ */
static void stat4Destructor(void *pOld){ static void statAccumDestructor(void *pOld){
Stat4Accum *p = (Stat4Accum*)pOld; StatAccum *p = (StatAccum*)pOld;
#ifdef SQLITE_ENABLE_STAT4 #ifdef SQLITE_ENABLE_STAT4
int i; int i;
for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+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 ** PRIMARY KEY of the table. The covering index that implements the
** original WITHOUT ROWID table as N==K as a special case. ** original WITHOUT ROWID table as N==K as a special case.
** **
** This routine allocates the Stat4Accum object in heap memory. The return ** This routine allocates the StatAccum object in heap memory. The return
** value is a pointer to the Stat4Accum object. The datatype of the ** 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 Stat4Accum ** return value is BLOB, but it is really just a pointer to the StatAccum
** object. ** object.
*/ */
static void statInit( static void statInit(
@ -391,7 +393,7 @@ static void statInit(
int argc, int argc,
sqlite3_value **argv sqlite3_value **argv
){ ){
Stat4Accum *p; StatAccum *p;
int nCol; /* Number of columns in index being sampled */ int nCol; /* Number of columns in index being sampled */
int nKeyCol; /* Number of key columns */ int nKeyCol; /* Number of key columns */
int nColUp; /* nCol rounded up for alignment */ int nColUp; /* nCol rounded up for alignment */
@ -410,13 +412,13 @@ static void statInit(
assert( nKeyCol<=nCol ); assert( nKeyCol<=nCol );
assert( nKeyCol>0 ); assert( nKeyCol>0 );
/* Allocate the space required for the Stat4Accum object */ /* Allocate the space required for the StatAccum object */
n = sizeof(*p) n = sizeof(*p)
+ sizeof(tRowcnt)*nColUp /* Stat4Accum.anEq */ + sizeof(tRowcnt)*nColUp /* StatAccum.anEq */
+ sizeof(tRowcnt)*nColUp /* Stat4Accum.anDLt */ + sizeof(tRowcnt)*nColUp /* StatAccum.anDLt */
#ifdef SQLITE_ENABLE_STAT4 #ifdef SQLITE_ENABLE_STAT4
+ sizeof(tRowcnt)*nColUp /* Stat4Accum.anLt */ + sizeof(tRowcnt)*nColUp /* StatAccum.anLt */
+ sizeof(Stat4Sample)*(nCol+mxSample) /* Stat4Accum.aBest[], a[] */ + sizeof(StatSample)*(nCol+mxSample) /* StatAccum.aBest[], a[] */
+ sizeof(tRowcnt)*3*nColUp*(nCol+mxSample) + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample)
#endif #endif
; ;
@ -445,8 +447,8 @@ static void statInit(
p->current.anLt = &p->current.anEq[nColUp]; p->current.anLt = &p->current.anEq[nColUp];
p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]); p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]);
/* Set up the Stat4Accum.a[] and aBest[] arrays */ /* Set up the StatAccum.a[] and aBest[] arrays */
p->a = (struct Stat4Sample*)&p->current.anLt[nColUp]; p->a = (struct StatSample*)&p->current.anLt[nColUp];
p->aBest = &p->a[mxSample]; p->aBest = &p->a[mxSample];
pSpace = (u8*)(&p->a[mxSample+nCol]); pSpace = (u8*)(&p->a[mxSample+nCol]);
for(i=0; i<(mxSample+nCol); i++){ 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 ** 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 ** (given by the 3rd parameter) is never used and can be any positive
** value. */ ** value. */
sqlite3_result_blob(context, p, sizeof(*p), stat4Destructor); sqlite3_result_blob(context, p, sizeof(*p), statAccumDestructor);
} }
static const FuncDef statInitFuncdef = { static const FuncDef statInitFuncdef = {
2+IsStat4, /* nArg */ 2+IsStat4, /* nArg */
@ -493,9 +495,9 @@ static const FuncDef statInitFuncdef = {
** the anEq[] array from pSample->anEq[pSample->iCol+1] onwards are valid. ** the anEq[] array from pSample->anEq[pSample->iCol+1] onwards are valid.
*/ */
static int sampleIsBetterPost( static int sampleIsBetterPost(
Stat4Accum *pAccum, StatAccum *pAccum,
Stat4Sample *pNew, StatSample *pNew,
Stat4Sample *pOld StatSample *pOld
){ ){
int nCol = pAccum->nCol; int nCol = pAccum->nCol;
int i; int i;
@ -517,9 +519,9 @@ static int sampleIsBetterPost(
** the anEq[] array from pSample->anEq[pSample->iCol] onwards are valid. ** the anEq[] array from pSample->anEq[pSample->iCol] onwards are valid.
*/ */
static int sampleIsBetter( static int sampleIsBetter(
Stat4Accum *pAccum, StatAccum *pAccum,
Stat4Sample *pNew, StatSample *pNew,
Stat4Sample *pOld StatSample *pOld
){ ){
tRowcnt nEqNew = pNew->anEq[pNew->iCol]; tRowcnt nEqNew = pNew->anEq[pNew->iCol];
tRowcnt nEqOld = pOld->anEq[pOld->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, ** Copy the contents of sample *pNew into the p->a[] array. If necessary,
** remove the least desirable sample from p->a[] to make room. ** remove the least desirable sample from p->a[] to make room.
*/ */
static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ static void sampleInsert(StatAccum *p, StatSample *pNew, int nEqZero){
Stat4Sample *pSample = 0; StatSample *pSample = 0;
int i; int i;
assert( IsStat4 || nEqZero==0 ); assert( IsStat4 || nEqZero==0 );
/* Stat4Accum.nMaxEqZero is set to the maximum number of leading 0 /* StatAccum.nMaxEqZero is set to the maximum number of leading 0
** values in the anEq[] array of any sample in Stat4Accum.a[]. In ** values in the anEq[] array of any sample in StatAccum.a[]. In
** other words, if nMaxEqZero is n, then it is guaranteed that there ** 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 ){ if( nEqZero>p->nMaxEqZero ){
p->nMaxEqZero = nEqZero; p->nMaxEqZero = nEqZero;
} }
if( pNew->isPSample==0 ){ if( pNew->isPSample==0 ){
Stat4Sample *pUpgrade = 0; StatSample *pUpgrade = 0;
assert( pNew->anEq[pNew->iCol]>0 ); assert( pNew->anEq[pNew->iCol]>0 );
/* This sample is being added because the prefix that ends in column /* 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 ** this one. Instead, upgrade the priority of the highest priority
** existing sample that shares this prefix. */ ** existing sample that shares this prefix. */
for(i=p->nSample-1; i>=0; i--){ 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->anEq[pNew->iCol]==0 ){
if( pOld->isPSample ) return; if( pOld->isPSample ) return;
assert( pOld->iCol>pNew->iCol ); 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 necessary, remove sample iMin to make room for the new sample. */
if( p->nSample>=p->mxSample ){ if( p->nSample>=p->mxSample ){
Stat4Sample *pMin = &p->a[p->iMin]; StatSample *pMin = &p->a[p->iMin];
tRowcnt *anEq = pMin->anEq; tRowcnt *anEq = pMin->anEq;
tRowcnt *anLt = pMin->anLt; tRowcnt *anLt = pMin->anLt;
tRowcnt *anDLt = pMin->anDLt; tRowcnt *anDLt = pMin->anDLt;
@ -624,20 +626,20 @@ find_new_min:
} }
#endif /* SQLITE_ENABLE_STAT4 */ #endif /* SQLITE_ENABLE_STAT4 */
#ifdef SQLITE_ENABLE_STAT4
/* /*
** Field iChng of the index being scanned has changed. So at this point ** 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 ** p->current contains a sample that reflects the previous row of the
** index. The value of anEq[iChng] and subsequent anEq[] elements are ** index. The value of anEq[iChng] and subsequent anEq[] elements are
** correct at this point. ** correct at this point.
*/ */
static void samplePushPrevious(Stat4Accum *p, int iChng){ static void samplePushPrevious(StatAccum *p, int iChng){
#ifdef SQLITE_ENABLE_STAT4
int i; int i;
/* Check if any samples from the aBest[] array should be pushed /* Check if any samples from the aBest[] array should be pushed
** into IndexSample.a[] at this point. */ ** into IndexSample.a[] at this point. */
for(i=(p->nCol-2); i>=iChng; i--){ 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]; pBest->anEq[i] = p->current.anEq[i];
if( p->nSample<p->mxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){ if( p->nSample<p->mxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){
sampleInsert(p, pBest, i); sampleInsert(p, pBest, i);
@ -661,25 +663,20 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){
} }
p->nMaxEqZero = 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) ** Implementation of the stat_push SQL function: stat_push(P,C,R)
** Arguments: ** 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 ** C Index of left-most column to differ from previous row
** R Rowid for the current row. Might be a key record for ** R Rowid for the current row. Might be a key record for
** WITHOUT ROWID tables. ** WITHOUT ROWID tables.
** **
** This SQL function always returns NULL. It's purpose it to accumulate ** 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 ** index being analyzed. The stat_get() SQL function will later be used to
** extract relevant information for constructing the sqlite_statN tables. ** extract relevant information for constructing the sqlite_statN tables.
** **
@ -693,7 +690,7 @@ static void statPush(
int i; int i;
/* The three function arguments */ /* 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]); int iChng = sqlite3_value_int(argv[1]);
UNUSED_PARAMETER( argc ); UNUSED_PARAMETER( argc );
@ -706,7 +703,9 @@ static void statPush(
for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1; for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
}else{ }else{
/* Second and subsequent calls get processed here */ /* Second and subsequent calls get processed here */
#ifdef SQLITE_ENABLE_STAT4
samplePushPrevious(p, iChng); samplePushPrevious(p, iChng);
#endif
/* Update anDLt[], anLt[] and anEq[] to reflect the values that apply /* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
** to the current row of the index. */ ** 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 ** Implementation of the stat_get(P,J) SQL function. This routine is
** used to query statistical information that has been gathered into ** used to query statistical information that has been gathered into
** the Stat4Accum object by prior calls to stat_push(). The P parameter ** the StatAccum object by prior calls to stat_push(). The P parameter
** has type BLOB but it is really just a pointer to the Stat4Accum object. ** has type BLOB but it is really just a pointer to the StatAccum object.
** The content to returned is determined by the parameter J ** The content to returned is determined by the parameter J
** which is one of the STAT_GET_xxxx values defined above. ** 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 ** The stat_get(P,J) function is not available to generic SQL. It is
** inserted as part of a manually constructed bytecode program. (See ** inserted as part of a manually constructed bytecode program. (See
** the callStatGet() routine below.) It is guaranteed that the P ** 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. ** NULL.
** **
** If STAT4 is not enabled, then J is always ** If STAT4 is not enabled, then J is always
@ -796,7 +795,7 @@ static void statGet(
int argc, int argc,
sqlite3_value **argv sqlite3_value **argv
){ ){
Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]); StatAccum *p = (StatAccum*)sqlite3_value_blob(argv[0]);
#ifdef SQLITE_ENABLE_STAT4 #ifdef SQLITE_ENABLE_STAT4
/* STAT4 has a parameter on this routine. */ /* STAT4 has a parameter on this routine. */
int eCall = sqlite3_value_int(argv[1]); 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 ** 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 ** entries in the index. There is one additional integer in the list
** for each indexed column. This additional integer is an estimate of ** 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, ** 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 ** if the index is on columns (a,b) and the sqlite_stat1 value is
** "100 10 2", then SQLite estimates that: ** "100 10 2", then SQLite estimates that:
@ -860,7 +859,7 @@ static void statGet(
p->iGet = 0; p->iGet = 0;
} }
if( p->iGet<p->nSample ){ if( p->iGet<p->nSample ){
Stat4Sample *pS = p->a + p->iGet; StatSample *pS = p->a + p->iGet;
if( pS->nRowid==0 ){ if( pS->nRowid==0 ){
sqlite3_result_int64(context, pS->u.iRowid); sqlite3_result_int64(context, pS->u.iRowid);
}else{ }else{
@ -951,7 +950,7 @@ static void analyzeOneTable(
int iDb; /* Index of database containing pTab */ int iDb; /* Index of database containing pTab */
u8 needTableCnt = 1; /* True to count the table */ u8 needTableCnt = 1; /* True to count the table */
int regNewRowid = iMem++; /* Rowid for the inserted record */ 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 */ int regChng = iMem++; /* Index of changed index field */
#ifdef SQLITE_ENABLE_STAT4 #ifdef SQLITE_ENABLE_STAT4
int regRowid = iMem++; /* Rowid argument passed to stat_push() */ int regRowid = iMem++; /* Rowid argument passed to stat_push() */