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