Compare commits

...

1 Commits

Author SHA1 Message Date
drh ee07978c9a Experimental changes that reduce the size of Expr objects from 72 to 64
bytes each on x64 and from 48 to 44 bytes each on x32.

FossilOrigin-Name: 8ad0a123a2046e4bf95b4f9c28f26221afb3fc43
2014-05-06 15:28:56 +00:00
11 changed files with 214 additions and 138 deletions
+18 -15
View File
@@ -1,5 +1,5 @@
C When\sbuilding\sfor\sWindows\s8.0\susing\sVisual\sStudio\s2013,\smake\ssure\sthe\scross-compilation\snative\slibrary\spath\sis\sset\scorrectly.
D 2014-05-05T22:43:17.621
C Experimental\schanges\sthat\sreduce\sthe\ssize\sof\sExpr\sobjects\sfrom\s72\sto\s64\nbytes\seach\son\sx64\sand\sfrom\s48\sto\s44\sbytes\seach\son\sx32.
D 2014-05-06T15:28:56.475
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in dd2b1aba364ff9b05de41086f74407f285c57670
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -160,7 +160,7 @@ F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c b00900877f766f116f9e16116f1ccacdc21d82f1
F src/analyze.c 3596f863bb80126fe56ba217df5932749271efc8
F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52
F src/attach.c a1ada8e4177827c5873aa356b933f2d4d1293a9a
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
@@ -174,10 +174,10 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
F src/delete.c bcf8f72126cea80fc3d5bc5494cf19b3f8935aaf
F src/expr.c 4f9e497c66e2f25a4d139357a778c84d5713207c
F src/expr.c 78326e5d1fa27a88a6c037fabc6c63359695e937
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 5269ef07b100763134f71b889327c333bd0989cf
F src/func.c 2945bb2c4cdc0ac43733046285a4434310be1811
F src/func.c 863735228a1ff6e225a8904169644a4fd40df43c
F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486
F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
@@ -210,7 +210,7 @@ F src/os_win.c 485d06a93965f306c7281fca0937829292367234
F src/os_win.h 057344a6720b4c8405d9bd98f58cb37a6ee46c25
F src/pager.c ab62a24218d87dda1be641f6c5ad291bff78fd94
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0
F src/parse.y b9adfa13ce569c12aa157c8ebc5fdc670f1a0acb
F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c
@@ -218,14 +218,14 @@ F src/pragma.c 810ef31ccfaa233201dcf100637a9777cc24e897
F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337
F src/printf.c e5a0005f8b3de21f85da6a709d2fbee76775bf4b
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66
F src/resolve.c 06b706383c66ba05f515014fb7f37e84a22fdf96
F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
F src/select.c 089c4d46f067a5cccae93524c6377f981ba99bd9
F src/select.c 109d659ed3f949e11de6bc74afe6a56b68ff3b80
F src/shell.c 2afe7a7154e97be0c74c5feacf09626bda8493be
F src/sqlite.h.in bde98816e1ba0c9ffef50afe7b32f4e5a8f54fe0
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h b2947801eccefd7ba3e5f14e1353289351a83cf3
F src/sqliteInt.h 23b03ab00dac71f2402eb9fd977aaed735d42c0c
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -293,8 +293,8 @@ F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
F src/where.c 91dfd382273c3f67fcdc0ac4728f9140f91c6ab3
F src/walker.c 4a73ee39c361017532530ef18066d7e87e0d9bd0
F src/where.c b8df0204d0e7bfe735f7892d8e96493652d607ac
F src/whereInt.h 6804c2e5010378568c2bb1350477537755296a46
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -1168,7 +1168,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
P 9a06773acc181e981f61f476a8e56417b98beba9
R e91b1cf1dddb5793408fd6de2be74034
U mistachkin
Z b713eaa9517cf3b104e3dc82bdd65124
P c1ab9092e29bc9d172c1f1a3becbcc83b79f2080
R 4b8f36fa136ae7cf835aa3d588ac1c25
T *branch * smaller-expr
T *sym-smaller-expr *
T -sym-trunk *
U drh
Z 8672a4e9e0a77fa3f766205961da49e1
+1 -1
View File
@@ -1 +1 @@
c1ab9092e29bc9d172c1f1a3becbcc83b79f2080
8ad0a123a2046e4bf95b4f9c28f26221afb3fc43
+4 -4
View File
@@ -524,14 +524,14 @@ int sqlite3FixExpr(
}
}
if( ExprHasProperty(pExpr, EP_TokenOnly) ) break;
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
if( ExprUsesRight(pExpr) ){
if( sqlite3FixExpr(pFix, pExpr->x.pRight) ) return 1;
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
}else{
assert( ExprHasProperty(pExpr, EP_xIsList) );
if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
}
if( sqlite3FixExpr(pFix, pExpr->pRight) ){
return 1;
}
pExpr = pExpr->pLeft;
}
return 0;
+87 -53
View File
@@ -36,7 +36,7 @@ char sqlite3ExprAffinity(Expr *pExpr){
if( pExpr->flags & EP_Generic ) return SQLITE_AFF_NONE;
op = pExpr->op;
if( op==TK_SELECT ){
assert( pExpr->flags&EP_xIsSelect );
assert( ExprHasProperty(pExpr, EP_xIsSelect) );
return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
}
#ifndef SQLITE_OMIT_CAST
@@ -96,7 +96,7 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
Expr *sqlite3ExprSkipCollate(Expr *pExpr){
while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
if( ExprHasProperty(pExpr, EP_Unlikely) ){
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
assert( ExprHasProperty(pExpr, EP_xIsList) );
assert( pExpr->x.pList->nExpr>0 );
assert( pExpr->op==TK_FUNCTION );
pExpr = pExpr->x.pList->a[0].pExpr;
@@ -148,8 +148,8 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
if( p->flags & EP_Collate ){
if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){
p = p->pLeft;
}else{
p = p->pRight;
}else if( ExprUsesRight(p) ){
p = p->x.pRight;
}
}else{
break;
@@ -200,8 +200,8 @@ static char comparisonAffinity(Expr *pExpr){
pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT );
assert( pExpr->pLeft );
aff = sqlite3ExprAffinity(pExpr->pLeft);
if( pExpr->pRight ){
aff = sqlite3CompareAffinity(pExpr->pRight, aff);
if( ExprUsesRight(pExpr) ){
aff = sqlite3CompareAffinity(pExpr->x.pRight, aff);
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
}else if( !aff ){
@@ -359,10 +359,12 @@ static void heightOfSelect(Select *p, int *pnHeight){
static void exprSetHeight(Expr *p){
int nHeight = 0;
heightOfExpr(p->pLeft, &nHeight);
heightOfExpr(p->pRight, &nHeight);
if( ExprHasProperty(p, EP_xIsSelect) ){
if( ExprUsesRight(p) ){
heightOfExpr(p->x.pRight, &nHeight);
}else if( ExprHasProperty(p, EP_xIsSelect) ){
heightOfSelect(p->x.pSelect, &nHeight);
}else{
assert( ExprHasProperty(p, EP_xIsList) );
heightOfExprList(p->x.pList, &nHeight);
}
p->nHeight = nHeight + 1;
@@ -489,8 +491,8 @@ void sqlite3ExprAttachSubtrees(
sqlite3ExprDelete(db, pRight);
}else{
if( pRight ){
pRoot->pRight = pRight;
pRoot->flags |= EP_Collate & pRight->flags;
pRoot->x.pRight = pRight;
pRoot->flags |= (EP_Collate & pRight->flags);
}
if( pLeft ){
pRoot->pLeft = pLeft;
@@ -593,7 +595,7 @@ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
return 0;
}
pNew->x.pList = pList;
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
ExprSetProperty(pNew, EP_xIsList);
sqlite3ExprSetHeight(pParse, pNew);
return pNew;
}
@@ -690,14 +692,16 @@ void sqlite3ExprDelete(sqlite3 *db, Expr *p){
/* Sanity check: Assert that the IntValue is non-negative if it exists */
assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
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_MemToken) ) sqlite3DbFree(db, p->u.zToken);
if( ExprHasProperty(p, EP_xIsSelect) ){
if( ExprHasProperty(p, EP_MemToken) ){
sqlite3DbFree(db, p->u.zToken);
}
if( ExprUsesRight(p) ){
sqlite3ExprDelete(db, p->x.pRight);
}else if( ExprHasProperty(p, EP_xIsSelect) ){
sqlite3SelectDelete(db, p->x.pSelect);
}else{
assert( ExprHasProperty(p, EP_xIsList) );
sqlite3ExprListDelete(db, p->x.pList);
}
}
@@ -766,7 +770,6 @@ static int dupedExprStructSize(Expr *p, int flags){
if( p->pLeft || p->x.pList ){
nSize = EXPR_REDUCEDSIZE | EP_Reduced;
}else{
assert( p->pRight==0 );
nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
}
}
@@ -804,7 +807,10 @@ static int dupedExprSize(Expr *p, int flags){
if( p ){
nByte = dupedExprNodeSize(p, flags);
if( flags&EXPRDUP_REDUCE ){
nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags);
nByte += dupedExprSize(p->pLeft, flags);
if( ExprUsesRight(p) ){
nByte += dupedExprSize(p->x.pRight, flags);
}
}
}
return nByte;
@@ -814,7 +820,7 @@ static int dupedExprSize(Expr *p, int flags){
** This function is similar to sqlite3ExprDup(), except that if pzBuffer
** is not NULL then *pzBuffer is assumed to point to a buffer large enough
** to store the copy of expression p, the copies of p->u.zToken
** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
** (if applicable), and the copies of the p->pLeft and p->x.pRight expressions,
** if any. Before returning, *pzBuffer is set to the first byte passed the
** portion of the buffer copied into by this function.
*/
@@ -874,17 +880,20 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
/* Fill in the pNew->x.pSelect or pNew->x.pList member. */
if( ExprHasProperty(p, EP_xIsSelect) ){
pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, isReduced);
}else{
}else if( ExprHasProperty(p, EP_xIsList) ){
pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, isReduced);
}
}
/* Fill in pNew->pLeft and pNew->pRight. */
/* Fill in pNew->pLeft and pNew->x.pRight. */
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);
pNew->pRight = exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc);
if( ExprUsesRight(p) ){
assert( ExprUsesRight(p) );
pNew->x.pRight = exprDup(db, p->x.pRight, EXPRDUP_REDUCE, &zAlloc);
}
}
if( pzBuffer ){
*pzBuffer = zAlloc;
@@ -892,7 +901,10 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
}else{
if( !ExprHasProperty(p, EP_TokenOnly) ){
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
if( ExprUsesRight(p) ){
assert( ExprUsesRight(pNew) );
pNew->x.pRight = sqlite3ExprDup(db, p->x.pRight, 0);
}
}
}
@@ -2530,8 +2542,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
case TK_NE:
case TK_EQ: {
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
assert( ExprUsesRight(pExpr) );
r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->x.pRight, op,
r1, r2, inReg, SQLITE_STOREP2);
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
@@ -2548,9 +2561,10 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
testcase( op==TK_IS );
testcase( op==TK_ISNOT );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
assert( ExprUsesRight(pExpr) );
r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, &regFree2);
op = (op==TK_IS) ? TK_EQ : TK_NE;
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
codeCompare(pParse, pExpr->pLeft, pExpr->x.pRight, op,
r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ);
VdbeCoverageIf(v, op==TK_EQ);
VdbeCoverageIf(v, op==TK_NE);
@@ -2582,7 +2596,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
assert( TK_RSHIFT==OP_ShiftRight ); testcase( op==TK_RSHIFT );
assert( TK_CONCAT==OP_Concat ); testcase( op==TK_CONCAT );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
assert( ExprUsesRight(pExpr) );
r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, &regFree2);
sqlite3VdbeAddOp3(v, op, r2, r1, target);
testcase( regFree1==0 );
testcase( regFree2==0 );
@@ -2656,10 +2671,10 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
u8 enc = ENC(db); /* The text encoding used by this database */
CollSeq *pColl = 0; /* A collating sequence */
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
}else{
assert( ExprHasProperty(pExpr, EP_xIsList) );
pFarg = pExpr->x.pList;
}
nFarg = pFarg ? pFarg->nExpr : 0;
@@ -2926,7 +2941,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */
VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; )
assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
assert( ExprHasProperty(pExpr, EP_xIsList) && pExpr->x.pList );
assert(pExpr->x.pList->nExpr > 0);
pEList = pExpr->x.pList;
aListelem = pEList->a;
@@ -2938,6 +2953,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
exprToRegister(&tempX, sqlite3ExprCodeTemp(pParse, pX, &regFree1));
testcase( regFree1==0 );
opCompare.op = TK_EQ;
opCompare.flags = 0;
opCompare.pLeft = &tempX;
pTest = &opCompare;
/* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001:
@@ -2950,7 +2966,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
sqlite3ExprCachePush(pParse);
if( pX ){
assert( pTest!=0 );
opCompare.pRight = aListelem[i].pExpr;
opCompare.x.pRight = aListelem[i].pExpr;
}else{
pTest = aListelem[i].pExpr;
}
@@ -3364,7 +3380,8 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
sqlite3ExplainPrintf(pOut,"%s(", zBinOp);
sqlite3ExplainExpr(pOut, pExpr->pLeft);
sqlite3ExplainPrintf(pOut,",");
sqlite3ExplainExpr(pOut, pExpr->pRight);
assert( ExprUsesRight(pExpr) );
sqlite3ExplainExpr(pOut, pExpr->x.pRight);
sqlite3ExplainPrintf(pOut,")");
}else if( zUniOp ){
sqlite3ExplainPrintf(pOut,"%s(", zUniOp);
@@ -3482,17 +3499,20 @@ static void exprCodeBetween(
Expr exprX; /* The x subexpression */
int regFree1 = 0; /* Temporary use register */
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
assert( ExprHasProperty(pExpr, EP_xIsList) );
exprX = *pExpr->pLeft;
exprAnd.op = TK_AND;
exprAnd.flags = 0;
exprAnd.pLeft = &compLeft;
exprAnd.pRight = &compRight;
exprAnd.x.pRight = &compRight;
compLeft.op = TK_GE;
compLeft.flags = 0;
compLeft.pLeft = &exprX;
compLeft.pRight = pExpr->x.pList->a[0].pExpr;
compLeft.x.pRight = pExpr->x.pList->a[0].pExpr;
compRight.op = TK_LE;
compRight.flags = 0;
compRight.pLeft = &exprX;
compRight.pRight = pExpr->x.pList->a[1].pExpr;
compRight.x.pRight = pExpr->x.pList->a[1].pExpr;
exprToRegister(&exprX, sqlite3ExprCodeTemp(pParse, &exprX, &regFree1));
if( jumpIfTrue ){
sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull);
@@ -3543,7 +3563,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
sqlite3ExprCachePush(pParse);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
assert( ExprUsesRight(pExpr) );
sqlite3ExprIfTrue(pParse, pExpr->x.pRight, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2);
sqlite3ExprCachePop(pParse);
break;
@@ -3552,7 +3573,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
sqlite3ExprCachePush(pParse);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
assert( ExprUsesRight(pExpr) );
sqlite3ExprIfTrue(pParse, pExpr->x.pRight, dest, jumpIfNull);
sqlite3ExprCachePop(pParse);
break;
}
@@ -3569,8 +3591,9 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
case TK_EQ: {
testcase( jumpIfNull==0 );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
assert( ExprUsesRight(pExpr) );
r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->x.pRight, op,
r1, r2, dest, jumpIfNull);
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
@@ -3587,9 +3610,10 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
testcase( op==TK_IS );
testcase( op==TK_ISNOT );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
assert( ExprUsesRight(pExpr) );
r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, &regFree2);
op = (op==TK_IS) ? TK_EQ : TK_NE;
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
codeCompare(pParse, pExpr->pLeft, pExpr->x.pRight, op,
r1, r2, dest, SQLITE_NULLEQ);
VdbeCoverageIf(v, op==TK_EQ);
VdbeCoverageIf(v, op==TK_NE);
@@ -3698,7 +3722,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
assert( ExprUsesRight(pExpr) );
sqlite3ExprIfFalse(pParse, pExpr->x.pRight, dest, jumpIfNull);
sqlite3ExprCachePop(pParse);
break;
}
@@ -3707,7 +3732,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
assert( ExprUsesRight(pExpr) );
sqlite3ExprIfFalse(pParse, pExpr->x.pRight, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2);
sqlite3ExprCachePop(pParse);
break;
@@ -3725,8 +3751,9 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
case TK_EQ: {
testcase( jumpIfNull==0 );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
assert( ExprUsesRight(pExpr) );
r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->x.pRight, op,
r1, r2, dest, jumpIfNull);
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
@@ -3743,9 +3770,10 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
testcase( pExpr->op==TK_IS );
testcase( pExpr->op==TK_ISNOT );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
assert( ExprUsesRight(pExpr) );
r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, &regFree2);
op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
codeCompare(pParse, pExpr->pLeft, pExpr->x.pRight, op,
r1, r2, dest, SQLITE_NULLEQ);
VdbeCoverageIf(v, op==TK_EQ);
VdbeCoverageIf(v, op==TK_NE);
@@ -3848,10 +3876,16 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
}
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
if( combinedFlags & EP_xIsSelect ) return 2;
if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2;
if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2;
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
if( (pA->flags&EP_xMask)!=(pB->flags&EP_xMask) ) return 2;
if( ExprUsesRight(pA) ){
if( sqlite3ExprCompare(pA->x.pRight, pB->x.pRight, iTab) ) return 2;
}else if( ExprHasProperty(pA, EP_xIsSelect) ){
return 2;
}else{
assert( ExprHasProperty(pA, EP_xIsList) );
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
}
if( ALWAYS((combinedFlags & EP_Reduced)==0) ){
if( pA->iColumn!=pB->iColumn ) return 2;
if( pA->iTable!=pB->iTable
@@ -3916,7 +3950,7 @@ int sqlite3ExprImpliesExpr(Expr *pE1, Expr *pE2, int iTab){
}
if( pE2->op==TK_OR
&& (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab)
|| sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) )
|| sqlite3ExprImpliesExpr(pE1, pE2->x.pRight, iTab) )
){
return 1;
}
@@ -4119,7 +4153,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
u8 enc = ENC(pParse->db);
i = addAggInfoFunc(pParse->db, pAggInfo);
if( i>=0 ){
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
assert( ExprHasProperty(pExpr, EP_xIsList) );
pItem = &pAggInfo->aFunc[i];
pItem->pExpr = pExpr;
pItem->iMem = ++pParse->nMem;
+4 -6
View File
@@ -1606,7 +1606,7 @@ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
}
/*
** pExpr points to an expression which implements a function. If
** pExpr might point to an expression which implements a function. If
** it is appropriate to apply the LIKE optimization to that function
** then set aWc[0] through aWc[2] to the wildcard characters and
** return TRUE. If the function is not a LIKE-style function then
@@ -1614,13 +1614,11 @@ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
*/
int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
FuncDef *pDef;
if( pExpr->op!=TK_FUNCTION
|| !pExpr->x.pList
|| pExpr->x.pList->nExpr!=2
){
if( pExpr->op!=TK_FUNCTION ) return 0;
assert( ExprHasProperty(pExpr, EP_xIsList) || pExpr->x.pList==0 );
if( !pExpr->x.pList || pExpr->x.pList->nExpr!=2 ){
return 0;
}
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
pDef = sqlite3FindFunction(db, pExpr->u.zToken,
sqlite3Strlen30(pExpr->u.zToken),
2, SQLITE_UTF8, 0);
+6 -2
View File
@@ -942,8 +942,9 @@ expr(A) ::= expr(X) NOT NULL(E). {spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);}
sqlite3 *db = pParse->db;
if( db->mallocFailed==0 && pY->op==TK_NULL ){
pA->op = (u8)op;
sqlite3ExprDelete(db, pA->pRight);
pA->pRight = 0;
assert( ExprUsesRight(pA) );
sqlite3ExprDelete(db, pA->x.pRight);
pA->x.pRight = 0;
}
}
}
@@ -997,6 +998,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
A.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, W.pExpr, 0, 0);
if( A.pExpr ){
A.pExpr->x.pList = pList;
ExprSetProperty(A.pExpr, EP_xIsList);
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
@@ -1051,6 +1053,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0);
if( A.pExpr ){
A.pExpr->x.pList = Y;
ExprSetProperty(A.pExpr, EP_xIsList);
sqlite3ExprSetHeight(pParse, A.pExpr);
}else{
sqlite3ExprListDelete(pParse->db, Y);
@@ -1118,6 +1121,7 @@ expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, 0, 0);
if( A.pExpr ){
A.pExpr->x.pList = Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y;
ExprSetProperty(A.pExpr, EP_xIsList);
sqlite3ExprSetHeight(pParse, A.pExpr);
}else{
sqlite3ExprListDelete(pParse->db, Y);
+11 -7
View File
@@ -197,7 +197,7 @@ int sqlite3MatchSpanName(
** pExpr->iColumn Set to the column number within the table.
** pExpr->op Set to TK_COLUMN.
** pExpr->pLeft Any expression this points to is deleted
** pExpr->pRight Any expression this points to is deleted.
** pExpr->x.pRight Any expression this points to is deleted.
**
** The zDb variable is the name of the database (the "X"). This value may be
** NULL meaning that name is of the form Y.Z or Z. Any available database
@@ -415,7 +415,7 @@ static int lookupName(
char *zAs = pEList->a[j].zName;
if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
Expr *pOrig;
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
assert( pExpr->pLeft==0 && pExpr->x.pRight==0 );
assert( pExpr->x.pList==0 );
assert( pExpr->x.pSelect==0 );
pOrig = pEList->a[j].pExpr;
@@ -495,8 +495,10 @@ static int lookupName(
*/
sqlite3ExprDelete(db, pExpr->pLeft);
pExpr->pLeft = 0;
sqlite3ExprDelete(db, pExpr->pRight);
pExpr->pRight = 0;
if( ExprUsesRight(pExpr) ){
sqlite3ExprDelete(db, pExpr->x.pRight);
pExpr->x.pRight = 0;
}
pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN);
lookupname_end:
if( cnt==1 ){
@@ -655,16 +657,18 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
Expr *pRight;
/* if( pSrcList==0 ) break; */
pRight = pExpr->pRight;
assert( ExprUsesRight(pExpr) );
pRight = pExpr->x.pRight;
if( pRight->op==TK_ID ){
zDb = 0;
zTable = pExpr->pLeft->u.zToken;
zColumn = pRight->u.zToken;
}else{
assert( pRight->op==TK_DOT );
assert( ExprUsesRight(pRight) );
zDb = pExpr->pLeft->u.zToken;
zTable = pRight->pLeft->u.zToken;
zColumn = pRight->pRight->u.zToken;
zColumn = pRight->x.pRight->u.zToken;
}
return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
}
@@ -683,7 +687,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
FuncDef *pDef; /* Information about the function */
u8 enc = ENC(pParse->db); /* The database encoding */
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
assert( ExprHasProperty(pExpr, EP_xIsList) || pList==0 );
notValidPartIdxWhere(pParse, pNC, "functions");
zId = pExpr->u.zToken;
nId = sqlite3Strlen30(zId);
+16 -12
View File
@@ -340,7 +340,7 @@ static void setJoinExpr(Expr *p, int iTable){
ExprSetVVAProperty(p, EP_NoReduce);
p->iRightJoinTable = (i16)iTable;
setJoinExpr(p->pLeft, iTable);
p = p->pRight;
p = ExprUsesRight(p) ? p->x.pRight : 0;
}
}
@@ -1562,7 +1562,8 @@ static int selectColumnsFromExprList(
Expr *pColExpr = p; /* The expression that is the result column name */
Table *pTab; /* Table associated with this expression */
while( pColExpr->op==TK_DOT ){
pColExpr = pColExpr->pRight;
assert( ExprUsesRight(pColExpr) );
pColExpr = pColExpr->x.pRight;
assert( pColExpr!=0 );
}
if( pColExpr->op==TK_COLUMN && ALWAYS(pColExpr->pTab!=0) ){
@@ -2994,17 +2995,19 @@ static Expr *substExpr(
}else{
Expr *pNew;
assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
assert( pExpr->pLeft==0 && pExpr->x.pRight==0 );
pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0);
sqlite3ExprDelete(db, pExpr);
pExpr = pNew;
}
}else{
pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList);
pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
if( ExprUsesRight(pExpr) ){
pExpr->x.pRight = substExpr(db, pExpr->x.pRight, iTable, pEList);
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
substSelect(db, pExpr->x.pSelect, iTable, pEList);
}else{
assert( ExprHasProperty(pExpr, EP_xIsList) );
substExprList(db, pExpr->x.pList, iTable, pEList);
}
}
@@ -4054,9 +4057,9 @@ static int selectExpander(Walker *pWalker, Select *p){
for(k=0; k<pEList->nExpr; k++){
pE = pEList->a[k].pExpr;
if( pE->op==TK_ALL ) break;
assert( pE->op!=TK_DOT || pE->pRight!=0 );
assert( pE->op!=TK_DOT || !ExprUsesRight(pE) || pE->x.pRight!=0 );
assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break;
if( pE->op==TK_DOT && pE->x.pRight->op==TK_ALL ) break;
}
if( k<pEList->nExpr ){
/*
@@ -4079,7 +4082,7 @@ static int selectExpander(Walker *pWalker, Select *p){
for(k=0; k<pEList->nExpr; k++){
pE = a[k].pExpr;
pRight = pE->pRight;
pRight = ExprUsesRight(pE) ? pE->x.pRight : 0;
assert( pE->op!=TK_DOT || pRight!=0 );
if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){
/* This particular expression does not need to be expanded.
@@ -4376,7 +4379,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
if( pFunc->iDistinct>=0 ){
Expr *pE = pFunc->pExpr;
assert( !ExprHasProperty(pE, EP_xIsSelect) );
assert( ExprHasProperty(pE, EP_xIsList) || pE->x.pList==0 );
if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
"argument");
@@ -4400,7 +4403,7 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
struct AggInfo_func *pF;
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
ExprList *pList = pF->pExpr->x.pList;
assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
assert( ExprHasProperty(pF->pExpr, EP_xIsList) || pList==0 );
sqlite3VdbeAddOp4(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0, 0,
(void*)pF->pFunc, P4_FUNCDEF);
}
@@ -4424,7 +4427,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
int addrNext = 0;
int regAgg;
ExprList *pList = pF->pExpr->x.pList;
assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
assert( ExprHasProperty(pF->pExpr, EP_xIsList) || pList==0 );
if( pList ){
nArg = pList->nExpr;
regAgg = sqlite3GetTempRange(pParse, nArg);
@@ -4899,7 +4902,8 @@ int sqlite3Select(
}
sAggInfo.nAccumulator = sAggInfo.nColumn;
for(i=0; i<sAggInfo.nFunc; i++){
assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) );
assert( ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsList)
|| sAggInfo.aFunc[i].pExpr->x.pList==0 );
sNC.ncFlags |= NC_InAggFunc;
sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);
sNC.ncFlags &= ~NC_InAggFunc;
+11 -5
View File
@@ -1871,8 +1871,8 @@ struct Expr {
*********************************************************************/
Expr *pLeft; /* Left subnode */
Expr *pRight; /* Right subnode */
union {
Expr *pRight; /* Right subnode */
ExprList *pList; /* op = IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */
Select *pSelect; /* EP_xIsSelect and op = IN, EXISTS, SELECT */
} x;
@@ -1882,13 +1882,13 @@ struct Expr {
** access them will result in a segfault or malfunction.
*********************************************************************/
#if SQLITE_MAX_EXPR_DEPTH>0
int nHeight; /* Height of the tree headed by this node */
#endif
int iTable; /* TK_COLUMN: cursor number of table holding column
** TK_REGISTER: register number
** TK_TRIGGER: 1 -> new, 0 -> old
** EP_Unlikely: 1000 times likelihood */
#if SQLITE_MAX_EXPR_DEPTH>0
int nHeight; /* Height of the tree headed by this node */
#endif
ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
** TK_VARIABLE: variable number (always >= 1). */
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
@@ -1914,7 +1914,6 @@ struct Expr {
#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */
#define EP_Generic 0x000200 /* Ignore COLLATE or affinity on this tree */
#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 */
@@ -1923,6 +1922,9 @@ struct Expr {
#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
#define EP_Constant 0x080000 /* Node is a constant */
#define EP_xIsSelect 0x100000 /* Use x.pSelect, not x.pList or x.pRight */
#define EP_xIsList 0x200000 /* Use x.pList, not x.pSelect or x.pRight */
#define EP_xMask 0x300000 /* Combination of xIsSelect and xIsList */
/*
** These macros can be used to test, set, or clear bits in the
@@ -1933,6 +1935,10 @@ struct Expr {
#define ExprSetProperty(E,P) (E)->flags|=(P)
#define ExprClearProperty(E,P) (E)->flags&=~(P)
/* True if the x.pRight field of Expr E is valid */
#define ExprUsesRight(E) (((E)->flags&EP_xMask)==0)
/* The ExprSetVVAProperty() macro is used for Verification, Validation,
** and Accreditation only. It works like ExprSetProperty() during VVA
** processes but is a no-op for delivery.
+4 -2
View File
@@ -45,10 +45,12 @@ int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
if( rc==WRC_Continue
&& !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) ){
if( ExprUsesRight(pExpr) ){
if( sqlite3WalkExpr(pWalker, pExpr->x.pRight) ) return WRC_Abort;
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
}else{
assert( ExprHasProperty(pExpr, EP_xIsList) );
if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
}
}
+52 -31
View File
@@ -260,7 +260,8 @@ static void whereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
whereClauseInsert(pWC, pExpr, 0);
}else{
whereSplit(pWC, pExpr->pLeft, op);
whereSplit(pWC, pExpr->pRight, op);
assert( ExprUsesRight(pExpr) );
whereSplit(pWC, pExpr->x.pRight, op);
}
}
@@ -311,11 +312,13 @@ static Bitmask exprTableUsage(WhereMaskSet *pMaskSet, Expr *p){
mask = getMask(pMaskSet, p->iTable);
return mask;
}
mask = exprTableUsage(pMaskSet, p->pRight);
mask |= exprTableUsage(pMaskSet, p->pLeft);
if( ExprHasProperty(p, EP_xIsSelect) ){
mask = exprTableUsage(pMaskSet, p->pLeft);
if( ExprUsesRight(p) ){
mask |= exprTableUsage(pMaskSet, p->x.pRight);
}else if( ExprHasProperty(p, EP_xIsSelect) ){
mask |= exprSelectTableUsage(pMaskSet, p->x.pSelect);
}else{
assert( ExprHasProperty(p, EP_xIsList) );
mask |= exprListTableUsage(pMaskSet, p->x.pList);
}
return mask;
@@ -382,15 +385,16 @@ static int allowedOp(int op){
** is not commuted.
*/
static void exprCommute(Parse *pParse, Expr *pExpr){
u16 expRight = (pExpr->pRight->flags & EP_Collate);
u16 expRight = (pExpr->x.pRight->flags & EP_Collate);
u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
assert( ExprUsesRight(pExpr) );
assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
if( expRight==expLeft ){
/* Either X and Y both have COLLATE operator or neither do */
if( expRight ){
/* Both X and Y have COLLATE operators. Make sure X is always
** used by clearing the EP_Collate flag from Y. */
pExpr->pRight->flags &= ~EP_Collate;
pExpr->x.pRight->flags &= ~EP_Collate;
}else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
/* Neither X nor Y have COLLATE operators, but X has a non-default
** collating sequence. So add the EP_Collate marker on X to cause
@@ -398,7 +402,7 @@ static void exprCommute(Parse *pParse, Expr *pExpr){
pExpr->pLeft->flags |= EP_Collate;
}
}
SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
SWAP(Expr*,pExpr->x.pRight,pExpr->pLeft);
if( pExpr->op>=TK_GT ){
assert( TK_LT==TK_GT+2 );
assert( TK_GE==TK_LE+2 );
@@ -459,7 +463,8 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
&& pScan->nEquiv<ArraySize(pScan->aEquiv)
){
int j;
pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
assert( ExprUsesRight(pTerm->pExpr) );
pX = sqlite3ExprSkipCollate(pTerm->pExpr->x.pRight);
assert( pX->op==TK_COLUMN );
for(j=0; j<pScan->nEquiv; j+=2){
if( pScan->aEquiv[j]==pX->iTable
@@ -482,16 +487,16 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
continue;
}
assert(pX->pLeft);
pColl = sqlite3BinaryCompareCollSeq(pParse,
pX->pLeft, pX->pRight);
assert( pX->pLeft!=0 );
pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft,
ExprUsesRight(pX) ? pX->x.pRight : 0);
if( pColl==0 ) pColl = pParse->db->pDfltColl;
if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
continue;
}
}
if( (pTerm->eOperator & WO_EQ)!=0
&& (pX = pTerm->pExpr->pRight)->op==TK_COLUMN
&& (pX = pTerm->pExpr->x.pRight)->op==TK_COLUMN
&& pX->iTable==pScan->aEquiv[0]
&& pX->iColumn==pScan->aEquiv[1]
){
@@ -1016,7 +1021,8 @@ static void exprAnalyzeOrTerm(
** of both right and left sides must be such that no type
** conversions are required on the right. (Ticket #2249)
*/
affRight = sqlite3ExprAffinity(pOrTerm->pExpr->pRight);
assert( ExprUsesRight(pOrTerm->pExpr) );
affRight = sqlite3ExprAffinity(pOrTerm->pExpr->x.pRight);
affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft);
if( affRight!=0 && affRight!=affLeft ){
okToChngToIN = 0;
@@ -1042,7 +1048,8 @@ static void exprAnalyzeOrTerm(
assert( pOrTerm->eOperator & WO_EQ );
assert( pOrTerm->leftCursor==iCursor );
assert( pOrTerm->u.leftColumn==iColumn );
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
assert( ExprUsesRight(pOrTerm->pExpr) );
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->x.pRight, 0);
pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
pLeft = pOrTerm->pExpr->pLeft;
}
@@ -1052,7 +1059,7 @@ static void exprAnalyzeOrTerm(
if( pNew ){
int idxNew;
transferJoinMarkings(pNew, pExpr);
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
ExprSetProperty(pNew, EP_xIsList);
pNew->x.pList = pList;
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
@@ -1116,16 +1123,16 @@ static void exprAnalyze(
prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
op = pExpr->op;
if( op==TK_IN ){
assert( pExpr->pRight==0 );
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
pTerm->prereqRight = exprSelectTableUsage(pMaskSet, pExpr->x.pSelect);
}else{
assert( ExprHasProperty(pExpr, EP_xIsList) || pExpr->x.pList==0 );
pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->x.pList);
}
}else if( op==TK_ISNULL ){
pTerm->prereqRight = 0;
}else{
pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight);
}else if( ExprUsesRight(pExpr) ){
pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->x.pRight);
}
prereqAll = exprTableUsage(pMaskSet, pExpr);
if( ExprHasProperty(pExpr, EP_FromJoin) ){
@@ -1140,14 +1147,17 @@ static void exprAnalyze(
pTerm->eOperator = 0;
if( allowedOp(op) ){
Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
Expr *pRight;
u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
if( pLeft->op==TK_COLUMN ){
pTerm->leftCursor = pLeft->iTable;
pTerm->u.leftColumn = pLeft->iColumn;
pTerm->eOperator = operatorMask(op) & opMask;
}
if( pRight && pRight->op==TK_COLUMN ){
if( ExprUsesRight(pExpr)
&& (pRight = sqlite3ExprSkipCollate(pExpr->x.pRight))!=0
&& pRight->op==TK_COLUMN
){
WhereTerm *pNew;
Expr *pDup;
u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */
@@ -1673,7 +1683,8 @@ static void constructAutomaticIndex(
Expr *pX = pTerm->pExpr;
idxCols |= cMask;
pIdx->aiColumn[n] = pTerm->u.leftColumn;
pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
assert( ExprUsesRight(pX) );
pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->x.pRight);
pIdx->azColl[n] = ALWAYS(pColl) ? pColl->zName : "BINARY";
n++;
}
@@ -2103,7 +2114,8 @@ static int whereRangeScanEst(
/* If possible, improve on the iLower estimate using ($P:$L). */
if( pLower ){
int bOk; /* True if value is extracted from pExpr */
Expr *pExpr = pLower->pExpr->pRight;
Expr *pExpr = pLower->pExpr->x.pRight;
assert( ExprUsesRight(pLower->pExpr) );
assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
if( rc==SQLITE_OK && bOk ){
@@ -2118,7 +2130,8 @@ static int whereRangeScanEst(
/* If possible, improve on the iUpper estimate using ($P:$U). */
if( pUpper ){
int bOk; /* True if value is extracted from pExpr */
Expr *pExpr = pUpper->pExpr->pRight;
Expr *pExpr = pUpper->pExpr->x.pRight;
assert( ExprUsesRight(pUpper->pExpr) );
assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
if( rc==SQLITE_OK && bOk ){
@@ -2388,7 +2401,8 @@ static int codeEqualityTerm(
assert( iTarget>0 );
if( pX->op==TK_EQ ){
iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
assert( ExprUsesRight(pX) );
iReg = sqlite3ExprCodeTarget(pParse, pX->x.pRight, iTarget);
}else if( pX->op==TK_ISNULL ){
iReg = iTarget;
sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
@@ -2571,7 +2585,8 @@ static int codeAllEqualityTerms(
testcase( pTerm->eOperator & WO_ISNULL );
testcase( pTerm->eOperator & WO_IN );
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
Expr *pRight = pTerm->pExpr->pRight;
Expr *pRight = pTerm->pExpr->x.pRight;
assert( ExprUsesRight(pTerm->pExpr) );
if( sqlite3ExprCanBeNull(pRight) ){
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
VdbeCoverage(v);
@@ -2848,7 +2863,8 @@ static Bitmask codeOneLoopStart(
codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
addrNotFound = pLevel->addrNxt;
}else{
sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
assert( ExprUsesRight(pTerm->pExpr) );
sqlite3ExprCode(pParse, pTerm->pExpr->x.pRight, iTarget);
}
}
sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg);
@@ -2939,7 +2955,8 @@ static Bitmask codeOneLoopStart(
pX = pStart->pExpr;
assert( pX!=0 );
testcase( pStart->leftCursor!=iCur ); /* transitive constraints */
r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp);
assert( ExprUsesRight(pX) );
r1 = sqlite3ExprCodeTemp(pParse, pX->x.pRight, &rTemp);
sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1);
VdbeComment((v, "pk"));
VdbeCoverageIf(v, pX->op==TK_GT);
@@ -2962,7 +2979,8 @@ static Bitmask codeOneLoopStart(
testcase( pEnd->leftCursor!=iCur ); /* Transitive constraints */
testcase( pEnd->wtFlags & TERM_VIRTUAL );
memEndValue = ++pParse->nMem;
sqlite3ExprCode(pParse, pX->pRight, memEndValue);
assert( ExprUsesRight(pX) );
sqlite3ExprCode(pParse, pX->x.pRight, memEndValue);
if( pX->op==TK_LT || pX->op==TK_GT ){
testOp = bRev ? OP_Le : OP_Ge;
}else{
@@ -3126,7 +3144,8 @@ static Bitmask codeOneLoopStart(
/* Seek the index cursor to the start of the range. */
nConstraint = nEq;
if( pRangeStart ){
Expr *pRight = pRangeStart->pExpr->pRight;
Expr *pRight = pRangeStart->pExpr->x.pRight;
assert( ExprUsesRight(pRangeStart->pExpr) );
sqlite3ExprCode(pParse, pRight, regBase+nEq);
if( (pRangeStart->wtFlags & TERM_VNULL)==0
&& sqlite3ExprCanBeNull(pRight)
@@ -3170,7 +3189,8 @@ static Bitmask codeOneLoopStart(
*/
nConstraint = nEq;
if( pRangeEnd ){
Expr *pRight = pRangeEnd->pExpr->pRight;
Expr *pRight = pRangeEnd->pExpr->x.pRight;
assert( ExprUsesRight(pRangeEnd->pExpr) );
sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
sqlite3ExprCode(pParse, pRight, regBase+nEq);
if( (pRangeEnd->wtFlags & TERM_VNULL)==0
@@ -4229,7 +4249,8 @@ static int whereLoopAddBtreeIndex(
if( (eOp & (WO_EQ|WO_ISNULL))!=0 ){
testcase( eOp & WO_EQ );
testcase( eOp & WO_ISNULL );
rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut);
assert( ExprUsesRight(pExpr) );
rc = whereEqualScanEst(pParse, pBuilder, pExpr->x.pRight, &nOut);
}else{
rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
}