Initial implementation of the unlikely() SQL function used as a hint to
the query planner. FossilOrigin-Name: 036fc37a034093a4c6fc190633bd41c2b7230d77
This commit is contained in:
parent
d36e104112
commit
cca9f3d291
25
manifest
25
manifest
@ -1,5 +1,5 @@
|
|||||||
C Combine\sthe\sFuncDef.iPrefEnc\sand\sFuncDef.flags\sfields\sinto\sa\ssingle\nnew\sFuncDef.funcFlags\sfield.
|
C Initial\simplementation\sof\sthe\sunlikely()\sSQL\sfunction\sused\sas\sa\shint\sto\nthe\squery\splanner.
|
||||||
D 2013-09-06T13:10:12.385
|
D 2013-09-06T15:23:29.191
|
||||||
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
|
||||||
@ -172,10 +172,10 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
|||||||
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
|
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
|
||||||
F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
|
F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
|
||||||
F src/delete.c 2dc64ca360b7d7da481183ea920a813a0c203c97
|
F src/delete.c 2dc64ca360b7d7da481183ea920a813a0c203c97
|
||||||
F src/expr.c 33ae44812d25799000dbcfd54bb2142b30cdd049
|
F src/expr.c d0ed048b3b3c97fddbcccb8df43cc39b89e682c2
|
||||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||||
F src/fkey.c be866cd8c4fa6cae98ba33109578fd1a3311ee5b
|
F src/fkey.c be866cd8c4fa6cae98ba33109578fd1a3311ee5b
|
||||||
F src/func.c 7650d35651bb0ca903d24f4e5e944bfdaac9f152
|
F src/func.c a297b1f3cf48dd483f5453b7155bc5e8f4ca1fc2
|
||||||
F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759
|
F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759
|
||||||
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
|
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
|
||||||
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
||||||
@ -214,14 +214,14 @@ F src/pragma.c 3aa3d8c8623b7b71c5b1bfb72dcc31fb0c25665f
|
|||||||
F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f
|
F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f
|
||||||
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
|
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
|
||||||
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
|
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
|
||||||
F src/resolve.c 9d53899cc6e1f4ec0b4632d07e97d57827bf63b9
|
F src/resolve.c 748618c3df7f37f2cd33c8834770b1e34f9b1185
|
||||||
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
||||||
F src/select.c 9239586282bd146ec5843a2cde7d54cd7816cf78
|
F src/select.c 9239586282bd146ec5843a2cde7d54cd7816cf78
|
||||||
F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747
|
F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747
|
||||||
F src/sqlite.h.in ec40aa958a270416fb04b4f72210357bf163d2c5
|
F src/sqlite.h.in ec40aa958a270416fb04b4f72210357bf163d2c5
|
||||||
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
|
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
|
||||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||||
F src/sqliteInt.h 32e959dba9899360ce4ae3cd6cc77b4a8df277e8
|
F src/sqliteInt.h fd9005fab1cd063f5c4e76a2120efc080b43750a
|
||||||
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
|
||||||
@ -290,7 +290,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d
|
|||||||
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
|
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
|
||||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||||
F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
|
F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
|
||||||
F src/where.c 06c249a5137575ecf4d527e5a1dadb1087e4375c
|
F src/where.c c9f8ae51797bebfbfa49b9e5bede6fc142b44262
|
||||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
||||||
@ -308,7 +308,7 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
|
|||||||
F test/analyze6.test 19151da2c4e918905d2081b74ac5c4d47fc850ab
|
F test/analyze6.test 19151da2c4e918905d2081b74ac5c4d47fc850ab
|
||||||
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
|
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
|
||||||
F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88
|
F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88
|
||||||
F test/analyze9.test 4a48461d71a7b4a958570c580495a97e842e2700
|
F test/analyze9.test e688c7289d3d33b7185e2c2afcac6a9f095563a3
|
||||||
F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944
|
F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944
|
||||||
F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d
|
F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d
|
||||||
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
|
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
|
||||||
@ -1111,7 +1111,10 @@ 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 a99a53b81e29c9514b85318bea028d1667e5f760
|
P 97b10e66e98e84755aa577f8da017bf1aea2056c
|
||||||
R 8c10a6011eb52c6098e833ca515e6c77
|
R fcd7cd29a90a12a870cace66939b8877
|
||||||
|
T *branch * unlikely-func
|
||||||
|
T *sym-unlikely-func *
|
||||||
|
T -sym-trunk *
|
||||||
U drh
|
U drh
|
||||||
Z c7e49c79214a66374f550dcdb7a70012
|
Z 2a30cee668099b5c8e0e2b447ac67feb
|
||||||
|
@ -1 +1 @@
|
|||||||
97b10e66e98e84755aa577f8da017bf1aea2056c
|
036fc37a034093a4c6fc190633bd41c2b7230d77
|
20
src/expr.c
20
src/expr.c
@ -89,8 +89,16 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
|
|||||||
** an expression.
|
** an expression.
|
||||||
*/
|
*/
|
||||||
Expr *sqlite3ExprSkipCollate(Expr *pExpr){
|
Expr *sqlite3ExprSkipCollate(Expr *pExpr){
|
||||||
while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){
|
while( pExpr ){
|
||||||
pExpr = pExpr->pLeft;
|
if( pExpr->op==TK_COLLATE || pExpr->op==TK_AS ){
|
||||||
|
pExpr = pExpr->pLeft;
|
||||||
|
}else if( ExprHasAnyProperty(pExpr, EP_Hint) ){
|
||||||
|
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||||
|
assert( pExpr->x.pList->nExpr>0 );
|
||||||
|
pExpr = pExpr->x.pList->a[0].pExpr;
|
||||||
|
}else{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return pExpr;
|
return pExpr;
|
||||||
}
|
}
|
||||||
@ -2649,6 +2657,14 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The UNLIKELY() function is a no-op. The result is the value
|
||||||
|
** of the first argument.
|
||||||
|
*/
|
||||||
|
if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
|
||||||
|
assert( nFarg>=1 );
|
||||||
|
sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if( pFarg ){
|
if( pFarg ){
|
||||||
r1 = sqlite3GetTempRange(pParse, nFarg);
|
r1 = sqlite3GetTempRange(pParse, nFarg);
|
||||||
|
20
src/func.c
20
src/func.c
@ -418,14 +418,14 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The COALESCE() and IFNULL() functions are implemented as VDBE code so
|
** Some functions like COALESCE() and IFNULL() and UNLIKELY() are implemented
|
||||||
** that unused argument values do not have to be computed. However, we
|
** as VDBE code so that unused argument values do not have to be computed.
|
||||||
** still need some kind of function implementation for this routines in
|
** However, we still need some kind of function implementation for this
|
||||||
** the function table. That function implementation will never be called
|
** routines in the function table. The noopFunc macro provides this.
|
||||||
** so it doesn't matter what the implementation is. We might as well use
|
** noopFunc will never be called so it doesn't matter what the implementation
|
||||||
** the "version()" function as a substitute.
|
** is. We might as well use the "version()" function as a substitute.
|
||||||
*/
|
*/
|
||||||
#define ifnullFunc versionFunc /* Substitute function - never called */
|
#define noopFunc versionFunc /* Substitute function - never called */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Implementation of random(). Return a random integer.
|
** Implementation of random(). Return a random integer.
|
||||||
@ -1659,9 +1659,11 @@ void sqlite3RegisterGlobalFunctions(void){
|
|||||||
FUNCTION(lower, 1, 0, 0, lowerFunc ),
|
FUNCTION(lower, 1, 0, 0, lowerFunc ),
|
||||||
FUNCTION(coalesce, 1, 0, 0, 0 ),
|
FUNCTION(coalesce, 1, 0, 0, 0 ),
|
||||||
FUNCTION(coalesce, 0, 0, 0, 0 ),
|
FUNCTION(coalesce, 0, 0, 0, 0 ),
|
||||||
FUNCTION2(coalesce, -1, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE),
|
FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
|
||||||
FUNCTION(hex, 1, 0, 0, hexFunc ),
|
FUNCTION(hex, 1, 0, 0, hexFunc ),
|
||||||
FUNCTION2(ifnull, 2, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE),
|
FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
|
||||||
|
FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
|
||||||
|
FUNCTION2(unlikely, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
|
||||||
FUNCTION(random, 0, 0, 0, randomFunc ),
|
FUNCTION(random, 0, 0, 0, randomFunc ),
|
||||||
FUNCTION(randomblob, 1, 0, 0, randomBlob ),
|
FUNCTION(randomblob, 1, 0, 0, randomBlob ),
|
||||||
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
|
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
|
||||||
|
@ -570,6 +570,18 @@ static void notValidCheckConstraint(
|
|||||||
# define notValidCheckConstraint(P,N,M)
|
# define notValidCheckConstraint(P,N,M)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Expression p should encode a floating point value between 1.0 and 0.0.
|
||||||
|
** Return 1024 times this value. Or return -1 if p is not a floating point
|
||||||
|
** value between 1.0 and 0.0.
|
||||||
|
*/
|
||||||
|
static int exprProbability(Expr *p){
|
||||||
|
double r = -1.0;
|
||||||
|
if( p->op!=TK_FLOAT ) return -1;
|
||||||
|
sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8);
|
||||||
|
if( r<0.0 || r>1.0 ) return -1;
|
||||||
|
return (int)(r*1000.0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This routine is callback for sqlite3WalkExpr().
|
** This routine is callback for sqlite3WalkExpr().
|
||||||
@ -683,6 +695,19 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
|||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
is_agg = pDef->xFunc==0;
|
is_agg = pDef->xFunc==0;
|
||||||
|
if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
|
||||||
|
ExprSetProperty(pExpr, EP_Hint);
|
||||||
|
if( n==2 ){
|
||||||
|
pExpr->iTable = exprProbability(pList->a[1].pExpr);
|
||||||
|
if( pExpr->iTable<0 ){
|
||||||
|
sqlite3ErrorMsg(pParse, "second parameter to unlikely() must be "
|
||||||
|
"between 0.0 and 1.0");
|
||||||
|
pNC->nErr++;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
pExpr->iTable = 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||||
if( pDef ){
|
if( pDef ){
|
||||||
|
@ -1752,7 +1752,8 @@ struct Expr {
|
|||||||
#endif
|
#endif
|
||||||
int iTable; /* TK_COLUMN: cursor number of table holding column
|
int iTable; /* TK_COLUMN: cursor number of table holding column
|
||||||
** TK_REGISTER: register number
|
** TK_REGISTER: register number
|
||||||
** TK_TRIGGER: 1 -> new, 0 -> old */
|
** TK_TRIGGER: 1 -> new, 0 -> old
|
||||||
|
** EP_Hint: 1000 times likelihood */
|
||||||
ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
|
ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
|
||||||
** TK_VARIABLE: variable number (always >= 1). */
|
** TK_VARIABLE: variable number (always >= 1). */
|
||||||
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
|
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
|
||||||
@ -1780,7 +1781,7 @@ struct Expr {
|
|||||||
#define EP_FixedDest 0x0200 /* Result needed in a specific register */
|
#define EP_FixedDest 0x0200 /* Result needed in a specific register */
|
||||||
#define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
|
#define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
|
||||||
#define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
|
#define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
|
||||||
#define EP_Hint 0x1000 /* Not used */
|
#define EP_Hint 0x1000 /* The UNLIKELY() SQL function */
|
||||||
#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
|
#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
|
||||||
#define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
|
#define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
|
||||||
#define EP_Static 0x8000 /* Held in memory not obtained from malloc() */
|
#define EP_Static 0x8000 /* Held in memory not obtained from malloc() */
|
||||||
|
50
src/where.c
50
src/where.c
@ -52,12 +52,13 @@ typedef struct WhereOrSet WhereOrSet;
|
|||||||
** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The
|
** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The
|
||||||
** maximum cost for ordinary tables is 64*(2**63) which becomes 6900.
|
** maximum cost for ordinary tables is 64*(2**63) which becomes 6900.
|
||||||
** (Virtual tables can return a larger cost, but let's assume they do not.)
|
** (Virtual tables can return a larger cost, but let's assume they do not.)
|
||||||
** So all costs can be stored in a 16-bit unsigned integer without risk
|
** So all costs can be stored in a 16-bit integer without risk
|
||||||
** of overflow.
|
** of overflow.
|
||||||
**
|
**
|
||||||
** Costs are estimates, so no effort is made to compute 10*log2(X) exactly.
|
** Costs are estimates, so no effort is made to compute 10*log2(X) exactly.
|
||||||
** Instead, a close estimate is used. Any value of X<=1 is stored as 0.
|
** Instead, a close estimate is used. Any value of X=1 is stored as 0.
|
||||||
** X=2 is 10. X=3 is 16. X=1000 is 99. etc.
|
** X=2 is 10. X=3 is 16. X=1000 is 99. etc. Negative values are allowed.
|
||||||
|
** A WhereCost of -10 means 0.5. WhereCost of -20 means 0.25. And so forth.
|
||||||
**
|
**
|
||||||
** The tool/wherecosttest.c source file implements a command-line program
|
** The tool/wherecosttest.c source file implements a command-line program
|
||||||
** that will convert WhereCosts to integers, convert integers to WhereCosts
|
** that will convert WhereCosts to integers, convert integers to WhereCosts
|
||||||
@ -65,7 +66,7 @@ typedef struct WhereOrSet WhereOrSet;
|
|||||||
** command-line program is a useful utility to have around when working with
|
** command-line program is a useful utility to have around when working with
|
||||||
** this module.
|
** this module.
|
||||||
*/
|
*/
|
||||||
typedef unsigned short int WhereCost;
|
typedef short int WhereCost;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This object contains information needed to implement a single nested
|
** This object contains information needed to implement a single nested
|
||||||
@ -268,6 +269,7 @@ struct WhereTerm {
|
|||||||
WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
|
WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
|
||||||
WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
|
WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
|
||||||
} u;
|
} u;
|
||||||
|
WhereCost truthProb; /* Probability of truth for this expression */
|
||||||
u16 eOperator; /* A WO_xx value describing <op> */
|
u16 eOperator; /* A WO_xx value describing <op> */
|
||||||
u8 wtFlags; /* TERM_xxx bit flags. See below */
|
u8 wtFlags; /* TERM_xxx bit flags. See below */
|
||||||
u8 nChild; /* Number of children that must disable us */
|
u8 nChild; /* Number of children that must disable us */
|
||||||
@ -642,6 +644,9 @@ static void whereClauseClear(WhereClause *pWC){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Forward declaration */
|
||||||
|
static WhereCost whereCost(tRowcnt x);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Add a single new WhereTerm entry to the WhereClause object pWC.
|
** Add a single new WhereTerm entry to the WhereClause object pWC.
|
||||||
** The new WhereTerm object is constructed from Expr p and with wtFlags.
|
** The new WhereTerm object is constructed from Expr p and with wtFlags.
|
||||||
@ -683,6 +688,11 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
|
|||||||
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
|
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
|
||||||
}
|
}
|
||||||
pTerm = &pWC->a[idx = pWC->nTerm++];
|
pTerm = &pWC->a[idx = pWC->nTerm++];
|
||||||
|
if( p && ExprHasAnyProperty(p, EP_Hint) ){
|
||||||
|
pTerm->truthProb = whereCost(p->iTable) - 99;
|
||||||
|
}else{
|
||||||
|
pTerm->truthProb = -1;
|
||||||
|
}
|
||||||
pTerm->pExpr = sqlite3ExprSkipCollate(p);
|
pTerm->pExpr = sqlite3ExprSkipCollate(p);
|
||||||
pTerm->wtFlags = wtFlags;
|
pTerm->wtFlags = wtFlags;
|
||||||
pTerm->pWC = pWC;
|
pTerm->pWC = pWC;
|
||||||
@ -4257,6 +4267,32 @@ whereLoopInsert_noop:
|
|||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Adjust the WhereLoop.nOut value downward to account for terms of the
|
||||||
|
** WHERE clause that reference the loop but which are not used by an
|
||||||
|
** index.
|
||||||
|
**
|
||||||
|
** In the current implementation, the first extra WHERE clause term reduces
|
||||||
|
** the number of output rows by a factor of 10 and each additional term
|
||||||
|
** reduces the number of output rows by sqrt(2).
|
||||||
|
*/
|
||||||
|
static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop, int iCur){
|
||||||
|
WhereTerm *pTerm;
|
||||||
|
Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
|
||||||
|
int x = 0;
|
||||||
|
int i;
|
||||||
|
for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){
|
||||||
|
if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) continue;
|
||||||
|
if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue;
|
||||||
|
if( (pTerm->prereqAll & notAllowed)!=0 ) continue;
|
||||||
|
x += pTerm->truthProb;
|
||||||
|
}
|
||||||
|
for(i=pLoop->nLTerm-1; i>=0; i--){
|
||||||
|
x -= pLoop->aLTerm[i]->truthProb;
|
||||||
|
}
|
||||||
|
if( x<0 ) pLoop->nOut += x;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** We have so far matched pBuilder->pNew->u.btree.nEq terms of the index pIndex.
|
** We have so far matched pBuilder->pNew->u.btree.nEq terms of the index pIndex.
|
||||||
** Try to match one more.
|
** Try to match one more.
|
||||||
@ -4423,7 +4459,7 @@ static int whereLoopAddBtreeIndex(
|
|||||||
}
|
}
|
||||||
/* Step cost for each output row */
|
/* Step cost for each output row */
|
||||||
pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut);
|
pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut);
|
||||||
/* TBD: Adjust nOut for additional constraints */
|
whereLoopOutputAdjust(pBuilder->pWC, pNew, pSrc->iCursor);
|
||||||
rc = whereLoopInsert(pBuilder, pNew);
|
rc = whereLoopInsert(pBuilder, pNew);
|
||||||
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
|
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
|
||||||
&& pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0))
|
&& pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0))
|
||||||
@ -4627,7 +4663,9 @@ static int whereLoopAddBtree(
|
|||||||
** index scans so that a covering index scan will be favored over
|
** index scans so that a covering index scan will be favored over
|
||||||
** a table scan. */
|
** a table scan. */
|
||||||
pNew->rRun = whereCostAdd(rSize,rLogSize) + 16;
|
pNew->rRun = whereCostAdd(rSize,rLogSize) + 16;
|
||||||
|
whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor);
|
||||||
rc = whereLoopInsert(pBuilder, pNew);
|
rc = whereLoopInsert(pBuilder, pNew);
|
||||||
|
pNew->nOut = rSize;
|
||||||
if( rc ) break;
|
if( rc ) break;
|
||||||
}else{
|
}else{
|
||||||
Bitmask m = pSrc->colUsed & ~columnsInIndex(pProbe);
|
Bitmask m = pSrc->colUsed & ~columnsInIndex(pProbe);
|
||||||
@ -4659,7 +4697,9 @@ static int whereLoopAddBtree(
|
|||||||
** which we will simplify to just N*log2(N) */
|
** which we will simplify to just N*log2(N) */
|
||||||
pNew->rRun = rSize + rLogSize;
|
pNew->rRun = rSize + rLogSize;
|
||||||
}
|
}
|
||||||
|
whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor);
|
||||||
rc = whereLoopInsert(pBuilder, pNew);
|
rc = whereLoopInsert(pBuilder, pNew);
|
||||||
|
pNew->nOut = rSize;
|
||||||
if( rc ) break;
|
if( rc ) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -805,6 +805,7 @@ do_test 16.1 {
|
|||||||
ANALYZE;
|
ANALYZE;
|
||||||
}
|
}
|
||||||
set nByte2 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
|
set nByte2 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1]
|
||||||
|
puts "$nByte $nByte2"
|
||||||
|
|
||||||
expr {$nByte2 > $nByte+950 && $nByte2 < $nByte+1050}
|
expr {$nByte2 > $nByte+950 && $nByte2 < $nByte+1050}
|
||||||
} {1}
|
} {1}
|
||||||
@ -950,4 +951,3 @@ for {set i 0} {$i<16} {incr i} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user