** 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
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);
/* 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);
/* 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;
** 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;
#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);
** 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(
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 */
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
;
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++){
** 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 */
** 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;
** 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];
** 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
** 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 );
/* 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;
}
#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);
}
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.
**
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 );
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. */
/*
** 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
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]);
** 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:
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{
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() */