Merge in the Expr.flags expansion to 32-bits. Use an extra bit to help
optimize the sqlite3ExprSkipCollate() routine. FossilOrigin-Name: 4c84d1b4c20f18921dd705bf67e8225975b83e86
This commit is contained in:
commit
a4c3c87e3d
29
manifest
29
manifest
@ -1,5 +1,5 @@
|
||||
C Improvements\sto\slikelihood\sprocessing\sso\sthat\scommuting\san\sunindexed\sterm\sin\nthe\sWHERE\sclause\sdoes\snot\schange\sthe\squery\splan.
|
||||
D 2013-09-11T17:39:09.434
|
||||
C Merge\sin\sthe\sExpr.flags\sexpansion\sto\s32-bits.\s\sUse\san\sextra\sbit\sto\shelp\noptimize\sthe\ssqlite3ExprSkipCollate()\sroutine.
|
||||
D 2013-09-12T17:29:25.629
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -158,7 +158,7 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
|
||||
F src/analyze.c d322972af09e3f8debb45f420dfe3ded142b108b
|
||||
F src/attach.c eeb8d9d2c791caa0a54a835170ea898e96c2802d
|
||||
F src/attach.c 4a2b6a6d9b5f9fd55a8b59488ff7929fef73a195
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3
|
||||
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
||||
@ -172,7 +172,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
|
||||
F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
|
||||
F src/delete.c 2dc64ca360b7d7da481183ea920a813a0c203c97
|
||||
F src/expr.c d0ed048b3b3c97fddbcccb8df43cc39b89e682c2
|
||||
F src/expr.c 3104c01672d0b16d50c3a21e8db312bee64b68e8
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c be866cd8c4fa6cae98ba33109578fd1a3311ee5b
|
||||
F src/func.c 0aca17c8bc750fad4856e6098ed5e2597b641a75
|
||||
@ -203,10 +203,10 @@ F src/os.c b4ad71336fd96f97776f75587cd9e8218288f5be
|
||||
F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f
|
||||
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
|
||||
F src/os_unix.c 243fb37f47dc072fc59839ea241ff0a17c8d76e6
|
||||
F src/os_win.c bb592dfb850e4ee3e4caecce461dca74dc40936d
|
||||
F src/os_win.c 0e73f891dd806b82a76d4e19179c532f02236b86
|
||||
F src/pager.c 2aa4444ffe86e9282d03bc349a4a5e49bd77c0e8
|
||||
F src/pager.h f094af9f6ececfaa8a1e93876905a4f34233fb0c
|
||||
F src/parse.y 27c6b4138497d6f8360ba7847da6ed48033f957f
|
||||
F src/parse.y a97566d6da75075589a7c716d1bda14b586cf8da
|
||||
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
||||
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
|
||||
F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
|
||||
@ -214,14 +214,14 @@ F src/pragma.c 3aa3d8c8623b7b71c5b1bfb72dcc31fb0c25665f
|
||||
F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f
|
||||
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
|
||||
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
|
||||
F src/resolve.c 0e5b31ef428a76782c6ea8244d820f94f55c8110
|
||||
F src/resolve.c 062de789002f1ec5ccc35f7412eb6b4528421e66
|
||||
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
||||
F src/select.c 9239586282bd146ec5843a2cde7d54cd7816cf78
|
||||
F src/select.c d96bcdbc2e7de89cb72febeccd232746f67839fd
|
||||
F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747
|
||||
F src/sqlite.h.in ec40aa958a270416fb04b4f72210357bf163d2c5
|
||||
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h ac21b3aeb0251a4096a21a0750277f5701adfe0c
|
||||
F src/sqliteInt.h 5d368cb028e3c0e329fd5e8c41959a4310dff201
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@ -289,8 +289,8 @@ F src/vdbetrace.c e7ec40e1999ff3c6414424365d5941178966dcbc
|
||||
F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d
|
||||
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
|
||||
F src/where.c 47a9d554aa12e37d00c87ed6557edff3f96d1980
|
||||
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
|
||||
F src/where.c d2f58a441ba8709a99df6654b26a50b7ca7dada4
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
||||
@ -964,6 +964,7 @@ F test/tkt3992.test f3e7d548ac26f763b47bc0f750da3d03c81071da
|
||||
F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd
|
||||
F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1
|
||||
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
|
||||
F test/tpch01.test 8f4ac52f62f3e9f6bce0889105aecdf0275e331b
|
||||
F test/trace.test 4b36a41a3e9c7842151af6da5998f5080cdad9e5
|
||||
F test/trace2.test e7a988fdd982cdec62f1f1f34b0360e6476d01a0
|
||||
F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
|
||||
@ -1112,7 +1113,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
|
||||
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
||||
P 5d00cce74a7aefaf30022ae971ab1e0451e0ad6e
|
||||
R aedc9ce3e88fcb8ddfac4258d6222c86
|
||||
P 6e6bded055cdbc902731687c86d92c39a3ba5904 579a512538528cf4bb4381ba393c5d9e7310086b
|
||||
R dc2c889ddc263fd768cedb826f211ae2
|
||||
U drh
|
||||
Z 4fd6b6c258c46144822c202b8357c6fb
|
||||
Z cf223babd50a8b4daf3af8d47e55c943
|
||||
|
@ -1 +1 @@
|
||||
6e6bded055cdbc902731687c86d92c39a3ba5904
|
||||
4c84d1b4c20f18921dd705bf67e8225975b83e86
|
@ -509,7 +509,7 @@ int sqlite3FixExpr(
|
||||
Expr *pExpr /* The expression to be fixed to one database */
|
||||
){
|
||||
while( pExpr ){
|
||||
if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ) break;
|
||||
if( ExprHasProperty(pExpr, EP_TokenOnly) ) break;
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
|
||||
}else{
|
||||
|
97
src/expr.c
97
src/expr.c
@ -70,7 +70,7 @@ Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){
|
||||
Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
|
||||
if( pNew ){
|
||||
pNew->pLeft = pExpr;
|
||||
pNew->flags |= EP_Collate;
|
||||
pNew->flags |= EP_Collate|EP_Skip;
|
||||
pExpr = pNew;
|
||||
}
|
||||
}
|
||||
@ -85,21 +85,21 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
|
||||
}
|
||||
|
||||
/*
|
||||
** Skip over any TK_COLLATE and/or TK_AS operators at the root of
|
||||
** an expression.
|
||||
** Skip over any TK_COLLATE or TK_AS operators and any unlikely()
|
||||
** or likelihood() function at the root of an expression.
|
||||
*/
|
||||
Expr *sqlite3ExprSkipCollate(Expr *pExpr){
|
||||
while( pExpr ){
|
||||
if( pExpr->op==TK_COLLATE || pExpr->op==TK_AS ){
|
||||
pExpr = pExpr->pLeft;
|
||||
}else if( ExprHasAnyProperty(pExpr, EP_Hint) ){
|
||||
while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
|
||||
if( ExprHasProperty(pExpr, EP_Unlikely) ){
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
assert( pExpr->x.pList->nExpr>0 );
|
||||
assert( pExpr->op==TK_FUNCTION );
|
||||
pExpr = pExpr->x.pList->a[0].pExpr;
|
||||
}else{
|
||||
break;
|
||||
assert( pExpr->op==TK_COLLATE || pExpr->op==TK_AS );
|
||||
pExpr = pExpr->pLeft;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
@ -604,7 +604,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
||||
const char *z;
|
||||
|
||||
if( pExpr==0 ) return;
|
||||
assert( !ExprHasAnyProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
|
||||
z = pExpr->u.zToken;
|
||||
assert( z!=0 );
|
||||
assert( z[0]!=0 );
|
||||
@ -674,12 +674,12 @@ void sqlite3ExprDelete(sqlite3 *db, Expr *p){
|
||||
if( p==0 ) return;
|
||||
/* Sanity check: Assert that the IntValue is non-negative if it exists */
|
||||
assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
|
||||
if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
|
||||
if( !ExprHasProperty(p, EP_TokenOnly) ){
|
||||
/* The Expr.x union is never used at the same time as Expr.pRight */
|
||||
assert( p->x.pList==0 || p->pRight==0 );
|
||||
sqlite3ExprDelete(db, p->pLeft);
|
||||
sqlite3ExprDelete(db, p->pRight);
|
||||
if( !ExprHasProperty(p, EP_Reduced) && (p->flags2 & EP2_MallocedToken)!=0 ){
|
||||
sqlite3DbFree(db, p->u.zToken);
|
||||
}
|
||||
if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
|
||||
if( ExprHasProperty(p, EP_xIsSelect) ){
|
||||
sqlite3SelectDelete(db, p->x.pSelect);
|
||||
}else{
|
||||
@ -742,10 +742,10 @@ static int dupedExprStructSize(Expr *p, int flags){
|
||||
if( 0==(flags&EXPRDUP_REDUCE) ){
|
||||
nSize = EXPR_FULLSIZE;
|
||||
}else{
|
||||
assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
|
||||
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
|
||||
assert( !ExprHasProperty(p, EP_FromJoin) );
|
||||
assert( (p->flags2 & EP2_MallocedToken)==0 );
|
||||
assert( (p->flags2 & EP2_Irreducible)==0 );
|
||||
assert( !ExprHasProperty(p, EP_MemToken) );
|
||||
assert( !ExprHasProperty(p, EP_Irreduce) );
|
||||
if( p->pLeft || p->pRight || p->x.pList ){
|
||||
nSize = EXPR_REDUCEDSIZE | EP_Reduced;
|
||||
}else{
|
||||
@ -842,7 +842,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
||||
}
|
||||
|
||||
/* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
|
||||
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static);
|
||||
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken);
|
||||
pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
|
||||
pNew->flags |= staticFlag;
|
||||
|
||||
@ -862,7 +862,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
||||
}
|
||||
|
||||
/* Fill in pNew->pLeft and pNew->pRight. */
|
||||
if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly) ){
|
||||
if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
|
||||
zAlloc += dupedExprNodeSize(p, flags);
|
||||
if( ExprHasProperty(pNew, EP_Reduced) ){
|
||||
pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc);
|
||||
@ -872,8 +872,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
||||
*pzBuffer = zAlloc;
|
||||
}
|
||||
}else{
|
||||
pNew->flags2 = 0;
|
||||
if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
|
||||
if( !ExprHasProperty(p, EP_TokenOnly) ){
|
||||
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
|
||||
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
|
||||
}
|
||||
@ -1183,7 +1182,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||
/* If pWalker->u.i is 3 then any term of the expression that comes from
|
||||
** the ON or USING clauses of a join disqualifies the expression
|
||||
** from being considered constant. */
|
||||
if( pWalker->u.i==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){
|
||||
if( pWalker->u.i==3 && ExprHasProperty(pExpr, EP_FromJoin) ){
|
||||
pWalker->u.i = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
@ -1614,7 +1613,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
|
||||
}else{
|
||||
testcase( pParse->nQueryLoop>0 );
|
||||
pParse->nQueryLoop = 0;
|
||||
if( pX->pLeft->iColumn<0 && !ExprHasAnyProperty(pX, EP_xIsSelect) ){
|
||||
if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
|
||||
eType = IN_INDEX_ROWID;
|
||||
}
|
||||
}
|
||||
@ -1683,7 +1682,7 @@ int sqlite3CodeSubselect(
|
||||
** If all of the above are false, then we can run this code just once
|
||||
** save the results, and reuse the same result on subsequent invocations.
|
||||
*/
|
||||
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) ){
|
||||
if( !ExprHasProperty(pExpr, EP_VarSelect) ){
|
||||
testAddr = sqlite3CodeOnce(pParse);
|
||||
}
|
||||
|
||||
@ -2324,6 +2323,16 @@ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
|
||||
}
|
||||
#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */
|
||||
|
||||
/*
|
||||
** Convert an expression node to a TK_REGISTER
|
||||
*/
|
||||
static void exprToRegister(Expr *p, int iReg){
|
||||
p->op2 = p->op;
|
||||
p->op = TK_REGISTER;
|
||||
p->iTable = iReg;
|
||||
ExprClearProperty(p, EP_Skip);
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code into the current Vdbe to evaluate the given
|
||||
** expression. Attempt to store the results in register "target".
|
||||
@ -2623,7 +2632,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
testcase( op==TK_CONST_FUNC );
|
||||
testcase( op==TK_FUNCTION );
|
||||
if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){
|
||||
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
|
||||
pFarg = 0;
|
||||
}else{
|
||||
pFarg = pExpr->x.pList;
|
||||
@ -2862,9 +2871,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
** WHEN x=eN THEN rN ELSE y END
|
||||
**
|
||||
** X (if it exists) is in pExpr->pLeft.
|
||||
** Y is in pExpr->pRight. The Y is also optional. If there is no
|
||||
** ELSE clause and no other term matches, then the result of the
|
||||
** exprssion is NULL.
|
||||
** Y is in the last element of pExpr->x.pList if pExpr->x.pList->nExpr is
|
||||
** odd. The Y is also optional. If the number of elements in x.pList
|
||||
** is even, then Y is omitted and the "otherwise" result is NULL.
|
||||
** Ei is in pExpr->pList->a[i*2] and Ri is pExpr->pList->a[i*2+1].
|
||||
**
|
||||
** The result of the expression is the Ri for the first matching Ei,
|
||||
@ -2885,7 +2894,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; )
|
||||
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
|
||||
assert((pExpr->x.pList->nExpr % 2) == 0);
|
||||
assert(pExpr->x.pList->nExpr > 0);
|
||||
pEList = pExpr->x.pList;
|
||||
aListelem = pEList->a;
|
||||
@ -2895,9 +2903,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
cacheX = *pX;
|
||||
testcase( pX->op==TK_COLUMN );
|
||||
testcase( pX->op==TK_REGISTER );
|
||||
cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, ®Free1);
|
||||
exprToRegister(&cacheX, sqlite3ExprCodeTemp(pParse, pX, ®Free1));
|
||||
testcase( regFree1==0 );
|
||||
cacheX.op = TK_REGISTER;
|
||||
opCompare.op = TK_EQ;
|
||||
opCompare.pLeft = &cacheX;
|
||||
pTest = &opCompare;
|
||||
@ -2907,7 +2914,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
** purposes and possibly overwritten. */
|
||||
regFree1 = 0;
|
||||
}
|
||||
for(i=0; i<nExpr; i=i+2){
|
||||
for(i=0; i<nExpr-1; i=i+2){
|
||||
sqlite3ExprCachePush(pParse);
|
||||
if( pX ){
|
||||
assert( pTest!=0 );
|
||||
@ -2925,9 +2932,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
sqlite3ExprCachePop(pParse, 1);
|
||||
sqlite3VdbeResolveLabel(v, nextCase);
|
||||
}
|
||||
if( pExpr->pRight ){
|
||||
if( (nExpr&1)!=0 ){
|
||||
sqlite3ExprCachePush(pParse);
|
||||
sqlite3ExprCode(pParse, pExpr->pRight, target);
|
||||
sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target);
|
||||
sqlite3ExprCachePop(pParse, 1);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
|
||||
@ -3039,9 +3046,7 @@ int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
|
||||
int iMem;
|
||||
iMem = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem);
|
||||
pExpr->iTable = iMem;
|
||||
pExpr->op2 = pExpr->op;
|
||||
pExpr->op = TK_REGISTER;
|
||||
exprToRegister(pExpr, iMem);
|
||||
}
|
||||
return inReg;
|
||||
}
|
||||
@ -3171,7 +3176,7 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
|
||||
case TK_CONST_FUNC:
|
||||
case TK_FUNCTION: {
|
||||
ExprList *pFarg; /* List of function arguments */
|
||||
if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){
|
||||
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
|
||||
pFarg = 0;
|
||||
}else{
|
||||
pFarg = pExpr->x.pList;
|
||||
@ -3420,9 +3425,7 @@ static int evalConstExpr(Walker *pWalker, Expr *pExpr){
|
||||
** but suboptimal, so we want to know about the situation to fix it.
|
||||
** Hence the following assert: */
|
||||
assert( r2==r1 );
|
||||
pExpr->op2 = pExpr->op;
|
||||
pExpr->op = TK_REGISTER;
|
||||
pExpr->iTable = r2;
|
||||
exprToRegister(pExpr, r2);
|
||||
return WRC_Prune;
|
||||
}
|
||||
return WRC_Continue;
|
||||
@ -3520,9 +3523,7 @@ static void exprCodeBetween(
|
||||
compRight.op = TK_LE;
|
||||
compRight.pLeft = &exprX;
|
||||
compRight.pRight = pExpr->x.pList->a[1].pExpr;
|
||||
exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, ®Free1);
|
||||
exprX.op2 = exprX.op;
|
||||
exprX.op = TK_REGISTER;
|
||||
exprToRegister(&exprX, sqlite3ExprCodeTemp(pParse, &exprX, ®Free1));
|
||||
if( jumpIfTrue ){
|
||||
sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull);
|
||||
}else{
|
||||
@ -3837,8 +3838,8 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
|
||||
if( pA==0||pB==0 ){
|
||||
return pB==pA ? 0 : 2;
|
||||
}
|
||||
assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) );
|
||||
assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) );
|
||||
assert( !ExprHasProperty(pA, EP_TokenOnly|EP_Reduced) );
|
||||
assert( !ExprHasProperty(pB, EP_TokenOnly|EP_Reduced) );
|
||||
if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
|
||||
return 2;
|
||||
}
|
||||
@ -4052,7 +4053,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
||||
struct SrcList_item *pItem = pSrcList->a;
|
||||
for(i=0; i<pSrcList->nSrc; i++, pItem++){
|
||||
struct AggInfo_col *pCol;
|
||||
assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
|
||||
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
|
||||
if( pExpr->iTable==pItem->iCursor ){
|
||||
/* If we reach this point, it means that pExpr refers to a table
|
||||
** that is in the FROM clause of the aggregate query.
|
||||
@ -4147,7 +4148,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
||||
}
|
||||
/* Make pExpr point to the appropriate pAggInfo->aFunc[] entry
|
||||
*/
|
||||
assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
|
||||
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
|
||||
ExprSetIrreducible(pExpr);
|
||||
pExpr->iAgg = (i16)i;
|
||||
pExpr->pAggInfo = pAggInfo;
|
||||
|
32
src/os_win.c
32
src/os_win.c
@ -108,6 +108,14 @@
|
||||
# define winIsDirSep(a) (((a) == '/') || ((a) == '\\'))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This macro is used when a local variable is set to a value that is
|
||||
** [sometimes] not used by the code (e.g. via conditional compilation).
|
||||
*/
|
||||
#ifndef UNUSED_VARIABLE_VALUE
|
||||
# define UNUSED_VARIABLE_VALUE(x) (void)(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Returns the string that should be used as the directory separator.
|
||||
*/
|
||||
@ -358,7 +366,8 @@ const sqlite3_mem_methods *sqlite3MemGetWin32(void);
|
||||
*/
|
||||
#ifdef SQLITE_TEST
|
||||
int sqlite3_os_type = 0;
|
||||
#else
|
||||
#elif !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
|
||||
defined(SQLITE_WIN32_HAS_ANSI) && defined(SQLITE_WIN32_HAS_WIDE)
|
||||
static int sqlite3_os_type = 0;
|
||||
#endif
|
||||
|
||||
@ -1159,7 +1168,7 @@ static void *winMemMalloc(int nBytes){
|
||||
assert( nBytes>=0 );
|
||||
p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
|
||||
if( !p ){
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%lu), heap=%p",
|
||||
nBytes, osGetLastError(), (void*)hHeap);
|
||||
}
|
||||
return p;
|
||||
@ -1180,7 +1189,7 @@ static void winMemFree(void *pPrior){
|
||||
#endif
|
||||
if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
|
||||
if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%lu), heap=%p",
|
||||
pPrior, osGetLastError(), (void*)hHeap);
|
||||
}
|
||||
}
|
||||
@ -1206,7 +1215,7 @@ static void *winMemRealloc(void *pPrior, int nBytes){
|
||||
p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
|
||||
}
|
||||
if( !p ){
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p",
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%lu), heap=%p",
|
||||
pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(),
|
||||
(void*)hHeap);
|
||||
}
|
||||
@ -1230,7 +1239,7 @@ static int winMemSize(void *p){
|
||||
if( !p ) return 0;
|
||||
n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
|
||||
if( n==(SIZE_T)-1 ){
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%lu), heap=%p",
|
||||
p, osGetLastError(), (void*)hHeap);
|
||||
return 0;
|
||||
}
|
||||
@ -1260,7 +1269,7 @@ static int winMemInit(void *pAppData){
|
||||
SQLITE_WIN32_HEAP_MAX_SIZE);
|
||||
if( !pWinMemData->hHeap ){
|
||||
sqlite3_log(SQLITE_NOMEM,
|
||||
"failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
|
||||
"failed to HeapCreate (%lu), flags=%u, initSize=%u, maxSize=%u",
|
||||
osGetLastError(), SQLITE_WIN32_HEAP_FLAGS,
|
||||
SQLITE_WIN32_HEAP_INIT_SIZE, SQLITE_WIN32_HEAP_MAX_SIZE);
|
||||
return SQLITE_NOMEM;
|
||||
@ -1272,7 +1281,7 @@ static int winMemInit(void *pAppData){
|
||||
pWinMemData->hHeap = osGetProcessHeap();
|
||||
if( !pWinMemData->hHeap ){
|
||||
sqlite3_log(SQLITE_NOMEM,
|
||||
"failed to GetProcessHeap (%d)", osGetLastError());
|
||||
"failed to GetProcessHeap (%lu)", osGetLastError());
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pWinMemData->bOwned = FALSE;
|
||||
@ -1300,7 +1309,7 @@ static void winMemShutdown(void *pAppData){
|
||||
#endif
|
||||
if( pWinMemData->bOwned ){
|
||||
if( !osHeapDestroy(pWinMemData->hHeap) ){
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%lu), heap=%p",
|
||||
osGetLastError(), (void*)pWinMemData->hHeap);
|
||||
}
|
||||
pWinMemData->bOwned = FALSE;
|
||||
@ -3185,7 +3194,6 @@ static int winDelete(sqlite3_vfs *,const char*,int);
|
||||
static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
|
||||
winShmNode **pp;
|
||||
winShmNode *p;
|
||||
BOOL bRc;
|
||||
assert( winShmMutexHeld() );
|
||||
OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n",
|
||||
osGetCurrentProcessId(), deleteFlag));
|
||||
@ -3195,12 +3203,14 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
|
||||
int i;
|
||||
if( p->mutex ) sqlite3_mutex_free(p->mutex);
|
||||
for(i=0; i<p->nRegion; i++){
|
||||
bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
|
||||
BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
|
||||
OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",
|
||||
osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
|
||||
UNUSED_VARIABLE_VALUE(bRc);
|
||||
bRc = osCloseHandle(p->aRegion[i].hMap);
|
||||
OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n",
|
||||
osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
|
||||
UNUSED_VARIABLE_VALUE(bRc);
|
||||
}
|
||||
if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
|
||||
SimulateIOErrorBenign(1);
|
||||
@ -3919,6 +3929,7 @@ static const sqlite3_io_methods winIoMethod = {
|
||||
** sqlite3_vfs object.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/*
|
||||
** Convert a filename from whatever the underlying operating system
|
||||
** supports for filenames into UTF-8. Space to hold the result is
|
||||
@ -3937,6 +3948,7 @@ static char *winConvertToUtf8Filename(const void *zFilename){
|
||||
/* caller will handle out of memory */
|
||||
return zConverted;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Convert a UTF-8 filename into whatever form the underlying
|
||||
|
@ -1081,12 +1081,13 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
|
||||
|
||||
/* CASE expressions */
|
||||
expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
|
||||
A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, Z, 0);
|
||||
A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, 0, 0);
|
||||
if( A.pExpr ){
|
||||
A.pExpr->x.pList = Y;
|
||||
A.pExpr->x.pList = Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y;
|
||||
sqlite3ExprSetHeight(pParse, A.pExpr);
|
||||
}else{
|
||||
sqlite3ExprListDelete(pParse->db, Y);
|
||||
sqlite3ExprDelete(pParse->db, Z);
|
||||
}
|
||||
A.zStart = C.z;
|
||||
A.zEnd = &E.z[E.n];
|
||||
|
@ -107,6 +107,7 @@ static void resolveAlias(
|
||||
incrAggFunctionDepth(pDup, nSubquery);
|
||||
pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
|
||||
if( pDup==0 ) return;
|
||||
ExprSetProperty(pDup, EP_Skip);
|
||||
if( pEList->a[iCol].iAlias==0 ){
|
||||
pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
|
||||
}
|
||||
@ -129,7 +130,7 @@ static void resolveAlias(
|
||||
if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
|
||||
assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
|
||||
pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
|
||||
pExpr->flags2 |= EP2_MallocedToken;
|
||||
pExpr->flags |= EP_MemToken;
|
||||
}
|
||||
sqlite3DbFree(db, pDup);
|
||||
}
|
||||
@ -229,7 +230,7 @@ static int lookupName(
|
||||
|
||||
assert( pNC ); /* the name context cannot be NULL. */
|
||||
assert( zCol ); /* The Z in X.Y.Z cannot be NULL */
|
||||
assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
|
||||
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
|
||||
|
||||
/* Initialize the node to no-match */
|
||||
pExpr->iTable = -1;
|
||||
@ -604,7 +605,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
pParse = pNC->pParse;
|
||||
assert( pParse==pWalker->pParse );
|
||||
|
||||
if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return WRC_Prune;
|
||||
if( ExprHasProperty(pExpr, EP_Resolved) ) return WRC_Prune;
|
||||
ExprSetProperty(pExpr, EP_Resolved);
|
||||
#ifndef NDEBUG
|
||||
if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
|
||||
@ -697,7 +698,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
}else{
|
||||
is_agg = pDef->xFunc==0;
|
||||
if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
|
||||
ExprSetProperty(pExpr, EP_Hint);
|
||||
ExprSetProperty(pExpr, EP_Unlikely|EP_Skip);
|
||||
if( n==2 ){
|
||||
pExpr->iTable = exprProbability(pList->a[1].pExpr);
|
||||
if( pExpr->iTable<0 ){
|
||||
|
@ -264,7 +264,7 @@ static void addWhereTerm(
|
||||
pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0);
|
||||
if( pEq && isOuterJoin ){
|
||||
ExprSetProperty(pEq, EP_FromJoin);
|
||||
assert( !ExprHasAnyProperty(pEq, EP_TokenOnly|EP_Reduced) );
|
||||
assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
|
||||
ExprSetIrreducible(pEq);
|
||||
pEq->iRightJoinTable = (i16)pE2->iTable;
|
||||
}
|
||||
@ -300,7 +300,7 @@ static void addWhereTerm(
|
||||
static void setJoinExpr(Expr *p, int iTable){
|
||||
while( p ){
|
||||
ExprSetProperty(p, EP_FromJoin);
|
||||
assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
|
||||
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
|
||||
ExprSetIrreducible(p);
|
||||
p->iRightJoinTable = (i16)iTable;
|
||||
setJoinExpr(p->pLeft, iTable);
|
||||
|
@ -921,8 +921,6 @@ struct sqlite3 {
|
||||
void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
|
||||
void *pCollNeededArg;
|
||||
sqlite3_value *pErr; /* Most recent error message */
|
||||
char *zErrMsg; /* Most recent error message (UTF-8 encoded) */
|
||||
char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */
|
||||
union {
|
||||
volatile int isInterrupted; /* True if sqlite3_interrupt has been called */
|
||||
double notUsed1; /* Spacer */
|
||||
@ -1725,7 +1723,7 @@ typedef int ynVar;
|
||||
struct Expr {
|
||||
u8 op; /* Operation performed by this node */
|
||||
char affinity; /* The affinity of the column or 0 if not a column */
|
||||
u16 flags; /* Various flags. EP_* See below */
|
||||
u32 flags; /* Various flags. EP_* See below */
|
||||
union {
|
||||
char *zToken; /* Token value. Zero terminated and dequoted */
|
||||
int iValue; /* Non-negative integer value if EP_IntValue */
|
||||
@ -1739,8 +1737,8 @@ struct Expr {
|
||||
Expr *pLeft; /* Left subnode */
|
||||
Expr *pRight; /* Right subnode */
|
||||
union {
|
||||
ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */
|
||||
Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */
|
||||
ExprList *pList; /* op = IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */
|
||||
Select *pSelect; /* EP_xIsSelect and op = IN, EXISTS, SELECT */
|
||||
} x;
|
||||
|
||||
/* If the EP_Reduced flag is set in the Expr.flags mask, then no
|
||||
@ -1754,12 +1752,11 @@ struct Expr {
|
||||
int iTable; /* TK_COLUMN: cursor number of table holding column
|
||||
** TK_REGISTER: register number
|
||||
** TK_TRIGGER: 1 -> new, 0 -> old
|
||||
** EP_Hint: 1000 times likelihood */
|
||||
** EP_Unlikely: 1000 times likelihood */
|
||||
ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
|
||||
** TK_VARIABLE: variable number (always >= 1). */
|
||||
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
|
||||
i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
|
||||
u8 flags2; /* Second set of flags. EP2_... */
|
||||
u8 op2; /* TK_REGISTER: original value of Expr.op
|
||||
** TK_COLUMN: the value of p5 for OP_Column
|
||||
** TK_AGG_FUNCTION: nesting depth */
|
||||
@ -1770,28 +1767,25 @@ struct Expr {
|
||||
/*
|
||||
** The following are the meanings of bits in the Expr.flags field.
|
||||
*/
|
||||
#define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */
|
||||
#define EP_Agg 0x0002 /* Contains one or more aggregate functions */
|
||||
#define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */
|
||||
#define EP_Error 0x0008 /* Expression contains one or more errors */
|
||||
#define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */
|
||||
#define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */
|
||||
#define EP_DblQuoted 0x0040 /* token.z was originally in "..." */
|
||||
#define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
|
||||
#define EP_Collate 0x0100 /* Tree contains a TK_COLLATE opeartor */
|
||||
#define EP_FixedDest 0x0200 /* Result needed in a specific register */
|
||||
#define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
|
||||
#define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
|
||||
#define EP_Hint 0x1000 /* The UNLIKELY() SQL function */
|
||||
#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
|
||||
#define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
|
||||
#define EP_Static 0x8000 /* Held in memory not obtained from malloc() */
|
||||
|
||||
/*
|
||||
** The following are the meanings of bits in the Expr.flags2 field.
|
||||
*/
|
||||
#define EP2_MallocedToken 0x0001 /* Need to sqlite3DbFree() Expr.zToken */
|
||||
#define EP2_Irreducible 0x0002 /* Cannot EXPRDUP_REDUCE this Expr */
|
||||
#define EP_FromJoin 0x000001 /* Originated in ON or USING clause of a join */
|
||||
#define EP_Agg 0x000002 /* Contains one or more aggregate functions */
|
||||
#define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */
|
||||
#define EP_Error 0x000008 /* Expression contains one or more errors */
|
||||
#define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */
|
||||
#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
|
||||
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
|
||||
#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
|
||||
#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE opeartor */
|
||||
#define EP_FixedDest 0x000200 /* Result needed in a specific register */
|
||||
#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
|
||||
#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
|
||||
#define EP_Skip 0x001000 /* COLLATE, AS, or UNLIKELY */
|
||||
#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
|
||||
#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
|
||||
#define EP_Static 0x008000 /* Held in memory not obtained from malloc() */
|
||||
#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
|
||||
#define EP_Irreduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
|
||||
#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
|
||||
|
||||
/*
|
||||
** The pseudo-routine sqlite3ExprSetIrreducible sets the EP2_Irreducible
|
||||
@ -1800,7 +1794,7 @@ struct Expr {
|
||||
** so as not to burden production code.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
# define ExprSetIrreducible(X) (X)->flags2 |= EP2_Irreducible
|
||||
# define ExprSetIrreducible(X) (X)->flags |= EP_Irreduce
|
||||
#else
|
||||
# define ExprSetIrreducible(X)
|
||||
#endif
|
||||
@ -1809,8 +1803,8 @@ struct Expr {
|
||||
** These macros can be used to test, set, or clear bits in the
|
||||
** Expr.flags field.
|
||||
*/
|
||||
#define ExprHasProperty(E,P) (((E)->flags&(P))==(P))
|
||||
#define ExprHasAnyProperty(E,P) (((E)->flags&(P))!=0)
|
||||
#define ExprHasProperty(E,P) (((E)->flags&(P))!=0)
|
||||
#define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P))
|
||||
#define ExprSetProperty(E,P) (E)->flags|=(P)
|
||||
#define ExprClearProperty(E,P) (E)->flags&=~(P)
|
||||
|
||||
|
@ -43,7 +43,7 @@ int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
|
||||
testcase( ExprHasProperty(pExpr, EP_Reduced) );
|
||||
rc = pWalker->xExprCallback(pWalker, pExpr);
|
||||
if( rc==WRC_Continue
|
||||
&& !ExprHasAnyProperty(pExpr,EP_TokenOnly) ){
|
||||
&& !ExprHasProperty(pExpr,EP_TokenOnly) ){
|
||||
if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
|
||||
if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
|
@ -689,7 +689,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
|
||||
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
|
||||
}
|
||||
pTerm = &pWC->a[idx = pWC->nTerm++];
|
||||
if( p && ExprHasAnyProperty(p, EP_Hint) ){
|
||||
if( p && ExprHasProperty(p, EP_Unlikely) ){
|
||||
pTerm->truthProb = whereCost(p->iTable) - 99;
|
||||
}else{
|
||||
pTerm->truthProb = -1;
|
||||
|
187
test/tpch01.test
Normal file
187
test/tpch01.test
Normal file
@ -0,0 +1,187 @@
|
||||
# 2013-09-05
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# TPC-H test queries.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix tpch01
|
||||
|
||||
do_execsql_test tpch01-1.0 {
|
||||
CREATE TABLE NATION ( N_NATIONKEY INTEGER NOT NULL,
|
||||
N_NAME CHAR(25) NOT NULL,
|
||||
N_REGIONKEY INTEGER NOT NULL,
|
||||
N_COMMENT VARCHAR(152));
|
||||
CREATE TABLE REGION ( R_REGIONKEY INTEGER NOT NULL,
|
||||
R_NAME CHAR(25) NOT NULL,
|
||||
R_COMMENT VARCHAR(152));
|
||||
CREATE TABLE PART ( P_PARTKEY INTEGER NOT NULL,
|
||||
P_NAME VARCHAR(55) NOT NULL,
|
||||
P_MFGR CHAR(25) NOT NULL,
|
||||
P_BRAND CHAR(10) NOT NULL,
|
||||
P_TYPE VARCHAR(25) NOT NULL,
|
||||
P_SIZE INTEGER NOT NULL,
|
||||
P_CONTAINER CHAR(10) NOT NULL,
|
||||
P_RETAILPRICE DECIMAL(15,2) NOT NULL,
|
||||
P_COMMENT VARCHAR(23) NOT NULL );
|
||||
CREATE TABLE SUPPLIER ( S_SUPPKEY INTEGER NOT NULL,
|
||||
S_NAME CHAR(25) NOT NULL,
|
||||
S_ADDRESS VARCHAR(40) NOT NULL,
|
||||
S_NATIONKEY INTEGER NOT NULL,
|
||||
S_PHONE CHAR(15) NOT NULL,
|
||||
S_ACCTBAL DECIMAL(15,2) NOT NULL,
|
||||
S_COMMENT VARCHAR(101) NOT NULL);
|
||||
CREATE TABLE PARTSUPP ( PS_PARTKEY INTEGER NOT NULL,
|
||||
PS_SUPPKEY INTEGER NOT NULL,
|
||||
PS_AVAILQTY INTEGER NOT NULL,
|
||||
PS_SUPPLYCOST DECIMAL(15,2) NOT NULL,
|
||||
PS_COMMENT VARCHAR(199) NOT NULL );
|
||||
CREATE TABLE CUSTOMER ( C_CUSTKEY INTEGER NOT NULL,
|
||||
C_NAME VARCHAR(25) NOT NULL,
|
||||
C_ADDRESS VARCHAR(40) NOT NULL,
|
||||
C_NATIONKEY INTEGER NOT NULL,
|
||||
C_PHONE CHAR(15) NOT NULL,
|
||||
C_ACCTBAL DECIMAL(15,2) NOT NULL,
|
||||
C_MKTSEGMENT CHAR(10) NOT NULL,
|
||||
C_COMMENT VARCHAR(117) NOT NULL);
|
||||
CREATE TABLE ORDERS ( O_ORDERKEY INTEGER NOT NULL,
|
||||
O_CUSTKEY INTEGER NOT NULL,
|
||||
O_ORDERSTATUS CHAR(1) NOT NULL,
|
||||
O_TOTALPRICE DECIMAL(15,2) NOT NULL,
|
||||
O_ORDERDATE DATE NOT NULL,
|
||||
O_ORDERPRIORITY CHAR(15) NOT NULL,
|
||||
O_CLERK CHAR(15) NOT NULL,
|
||||
O_SHIPPRIORITY INTEGER NOT NULL,
|
||||
O_COMMENT VARCHAR(79) NOT NULL);
|
||||
CREATE TABLE LINEITEM ( L_ORDERKEY INTEGER NOT NULL,
|
||||
L_PARTKEY INTEGER NOT NULL,
|
||||
L_SUPPKEY INTEGER NOT NULL,
|
||||
L_LINENUMBER INTEGER NOT NULL,
|
||||
L_QUANTITY DECIMAL(15,2) NOT NULL,
|
||||
L_EXTENDEDPRICE DECIMAL(15,2) NOT NULL,
|
||||
L_DISCOUNT DECIMAL(15,2) NOT NULL,
|
||||
L_TAX DECIMAL(15,2) NOT NULL,
|
||||
L_RETURNFLAG CHAR(1) NOT NULL,
|
||||
L_LINESTATUS CHAR(1) NOT NULL,
|
||||
L_SHIPDATE DATE NOT NULL,
|
||||
L_COMMITDATE DATE NOT NULL,
|
||||
L_RECEIPTDATE DATE NOT NULL,
|
||||
L_SHIPINSTRUCT CHAR(25) NOT NULL,
|
||||
L_SHIPMODE CHAR(10) NOT NULL,
|
||||
L_COMMENT VARCHAR(44) NOT NULL);
|
||||
CREATE INDEX npki on nation(N_NATIONKEY);
|
||||
CREATE INDEX rpki on region(R_REGIONKEY);
|
||||
CREATE INDEX ppki on part(P_PARTKEY);
|
||||
CREATE INDEX spki on supplier(S_SUPPKEY);
|
||||
CREATE INDEX pspki on partsupp(PS_PARTKEY, PS_SUPPKEY);
|
||||
CREATE INDEX cpki on customer(C_CUSTKEY);
|
||||
CREATE INDEX opki on orders(O_ORDERKEY);
|
||||
CREATE INDEX lpki on lineitem(L_ORDERKEY, L_LINENUMBER);
|
||||
CREATE INDEX nrki on nation(n_regionkey);
|
||||
CREATE INDEX snki on supplier(s_nationkey);
|
||||
CREATE INDEX cnki on customer(c_nationkey);
|
||||
CREATE INDEX ocki on orders(O_CUSTKEY);
|
||||
CREATE INDEX odi on orders(O_ORDERDATE);
|
||||
CREATE INDEX lpki2 on lineitem(L_PARTKEY);
|
||||
CREATE INDEX lski on lineitem(L_SUPPKEY);
|
||||
CREATE INDEX lsdi on lineitem(L_SHIPDATE);
|
||||
CREATE INDEX lcdi on lineitem(L_COMMITDATE);
|
||||
CREATE INDEX lrdi on lineitem(L_RECEIPTDATE);
|
||||
CREATE INDEX bootleg_nni on nation(N_NAME);
|
||||
CREATE INDEX bootleg_psi on part(p_size);
|
||||
CREATE INDEX bootleg_pti on part(p_type);
|
||||
ANALYZE sqlite_master;
|
||||
INSERT INTO sqlite_stat1 VALUES('LINEITEM','lrdi','600572 236');
|
||||
INSERT INTO sqlite_stat1 VALUES('LINEITEM','lcdi','600572 244');
|
||||
INSERT INTO sqlite_stat1 VALUES('LINEITEM','lsdi','600572 238');
|
||||
INSERT INTO sqlite_stat1 VALUES('LINEITEM','lski','600572 601');
|
||||
INSERT INTO sqlite_stat1 VALUES('LINEITEM','lpki2','600572 31');
|
||||
INSERT INTO sqlite_stat1 VALUES('LINEITEM','lpki','600572 5 1');
|
||||
INSERT INTO sqlite_stat1 VALUES('ORDERS','odi','150000 63');
|
||||
INSERT INTO sqlite_stat1 VALUES('ORDERS','ocki','150000 15');
|
||||
INSERT INTO sqlite_stat1 VALUES('ORDERS','opki','150000 1');
|
||||
INSERT INTO sqlite_stat1 VALUES('CUSTOMER','cnki','15000 600');
|
||||
INSERT INTO sqlite_stat1 VALUES('CUSTOMER','cpki','15000 1');
|
||||
INSERT INTO sqlite_stat1 VALUES('PARTSUPP','pspki','80000 4 1');
|
||||
INSERT INTO sqlite_stat1 VALUES('SUPPLIER','snki','1000 40');
|
||||
INSERT INTO sqlite_stat1 VALUES('SUPPLIER','spki','1000 1');
|
||||
INSERT INTO sqlite_stat1 VALUES('PART','bootleg_pti','20000 134');
|
||||
INSERT INTO sqlite_stat1 VALUES('PART','bootleg_psi','20000 400');
|
||||
INSERT INTO sqlite_stat1 VALUES('PART','ppki','20000 1');
|
||||
INSERT INTO sqlite_stat1 VALUES('REGION','rpki','5 1');
|
||||
INSERT INTO sqlite_stat1 VALUES('NATION','bootleg_nni','25 1');
|
||||
INSERT INTO sqlite_stat1 VALUES('NATION','nrki','25 5');
|
||||
INSERT INTO sqlite_stat1 VALUES('NATION','npki','25 1');
|
||||
ANALYZE sqlite_master;
|
||||
} {}
|
||||
|
||||
do_test tpch01-1.1 {
|
||||
unset -nocomplain ::eqpres
|
||||
set ::eqpres [db eval {EXPLAIN QUERY PLAN
|
||||
select
|
||||
o_year,
|
||||
sum(case
|
||||
when nation = 'EGYPT' then volume
|
||||
else 0
|
||||
end) / sum(volume) as mkt_share
|
||||
from
|
||||
(
|
||||
select
|
||||
strftime('%Y', o_orderdate) as o_year,
|
||||
l_extendedprice * (1 - l_discount) as volume,
|
||||
n2.n_name as nation
|
||||
from
|
||||
part,
|
||||
supplier,
|
||||
lineitem,
|
||||
orders,
|
||||
customer,
|
||||
nation n1,
|
||||
nation n2,
|
||||
region
|
||||
where
|
||||
p_partkey = l_partkey
|
||||
and s_suppkey = l_suppkey
|
||||
and l_orderkey = o_orderkey
|
||||
and o_custkey = c_custkey
|
||||
and c_nationkey = n1.n_nationkey
|
||||
and n1.n_regionkey = r_regionkey
|
||||
and r_name = 'MIDDLE EAST'
|
||||
and s_nationkey = n2.n_nationkey
|
||||
and o_orderdate between '1995-01-01' and '1996-12-31'
|
||||
and p_type = 'LARGE PLATED STEEL'
|
||||
) as all_nations
|
||||
group by
|
||||
o_year
|
||||
order by
|
||||
o_year;}]
|
||||
set ::eqpres
|
||||
} {/0 0 0 {SEARCH TABLE part USING INDEX bootleg_pti .P_TYPE=..} 0 1 2 {SEARCH TABLE lineitem USING INDEX lpki2 .L_PARTKEY=..}.*/}
|
||||
do_test tpch01-1.1b {
|
||||
set ::eqpres
|
||||
} {/.* customer .* nation AS n1 .* nation AS n2 .*/}
|
||||
|
||||
do_eqp_test tpch01-1.2 {
|
||||
select
|
||||
c_custkey, c_name, sum(l_extendedprice * (1 - l_discount)) as revenue,
|
||||
c_acctbal, n_name, c_address, c_phone, c_comment
|
||||
from
|
||||
customer, orders, lineitem, nation
|
||||
where
|
||||
c_custkey = o_custkey and l_orderkey = o_orderkey
|
||||
and o_orderdate >= '1994-08-01' and o_orderdate < date('1994-08-01', '+3 month')
|
||||
and l_returnflag = 'R' and c_nationkey = n_nationkey
|
||||
group by
|
||||
c_custkey, c_name, c_acctbal, c_phone, n_name, c_address, c_comment
|
||||
order by
|
||||
revenue desc;
|
||||
} {0 0 1 {SEARCH TABLE orders USING INDEX odi (O_ORDERDATE>? AND O_ORDERDATE<?)} 0 1 0 {SEARCH TABLE customer USING INDEX cpki (C_CUSTKEY=?)} 0 2 3 {SEARCH TABLE nation USING INDEX npki (N_NATIONKEY=?)} 0 3 2 {SEARCH TABLE lineitem USING INDEX lpki (L_ORDERKEY=?)} 0 0 0 {USE TEMP B-TREE FOR GROUP BY} 0 0 0 {USE TEMP B-TREE FOR ORDER BY}}
|
Loading…
Reference in New Issue
Block a user