mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
Reduce the amount of code run and memory used for ANALYZE in the common case
where neither STAT3 and STAT4 are enabled. FossilOrigin-Name: 9d1424c91a21ed740aca53e437b8f7c1f0823c03
This commit is contained in:
16
manifest
16
manifest
@@ -1,5 +1,5 @@
|
||||
C Update\ssqlite3.pc.in\sto\suse\s@PACKAGE_VERSION@\sinstead\sof\s@RELEASE@.
|
||||
D 2013-08-27T15:41:09.212
|
||||
C Reduce\sthe\samount\sof\scode\srun\sand\smemory\sused\sfor\sANALYZE\sin\sthe\scommon\scase\nwhere\sneither\sSTAT3\sand\sSTAT4\sare\senabled.
|
||||
D 2013-08-27T20:16:48.420
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@@ -157,7 +157,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
|
||||
F src/analyze.c ce2a3385ac05f61e07d384b1c7e8c52e6ef1a3a6
|
||||
F src/analyze.c f1dbc79cbe97f960b20dfc3d24143dff988db41d
|
||||
F src/attach.c fea00cab11c854646a27641a263f5876569a51f9
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3
|
||||
@@ -221,7 +221,7 @@ F src/shell.c 00a23311466829d9b77f0be4f7cedee9328279db
|
||||
F src/sqlite.h.in bd1451ba1ab681022a53bccc3c39580ba094a3ff
|
||||
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h f3636620ad376f65bdbbf5e183f0e4309cb7526e
|
||||
F src/sqliteInt.h 97b1005b812048469c80ec9394a77e0ad83ea9c0
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@@ -1107,7 +1107,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
|
||||
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
||||
P 959bb5acdc3b4e2b481e3c38f20867131bfc9dbc
|
||||
R 2e3b4a437bff68926c962c9ab6977363
|
||||
U dan
|
||||
Z 665cf10c770598d3c963d389b4e25d18
|
||||
P 2460dfd8825d251e622e866e8dc1c0bf7fe7ec9f
|
||||
R d4ca9812963b4361724d44342b635223
|
||||
U drh
|
||||
Z 6faf42c735288a2cfa68556541b907cb
|
||||
|
||||
@@ -1 +1 @@
|
||||
2460dfd8825d251e622e866e8dc1c0bf7fe7ec9f
|
||||
9d1424c91a21ed740aca53e437b8f7c1f0823c03
|
||||
238
src/analyze.c
238
src/analyze.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** 2005 July 8
|
||||
** 2005-07-08
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
@@ -31,7 +31,9 @@
|
||||
** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3
|
||||
** is a superset of sqlite_stat2. The sqlite_stat4 is an enhanced
|
||||
** version of sqlite_stat3 and is only available when compiled with
|
||||
** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.0 and later.
|
||||
** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.0 and later. It is
|
||||
** not possible to enable both STAT3 and STAT4 at the same time. If they
|
||||
** are both enabled, then STAT4 is precedence.
|
||||
**
|
||||
** For most applications, sqlite_stat1 provides all the statisics required
|
||||
** for the query planner to make good choices.
|
||||
@@ -152,23 +154,23 @@
|
||||
# define IsStat4 0
|
||||
# define IsStat3 0
|
||||
# undef SQLITE_ENABLE_STAT34
|
||||
# undef SQLITE_STAT4_SAMPLES
|
||||
# define SQLITE_STAT4_SAMPLES 1
|
||||
#endif
|
||||
#define IsStat34 (IsStat3+IsStat4) /* 1 for STAT3 or STAT4. 0 otherwise */
|
||||
|
||||
/*
|
||||
** This routine generates code that opens the sqlite_stat1 table for
|
||||
** writing with cursor iStatCur. If the library was built with the
|
||||
** SQLITE_ENABLE_STAT4 macro defined, then the sqlite_stat4 table is
|
||||
** opened for writing using cursor (iStatCur+1)
|
||||
** This routine generates code that opens the sqlite_statN tables.
|
||||
** The sqlite_stat1 table is always relevant. sqlite_stat2 is now
|
||||
** obsolete. sqlite_stat3 and sqlite_stat4 are only opened when
|
||||
** appropriate compile-time options are provided.
|
||||
**
|
||||
** If the sqlite_stat1 tables does not previously exist, it is created.
|
||||
** Similarly, if the sqlite_stat4 table does not exist and the library
|
||||
** is compiled with SQLITE_ENABLE_STAT4 defined, it is created.
|
||||
** If the sqlite_statN tables do not previously exist, it is created.
|
||||
**
|
||||
** Argument zWhere may be a pointer to a buffer containing a table name,
|
||||
** or it may be a NULL pointer. If it is not NULL, then all entries in
|
||||
** the sqlite_stat1 and (if applicable) sqlite_stat4 tables associated
|
||||
** with the named table are deleted. If zWhere==0, then code is generated
|
||||
** to delete all stat table entries.
|
||||
** the sqlite_statN tables associated with the named table are deleted.
|
||||
** If zWhere==0, then code is generated to delete all stat table entries.
|
||||
*/
|
||||
static void openStatTable(
|
||||
Parse *pParse, /* Parsing context */
|
||||
@@ -188,16 +190,18 @@ static void openStatTable(
|
||||
#elif defined(SQLITE_ENABLE_STAT3)
|
||||
{ "sqlite_stat3", "tbl,idx,neq,nlt,ndlt,sample" },
|
||||
{ "sqlite_stat4", 0 },
|
||||
#else
|
||||
{ "sqlite_stat3", 0 },
|
||||
{ "sqlite_stat4", 0 },
|
||||
#endif
|
||||
};
|
||||
|
||||
int aRoot[] = {0, 0};
|
||||
u8 aCreateTbl[] = {0, 0};
|
||||
|
||||
int i;
|
||||
sqlite3 *db = pParse->db;
|
||||
Db *pDb;
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
int aRoot[ArraySize(aTable)];
|
||||
u8 aCreateTbl[ArraySize(aTable)];
|
||||
|
||||
if( v==0 ) return;
|
||||
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
||||
assert( sqlite3VdbeDb(v)==db );
|
||||
@@ -211,7 +215,7 @@ static void openStatTable(
|
||||
Table *pStat;
|
||||
if( (pStat = sqlite3FindTable(db, zTab, pDb->zName))==0 ){
|
||||
if( aTable[i].zCols ){
|
||||
/* The sqlite_stat[12] table does not exist. Create it. Note that a
|
||||
/* The sqlite_statN table does not exist. Create it. Note that a
|
||||
** side-effect of the CREATE TABLE statement is to leave the rootpage
|
||||
** of the new table in register pParse->regRoot. This is important
|
||||
** because the OpenWrite opcode below will be needing it. */
|
||||
@@ -226,6 +230,7 @@ static void openStatTable(
|
||||
** associated with the table zWhere. If zWhere is NULL, delete the
|
||||
** entire contents of the table. */
|
||||
aRoot[i] = pStat->tnum;
|
||||
aCreateTbl[i] = 0;
|
||||
sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab);
|
||||
if( zWhere ){
|
||||
sqlite3NestedParse(pParse,
|
||||
@@ -239,11 +244,14 @@ static void openStatTable(
|
||||
}
|
||||
|
||||
/* Open the sqlite_stat[134] tables for writing. */
|
||||
for(i=0; i<ArraySize(aRoot); i++){
|
||||
sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb);
|
||||
sqlite3VdbeChangeP4(v, -1, (char *)3, P4_INT32);
|
||||
sqlite3VdbeChangeP5(v, aCreateTbl[i]);
|
||||
if( !IsStat3 && !IsStat4 ) break;
|
||||
for(i=0; i<ArraySize(aTable); i++){
|
||||
if( aTable[i].zCols ){
|
||||
sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb);
|
||||
sqlite3VdbeChangeP4(v, -1, (char *)3, P4_INT32);
|
||||
sqlite3VdbeChangeP5(v, aCreateTbl[i]);
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,13 +270,15 @@ static void openStatTable(
|
||||
typedef struct Stat4Accum Stat4Accum;
|
||||
typedef struct Stat4Sample Stat4Sample;
|
||||
struct Stat4Sample {
|
||||
i64 iRowid; /* Rowid in main table of the key */
|
||||
tRowcnt *anEq; /* sqlite_stat4.nEq */
|
||||
tRowcnt *anLt; /* sqlite_stat4.nLt */
|
||||
tRowcnt *anDLt; /* sqlite_stat4.nDLt */
|
||||
#ifdef SQLITE_ENABLE_STAT34
|
||||
tRowcnt *anLt; /* sqlite_stat4.nLt */
|
||||
i64 iRowid; /* Rowid in main table of the key */
|
||||
u8 isPSample; /* True if a periodic sample */
|
||||
int iCol; /* If !isPSample, the reason for inclusion */
|
||||
u32 iHash; /* Tiebreaker hash */
|
||||
#endif
|
||||
};
|
||||
struct Stat4Accum {
|
||||
tRowcnt nRow; /* Number of rows in the entire table */
|
||||
@@ -285,9 +295,9 @@ struct Stat4Accum {
|
||||
};
|
||||
|
||||
/*
|
||||
** Implementation of the stat_init(C,N) SQL function. The two parameters
|
||||
** Implementation of the stat_init(N,C) SQL function. The two parameters
|
||||
** are the number of rows in the table or index (C) and the number of columns
|
||||
** in the index (N).
|
||||
** in the index (N). The second argument (C) is only used for STAT3 and STAT4.
|
||||
**
|
||||
** This routine allocates the Stat4Accum object in heap memory. The return
|
||||
** value is a pointer to the the Stat4Accum object encoded as a blob (i.e.
|
||||
@@ -299,64 +309,73 @@ static void statInit(
|
||||
sqlite3_value **argv
|
||||
){
|
||||
Stat4Accum *p;
|
||||
u8 *pSpace; /* Allocated space not yet assigned */
|
||||
tRowcnt nRow; /* Number of rows in table (C) */
|
||||
int mxSample; /* Maximum number of samples collected */
|
||||
int nCol; /* Number of columns in index being sampled */
|
||||
int nColUp; /* nCol rounded up for alignment */
|
||||
int n; /* Bytes of space to allocate */
|
||||
int i; /* Used to iterate through p->aSample[] */
|
||||
#ifdef SQLITE_ENABLE_STAT34
|
||||
int mxSample = SQLITE_STAT4_SAMPLES;
|
||||
#endif
|
||||
|
||||
/* Decode the three function arguments */
|
||||
UNUSED_PARAMETER(argc);
|
||||
nRow = (tRowcnt)sqlite3_value_int64(argv[0]);
|
||||
mxSample = SQLITE_STAT4_SAMPLES;
|
||||
nCol = sqlite3_value_int(argv[1]);
|
||||
nCol = sqlite3_value_int(argv[0]);
|
||||
assert( nCol>1 ); /* >1 because it includes the rowid column */
|
||||
nColUp = sizeof(tRowcnt)<8 ? (nCol+1)&~1 : nCol;
|
||||
|
||||
/* Allocate the space required for the Stat4Accum object */
|
||||
n = sizeof(*p)
|
||||
+ sizeof(tRowcnt)*nCol /* Stat4Accum.anEq */
|
||||
+ sizeof(tRowcnt)*nCol /* Stat4Accum.anLt */
|
||||
+ sizeof(tRowcnt)*nCol /* Stat4Accum.anDLt */
|
||||
+ sizeof(Stat4Sample)*(nCol+mxSample) /* Stat4Accum.aBest[], a[] */
|
||||
+ sizeof(tRowcnt)*3*nCol*(nCol+mxSample);
|
||||
+ sizeof(tRowcnt)*nColUp /* Stat4Accum.anEq */
|
||||
+ sizeof(tRowcnt)*nColUp /* Stat4Accum.anDLt */
|
||||
#ifdef SQLITE_ENABLE_STAT34
|
||||
+ sizeof(tRowcnt)*nColUp /* Stat4Accum.anLt */
|
||||
+ sizeof(Stat4Sample)*(nCol+mxSample) /* Stat4Accum.aBest[], a[] */
|
||||
+ sizeof(tRowcnt)*3*nColUp*(nCol+mxSample)
|
||||
#endif
|
||||
;
|
||||
p = sqlite3MallocZero(n);
|
||||
if( p==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
|
||||
p->nRow = nRow;
|
||||
p->nRow = 0;
|
||||
p->nCol = nCol;
|
||||
p->mxSample = mxSample;
|
||||
p->nPSample = p->nRow/(mxSample/3+1) + 1;
|
||||
p->iGet = -1;
|
||||
|
||||
p->current.anDLt = (tRowcnt*)&p[1];
|
||||
p->current.anEq = &p->current.anDLt[nCol];
|
||||
p->current.anLt = &p->current.anEq[nCol];
|
||||
sqlite3_randomness(sizeof(p->iPrn), &p->iPrn);
|
||||
p->current.anEq = &p->current.anDLt[nColUp];
|
||||
|
||||
/* Set up the Stat4Accum.a[] and aBest[] arrays */
|
||||
p->a = (struct Stat4Sample*)&p->current.anLt[nCol];
|
||||
p->aBest = &p->a[mxSample];
|
||||
pSpace = (u8*)(&p->a[mxSample+nCol]);
|
||||
for(i=0; i<(mxSample+nCol); i++){
|
||||
p->a[i].anEq = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nCol);
|
||||
p->a[i].anLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nCol);
|
||||
p->a[i].anDLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nCol);
|
||||
}
|
||||
assert( (pSpace - (u8*)p)==n );
|
||||
#ifdef SQLITE_ENABLE_STAT34
|
||||
{
|
||||
u8 *pSpace; /* Allocated space not yet assigned */
|
||||
int i; /* Used to iterate through p->aSample[] */
|
||||
|
||||
for(i=0; i<nCol; i++){
|
||||
p->aBest[i].iCol = i;
|
||||
p->iGet = -1;
|
||||
p->mxSample = mxSample;
|
||||
p->nPSample = sqlite3_value_int64(argv[1])/(mxSample/3+1) + 1;
|
||||
p->current.anLt = &p->current.anEq[nColUp];
|
||||
sqlite3_randomness(sizeof(p->iPrn), &p->iPrn);
|
||||
|
||||
/* Set up the Stat4Accum.a[] and aBest[] arrays */
|
||||
p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
|
||||
p->aBest = &p->a[mxSample];
|
||||
pSpace = (u8*)(&p->a[mxSample+nCol]);
|
||||
for(i=0; i<(mxSample+nCol); i++){
|
||||
p->a[i].anEq = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
|
||||
p->a[i].anLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
|
||||
p->a[i].anDLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
|
||||
}
|
||||
assert( (pSpace - (u8*)p)==n );
|
||||
|
||||
for(i=0; i<nCol; i++){
|
||||
p->aBest[i].iCol = i;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return a pointer to the allocated object to the caller */
|
||||
sqlite3_result_blob(context, p, sizeof(p), sqlite3_free);
|
||||
}
|
||||
static const FuncDef statInitFuncdef = {
|
||||
2, /* nArg */
|
||||
1+IsStat34, /* nArg */
|
||||
SQLITE_UTF8, /* iPrefEnc */
|
||||
0, /* flags */
|
||||
0, /* pUserData */
|
||||
@@ -544,11 +563,16 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the stat_push SQL function.
|
||||
** Implementation of the stat_push SQL function: stat_push(P,R,C)
|
||||
** Arguments:
|
||||
**
|
||||
** stat_push(P,R,C)
|
||||
** P Pointer to the Stat4Accum object created by stat_init()
|
||||
** C Index of left-most column to differ from previous row
|
||||
** R Rowid for the current row
|
||||
**
|
||||
** The return value is always NULL.
|
||||
** The SQL function always returns NULL.
|
||||
**
|
||||
** The R parameter is only used for STAT3 and STAT4.
|
||||
*/
|
||||
static void statPush(
|
||||
sqlite3_context *context,
|
||||
@@ -559,15 +583,17 @@ static void statPush(
|
||||
|
||||
/* The three function arguments */
|
||||
Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
|
||||
i64 rowid = sqlite3_value_int64(argv[1]);
|
||||
int iChng = sqlite3_value_int(argv[2]);
|
||||
int iChng = sqlite3_value_int(argv[1]);
|
||||
|
||||
assert( p->nCol>1 ); /* Includes rowid field */
|
||||
assert( iChng<p->nCol );
|
||||
|
||||
/* p->current.anEq[0] is false the first time this function is called. */
|
||||
if( p->current.anEq[0] ){
|
||||
|
||||
if( p->nRow==0 ){
|
||||
/* anEq[0] is only zero for the very first call to this function. Do
|
||||
** appropriate initialization */
|
||||
for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
|
||||
}else{
|
||||
/* Second and subsequent calls get processed here */
|
||||
samplePushPrevious(p, iChng);
|
||||
|
||||
/* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
|
||||
@@ -577,18 +603,17 @@ static void statPush(
|
||||
}
|
||||
for(i=iChng; i<p->nCol; i++){
|
||||
p->current.anDLt[i]++;
|
||||
#ifdef SQLITE_ENABLE_STAT34
|
||||
p->current.anLt[i] += p->current.anEq[i];
|
||||
#endif
|
||||
p->current.anEq[i] = 1;
|
||||
}
|
||||
|
||||
}else{
|
||||
for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
|
||||
}
|
||||
|
||||
if( IsStat4 || IsStat3 ){
|
||||
p->current.iRowid = rowid;
|
||||
p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345;
|
||||
}
|
||||
p->nRow++;
|
||||
#ifdef SQLITE_ENABLE_STAT34
|
||||
p->current.iRowid = sqlite3_value_int64(argv[2]);
|
||||
p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345;
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
{
|
||||
@@ -613,7 +638,7 @@ static void statPush(
|
||||
#endif
|
||||
}
|
||||
static const FuncDef statPushFuncdef = {
|
||||
3, /* nArg */
|
||||
2+IsStat34, /* nArg */
|
||||
SQLITE_UTF8, /* iPrefEnc */
|
||||
0, /* flags */
|
||||
0, /* pUserData */
|
||||
@@ -749,7 +774,7 @@ static void statGet(
|
||||
#endif /* SQLITE_ENABLE_STAT34 */
|
||||
}
|
||||
static const FuncDef statGetFuncdef = {
|
||||
2, /* nArg */
|
||||
1+IsStat34, /* nArg */
|
||||
SQLITE_UTF8, /* iPrefEnc */
|
||||
0, /* flags */
|
||||
0, /* pUserData */
|
||||
@@ -771,7 +796,7 @@ static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
|
||||
#endif
|
||||
sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4, regOut);
|
||||
sqlite3VdbeChangeP4(v, -1, (char*)&statGetFuncdef, P4_FUNCDEF);
|
||||
sqlite3VdbeChangeP5(v, 1 + IsStat3 + IsStat4);
|
||||
sqlite3VdbeChangeP5(v, 1 + IsStat34);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -797,8 +822,10 @@ static void analyzeOneTable(
|
||||
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 regRowid = iMem++; /* Rowid argument passed to stat_push() */
|
||||
int regChng = iMem++; /* Index of changed index field */
|
||||
#ifdef SQLITE_ENABLE_STAT34
|
||||
int regRowid = iMem++; /* Rowid argument passed to stat_push() */
|
||||
#endif
|
||||
int regTemp = iMem++; /* Temporary use register */
|
||||
int regTabname = iMem++; /* Register containing table name */
|
||||
int regIdxname = iMem++; /* Register containing index name */
|
||||
@@ -884,7 +911,7 @@ static void analyzeOneTable(
|
||||
**
|
||||
** chng_addr_N:
|
||||
** regRowid = idx(rowid)
|
||||
** stat_push(P, regRowid, regChng)
|
||||
** stat_push(P, regChng, regRowid)
|
||||
** Next csr
|
||||
** if !eof(csr) goto next_row;
|
||||
**
|
||||
@@ -905,15 +932,18 @@ static void analyzeOneTable(
|
||||
|
||||
/* Invoke the stat_init() function. The arguments are:
|
||||
**
|
||||
** * the number of rows in the index,
|
||||
** * the number of columns in the index including the rowid,
|
||||
** * the recommended number of samples for the stat3/stat4 table.
|
||||
** (1) the number of columns in the index including the rowid,
|
||||
** (2) the number of rows in the index,
|
||||
**
|
||||
** The second argument is only used for STAT3 and STAT4
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+1);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, nCol+1, regStat4+2);
|
||||
#ifdef SQLITE_ENABLE_STAT34
|
||||
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+2);
|
||||
#endif
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, nCol+1, regStat4+1);
|
||||
sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4+1, regStat4);
|
||||
sqlite3VdbeChangeP4(v, -1, (char*)&statInitFuncdef, P4_FUNCDEF);
|
||||
sqlite3VdbeChangeP5(v, 2);
|
||||
sqlite3VdbeChangeP5(v, 1+IsStat34);
|
||||
|
||||
/* Implementation of the following:
|
||||
**
|
||||
@@ -964,17 +994,20 @@ static void analyzeOneTable(
|
||||
|
||||
/*
|
||||
** chng_addr_N:
|
||||
** regRowid = idx(rowid)
|
||||
** stat_push(P, regRowid, regChng)
|
||||
** regRowid = idx(rowid) // STAT34 only
|
||||
** stat_push(P, regChng, regRowid) // 3rd parameter STAT34 only
|
||||
** Next csr
|
||||
** if !eof(csr) goto next_row;
|
||||
*/
|
||||
sqlite3VdbeJumpHere(v, aGotoChng[nCol]);
|
||||
#ifdef SQLITE_ENABLE_STAT34
|
||||
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
|
||||
assert( regRowid==(regStat4+2) );
|
||||
#endif
|
||||
assert( regChng==(regStat4+1) );
|
||||
sqlite3VdbeAddOp3(v, OP_Function, 1, regStat4, regTemp);
|
||||
sqlite3VdbeChangeP4(v, -1, (char*)&statPushFuncdef, P4_FUNCDEF);
|
||||
sqlite3VdbeChangeP5(v, 3);
|
||||
assert( regRowid==(regStat4+1) && regChng==(regStat4+2) );
|
||||
sqlite3VdbeChangeP5(v, 2+IsStat34);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow);
|
||||
|
||||
/* Add the entry to the stat1 table. */
|
||||
@@ -985,7 +1018,8 @@ static void analyzeOneTable(
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
|
||||
|
||||
/* Add the entries to the stat3 or stat4 table. */
|
||||
if( IsStat3 || IsStat4 ){
|
||||
#ifdef SQLITE_ENABLE_STAT34
|
||||
{
|
||||
int regEq = regStat1;
|
||||
int regLt = regStat1+1;
|
||||
int regDLt = regStat1+2;
|
||||
@@ -1004,25 +1038,25 @@ static void analyzeOneTable(
|
||||
callStatGet(v, regStat4, STAT_GET_NLT, regLt);
|
||||
callStatGet(v, regStat4, STAT_GET_NDLT, regDLt);
|
||||
sqlite3VdbeAddOp3(v, OP_NotExists, iTabCur, addrNext, regSampleRowid);
|
||||
if( IsStat3 ){
|
||||
int iCol = pIdx->aiColumn[0];
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, iCol, regSample);
|
||||
}else{
|
||||
for(i=0; i<nCol; i++){
|
||||
int iCol = pIdx->aiColumn[i];
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, iCol, regCol+i);
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol+1, regSample);
|
||||
#ifdef SQLITE_ENABLE_STAT3
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur,
|
||||
pIdx->aiColumn[0], regSample);
|
||||
#else
|
||||
for(i=0; i<nCol; i++){
|
||||
int iCol = pIdx->aiColumn[i];
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, iCol, regCol+i);
|
||||
}
|
||||
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol+1, regSample);
|
||||
#endif
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 6, regTemp, "bbbbbb", 0);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext);
|
||||
sqlite3VdbeJumpHere(v, addrIsNull);
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_STAT34 */
|
||||
|
||||
/* Jump here if the index is empty */
|
||||
/* End of analysis */
|
||||
sqlite3VdbeJumpHere(v, addrRewind);
|
||||
sqlite3DbFree(db, aGotoChng);
|
||||
}
|
||||
|
||||
@@ -3056,7 +3056,6 @@ extern int sqlite3PendingByte;
|
||||
void sqlite3RootPageMoved(sqlite3*, int, int, int);
|
||||
void sqlite3Reindex(Parse*, Token*, Token*);
|
||||
void sqlite3AlterFunctions(void);
|
||||
void sqlite3AnalyzeFunctions(void);
|
||||
void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
|
||||
int sqlite3GetToken(const unsigned char *, int *);
|
||||
void sqlite3NestedParse(Parse*, const char*, ...);
|
||||
@@ -3107,8 +3106,11 @@ Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);
|
||||
void sqlite3BackupRestart(sqlite3_backup *);
|
||||
void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);
|
||||
|
||||
#if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4)
|
||||
void sqlite3AnalyzeFunctions(void);
|
||||
int sqlite3Stat4ProbeSetValue(Parse*,Index*,UnpackedRecord**,Expr*,u8,int,int*);
|
||||
void sqlite3Stat4ProbeFree(UnpackedRecord*);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The interface to the LEMON-generated parser
|
||||
|
||||
Reference in New Issue
Block a user