]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Experimental changes that reduce the size of Expr objects from 72 to 64 smaller-expr
authordrh <drh@noemail.net>
Tue, 6 May 2014 15:28:56 +0000 (15:28 +0000)
committerdrh <drh@noemail.net>
Tue, 6 May 2014 15:28:56 +0000 (15:28 +0000)
bytes each on x64 and from 48 to 44 bytes each on x32.

FossilOrigin-Name: 8ad0a123a2046e4bf95b4f9c28f26221afb3fc43

manifest
manifest.uuid
src/attach.c
src/expr.c
src/func.c
src/parse.y
src/resolve.c
src/select.c
src/sqliteInt.h
src/walker.c
src/where.c

index 089fba14e720b71b8e9a5a60265c4a3d6dbe47b7..29b28c7a0b0517de1fd4452c5d2ec35c2e543979 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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
index af81c8bc8271421a2467add7ef97305780d54ea6..c76d32477ca91f54510159fb4378d47211750841 100644 (file)
@@ -1 +1 @@
-c1ab9092e29bc9d172c1f1a3becbcc83b79f2080
\ No newline at end of file
+8ad0a123a2046e4bf95b4f9c28f26221afb3fc43
\ No newline at end of file
index 89050fd9dc1f5eea8f892a386e4d24e667661052..e51c20ee1ec266da7dccc95bab4ebb3d588d0d28 100644 (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;
index 08c121e3862437c9f20297c90a4152c741cbc2e1..c1e30cfd01cb03a65c6e1b790c430b58eab81c6d 100644 (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;
index 6be963580c9450efd2b808e594f870bf0c382021..cc8cb45cb8df3f699d9f726a172a492f3d0baed0 100644 (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);
index dbc129ce6384a44830a803f459b909bfd145240e..16b3a826c1bd4eed295f717c5470d3b333e391ab 100644 (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);
index 86169c51c1e069c01bb211d8808bc1a91fcd6071..dd4f3eb72866cb4b0ff0688de3fba07f0d5d4d78 100644 (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);
index 5fff010f34c01c15fe6c6d750d3e01cce68834a2..33c3cf07d6781b9c84faf439f593495a2463a48b 100644 (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;
index 4bd65a690fbd0f94f75fc4810f0a5ceeef5b6cef..4a0f8ad4e5bd3e916228b2c4200f2000b9c61c89 100644 (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.
index 016ae77a92be39b809ee7b8146b4d52df2725941..d6916e69e797960959ed4b764853601452e2097a 100644 (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;
     }
   }
index c5892590bca680be93e1c6b6a8f39fdd9fa942a6..31a4c418230f9fc709321a7e878a756e5d5c3d05 100644 (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);
           }