Fix the STAT4 information for WITHOUT ROWID tables.
FossilOrigin-Name: 5d8628fdffbcf837313958f0ee1ed8a2043d384e
This commit is contained in:
parent
39129ce8d9
commit
ec9e55d358
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
|||||||
C Fix\swhere.c\sso\sthat\sthe\sprimary\skey\svalues\sappended\sto\severy\sindex\sentry\son\sa\sWITHOUT\sROWID\stable\smay\sbe\sused\swhen\suseful.
|
C Fix\sthe\sSTAT4\sinformation\sfor\sWITHOUT\sROWID\stables.
|
||||||
D 2014-06-30T15:23:57.908
|
D 2014-06-30T17:07:39.466
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 1732320ecac3fee229d560d7ef2afa34681d1815
|
F Makefile.in 1732320ecac3fee229d560d7ef2afa34681d1815
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@ -161,7 +161,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
|||||||
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
|
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
|
||||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||||
F src/alter.c b00900877f766f116f9e16116f1ccacdc21d82f1
|
F src/alter.c b00900877f766f116f9e16116f1ccacdc21d82f1
|
||||||
F src/analyze.c 0f9ee2f88f7c564cedb16f8e0236f2d5ac8429aa
|
F src/analyze.c ec6e0691a6a23e0239dc733109b906ee04b89cc3
|
||||||
F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52
|
F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52
|
||||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||||
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
|
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
|
||||||
@ -1181,7 +1181,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||||
P de826c31589258f0906f87d65796944103e36d5b
|
P 6624a61d16e47ad691c4195ca8a1d68b7348118d
|
||||||
R 8442f880f57a242b77225992393b657c
|
R 54d510c828cc71c8f4dcbc102dfc2a66
|
||||||
U dan
|
U drh
|
||||||
Z 6c9f8a4d0a3c007f8c2ac1857a8d9913
|
Z 6aa7249d11aa6d73980f37e6212dc38c
|
||||||
|
@ -1 +1 @@
|
|||||||
6624a61d16e47ad691c4195ca8a1d68b7348118d
|
5d8628fdffbcf837313958f0ee1ed8a2043d384e
|
@ -246,6 +246,7 @@ static void openStatTable(
|
|||||||
assert( i<ArraySize(aTable) );
|
assert( i<ArraySize(aTable) );
|
||||||
sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb, 3);
|
sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb, 3);
|
||||||
sqlite3VdbeChangeP5(v, aCreateTbl[i]);
|
sqlite3VdbeChangeP5(v, aCreateTbl[i]);
|
||||||
|
VdbeComment((v, aTable[i].zName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +282,8 @@ struct Stat4Sample {
|
|||||||
struct Stat4Accum {
|
struct Stat4Accum {
|
||||||
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 */
|
tRowcnt nPSample; /* How often to do a periodic sample */
|
||||||
int nCol; /* Number of columns in index + rowid */
|
int nCol; /* Number of columns in index + pk/rowid */
|
||||||
|
int nKeyCol; /* Number of index columns w/o the pk/rowid */
|
||||||
int mxSample; /* Maximum number of samples to accumulate */
|
int mxSample; /* Maximum number of samples to accumulate */
|
||||||
Stat4Sample current; /* Current row as a Stat4Sample */
|
Stat4Sample current; /* Current row as a Stat4Sample */
|
||||||
u32 iPrn; /* Pseudo-random number used for sampling */
|
u32 iPrn; /* Pseudo-random number used for sampling */
|
||||||
@ -367,9 +369,17 @@ static void stat4Destructor(void *pOld){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Implementation of the stat_init(N,C) SQL function. The two parameters
|
** Implementation of the stat_init(N,K,C) SQL function. The three parameters
|
||||||
** are the number of rows in the table or index (C) and the number of columns
|
** are:
|
||||||
** in the index (N). The second argument (C) is only used for STAT3 and STAT4.
|
** N: The number of columns in the index including the rowid/pk
|
||||||
|
** K: The number of columns in the index excluding the rowid/pk
|
||||||
|
** C: The number of rows in the index
|
||||||
|
**
|
||||||
|
** C is only used for STAT3 and STAT4.
|
||||||
|
**
|
||||||
|
** For ordinary rowid tables, N==K+1. But for WITHOUT ROWID tables,
|
||||||
|
** N=K+P where P is the number of columns in the primary key. For the
|
||||||
|
** covering index that implements the original WITHOUT ROWID table, N==K.
|
||||||
**
|
**
|
||||||
** 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.
|
||||||
@ -382,6 +392,7 @@ static void statInit(
|
|||||||
){
|
){
|
||||||
Stat4Accum *p;
|
Stat4Accum *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 nColUp; /* nCol rounded up for alignment */
|
int nColUp; /* nCol rounded up for alignment */
|
||||||
int n; /* Bytes of space to allocate */
|
int n; /* Bytes of space to allocate */
|
||||||
sqlite3 *db; /* Database connection */
|
sqlite3 *db; /* Database connection */
|
||||||
@ -392,8 +403,11 @@ static void statInit(
|
|||||||
/* Decode the three function arguments */
|
/* Decode the three function arguments */
|
||||||
UNUSED_PARAMETER(argc);
|
UNUSED_PARAMETER(argc);
|
||||||
nCol = sqlite3_value_int(argv[0]);
|
nCol = sqlite3_value_int(argv[0]);
|
||||||
assert( nCol>1 ); /* >1 because it includes the rowid column */
|
assert( nCol>0 );
|
||||||
nColUp = sizeof(tRowcnt)<8 ? (nCol+1)&~1 : nCol;
|
nColUp = sizeof(tRowcnt)<8 ? (nCol+1)&~1 : nCol;
|
||||||
|
nKeyCol = sqlite3_value_int(argv[1]);
|
||||||
|
assert( nKeyCol<=nCol );
|
||||||
|
assert( nKeyCol>0 );
|
||||||
|
|
||||||
/* Allocate the space required for the Stat4Accum object */
|
/* Allocate the space required for the Stat4Accum object */
|
||||||
n = sizeof(*p)
|
n = sizeof(*p)
|
||||||
@ -415,6 +429,7 @@ static void statInit(
|
|||||||
p->db = db;
|
p->db = db;
|
||||||
p->nRow = 0;
|
p->nRow = 0;
|
||||||
p->nCol = nCol;
|
p->nCol = nCol;
|
||||||
|
p->nKeyCol = nKeyCol;
|
||||||
p->current.anDLt = (tRowcnt*)&p[1];
|
p->current.anDLt = (tRowcnt*)&p[1];
|
||||||
p->current.anEq = &p->current.anDLt[nColUp];
|
p->current.anEq = &p->current.anDLt[nColUp];
|
||||||
|
|
||||||
@ -425,9 +440,9 @@ static void statInit(
|
|||||||
|
|
||||||
p->iGet = -1;
|
p->iGet = -1;
|
||||||
p->mxSample = mxSample;
|
p->mxSample = mxSample;
|
||||||
p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[1])/(mxSample/3+1) + 1);
|
p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1);
|
||||||
p->current.anLt = &p->current.anEq[nColUp];
|
p->current.anLt = &p->current.anEq[nColUp];
|
||||||
p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[1])*0xd0944565;
|
p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[2])*0xd0944565;
|
||||||
|
|
||||||
/* Set up the Stat4Accum.a[] and aBest[] arrays */
|
/* Set up the Stat4Accum.a[] and aBest[] arrays */
|
||||||
p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
|
p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
|
||||||
@ -450,7 +465,7 @@ static void statInit(
|
|||||||
sqlite3_result_blob(context, p, sizeof(p), stat4Destructor);
|
sqlite3_result_blob(context, p, sizeof(p), stat4Destructor);
|
||||||
}
|
}
|
||||||
static const FuncDef statInitFuncdef = {
|
static const FuncDef statInitFuncdef = {
|
||||||
1+IsStat34, /* nArg */
|
2+IsStat34, /* nArg */
|
||||||
SQLITE_UTF8, /* funcFlags */
|
SQLITE_UTF8, /* funcFlags */
|
||||||
0, /* pUserData */
|
0, /* pUserData */
|
||||||
0, /* pNext */
|
0, /* pNext */
|
||||||
@ -691,7 +706,7 @@ static void statPush(
|
|||||||
|
|
||||||
UNUSED_PARAMETER( argc );
|
UNUSED_PARAMETER( argc );
|
||||||
UNUSED_PARAMETER( context );
|
UNUSED_PARAMETER( context );
|
||||||
assert( p->nCol>1 ); /* Includes rowid field */
|
assert( p->nCol>0 );
|
||||||
assert( iChng<p->nCol );
|
assert( iChng<p->nCol );
|
||||||
|
|
||||||
if( p->nRow==0 ){
|
if( p->nRow==0 ){
|
||||||
@ -819,7 +834,7 @@ static void statGet(
|
|||||||
char *z;
|
char *z;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
char *zRet = sqlite3MallocZero(p->nCol * 25);
|
char *zRet = sqlite3MallocZero( (p->nKeyCol+1)*25 );
|
||||||
if( zRet==0 ){
|
if( zRet==0 ){
|
||||||
sqlite3_result_error_nomem(context);
|
sqlite3_result_error_nomem(context);
|
||||||
return;
|
return;
|
||||||
@ -827,7 +842,7 @@ static void statGet(
|
|||||||
|
|
||||||
sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow);
|
sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow);
|
||||||
z = zRet + sqlite3Strlen30(zRet);
|
z = zRet + sqlite3Strlen30(zRet);
|
||||||
for(i=0; i<(p->nCol-1); i++){
|
for(i=0; i<p->nKeyCol; i++){
|
||||||
u64 nDistinct = p->current.anDLt[i] + 1;
|
u64 nDistinct = p->current.anDLt[i] + 1;
|
||||||
u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
|
u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
|
||||||
sqlite3_snprintf(24, z, " %llu", iVal);
|
sqlite3_snprintf(24, z, " %llu", iVal);
|
||||||
@ -996,18 +1011,19 @@ static void analyzeOneTable(
|
|||||||
|
|
||||||
if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
|
if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
|
||||||
if( pIdx->pPartIdxWhere==0 ) needTableCnt = 0;
|
if( pIdx->pPartIdxWhere==0 ) needTableCnt = 0;
|
||||||
VdbeNoopComment((v, "Begin analysis of %s", pIdx->zName));
|
if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIdx) ){
|
||||||
nCol = pIdx->nKeyCol;
|
nCol = pIdx->nKeyCol;
|
||||||
|
zIdxName = pTab->zName;
|
||||||
|
}else{
|
||||||
|
nCol = pIdx->nColumn;
|
||||||
|
zIdxName = pIdx->zName;
|
||||||
|
}
|
||||||
aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*(nCol+1));
|
aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*(nCol+1));
|
||||||
if( aGotoChng==0 ) continue;
|
if( aGotoChng==0 ) continue;
|
||||||
|
|
||||||
/* Populate the register containing the index name. */
|
/* Populate the register containing the index name. */
|
||||||
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
|
|
||||||
zIdxName = pTab->zName;
|
|
||||||
}else{
|
|
||||||
zIdxName = pIdx->zName;
|
|
||||||
}
|
|
||||||
sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, zIdxName, 0);
|
sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, zIdxName, 0);
|
||||||
|
VdbeComment((v, "Analysis for %s.%s", pTab->zName, zIdxName));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Pseudo-code for loop that calls stat_push():
|
** Pseudo-code for loop that calls stat_push():
|
||||||
@ -1045,7 +1061,7 @@ static void analyzeOneTable(
|
|||||||
** the regPrev array and a trailing rowid (the rowid slot is required
|
** the regPrev array and a trailing rowid (the rowid slot is required
|
||||||
** when building a record to insert into the sample column of
|
** when building a record to insert into the sample column of
|
||||||
** the sqlite_stat4 table. */
|
** the sqlite_stat4 table. */
|
||||||
pParse->nMem = MAX(pParse->nMem, regPrev+pIdx->nColumn);
|
pParse->nMem = MAX(pParse->nMem, regPrev+nCol);
|
||||||
|
|
||||||
/* Open a read-only cursor on the index being analyzed. */
|
/* Open a read-only cursor on the index being analyzed. */
|
||||||
assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) );
|
assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) );
|
||||||
@ -1061,12 +1077,13 @@ static void analyzeOneTable(
|
|||||||
** The second argument is only used for STAT3 and STAT4
|
** The second argument is only used for STAT3 and STAT4
|
||||||
*/
|
*/
|
||||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||||
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+2);
|
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+3);
|
||||||
#endif
|
#endif
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, nCol+1, regStat4+1);
|
sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1);
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2);
|
||||||
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, 1+IsStat34);
|
sqlite3VdbeChangeP5(v, 2+IsStat34);
|
||||||
|
|
||||||
/* Implementation of the following:
|
/* Implementation of the following:
|
||||||
**
|
**
|
||||||
@ -1166,10 +1183,9 @@ static void analyzeOneTable(
|
|||||||
int regSampleRowid = regCol + nCol;
|
int regSampleRowid = regCol + nCol;
|
||||||
int addrNext;
|
int addrNext;
|
||||||
int addrIsNull;
|
int addrIsNull;
|
||||||
int nSampleCol;
|
|
||||||
u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
|
u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
|
||||||
|
|
||||||
pParse->nMem = MAX(pParse->nMem, regCol+nCol+1);
|
pParse->nMem = MAX(pParse->nMem, regCol+nCol);
|
||||||
|
|
||||||
addrNext = sqlite3VdbeCurrentAddr(v);
|
addrNext = sqlite3VdbeCurrentAddr(v);
|
||||||
callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid);
|
callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid);
|
||||||
@ -1187,16 +1203,11 @@ static void analyzeOneTable(
|
|||||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur,
|
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur,
|
||||||
pIdx->aiColumn[0], regSample);
|
pIdx->aiColumn[0], regSample);
|
||||||
#else
|
#else
|
||||||
if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIdx) ){
|
for(i=0; i<nCol; i++){
|
||||||
nSampleCol = pIdx->nKeyCol;
|
|
||||||
}else{
|
|
||||||
nSampleCol = pIdx->nColumn;
|
|
||||||
}
|
|
||||||
for(i=nSampleCol-1; i>=0; i--){
|
|
||||||
i16 iCol = pIdx->aiColumn[i];
|
i16 iCol = pIdx->aiColumn[i];
|
||||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, iCol, regCol+i);
|
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, iCol, regCol+i);
|
||||||
}
|
}
|
||||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nSampleCol, regSample);
|
sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol, regSample);
|
||||||
#endif
|
#endif
|
||||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp);
|
sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp);
|
||||||
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
|
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
|
||||||
|
Loading…
Reference in New Issue
Block a user