]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Reduce the size of Expr from 80 to 72 bytes moving the pRight field inside the
authordrh <drh@noemail.net>
Wed, 19 Sep 2018 14:54:38 +0000 (14:54 +0000)
committerdrh <drh@noemail.net>
Wed, 19 Sep 2018 14:54:38 +0000 (14:54 +0000)
"x" union.  This is an incremental check-in that still has issues.

FossilOrigin-Name: 147c61a6d4b2a17d6c1da3584e3f29f2bc441e81fbea9d19110a9169c38fbd5f

14 files changed:
manifest
manifest.uuid
src/attach.c
src/expr.c
src/parse.y
src/resolve.c
src/select.c
src/sqliteInt.h
src/treeview.c
src/vdbeaux.c
src/walker.c
src/where.c
src/wherecode.c
src/whereexpr.c

index 27f417bc575c65bd244d5fe2575f779788f7369c..d89726185e12614ff88ae100dacd9e6eaad15c1c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Make\ssure\stemporary\sExpr\sobjects\sare\sfully\sinitialized\sprior\sto\ssending\sthem\ninto\ssqlite3ExprCodeTemp().
-D 2018-09-19T11:59:15.245
+C Reduce\sthe\ssize\sof\sExpr\sfrom\s80\sto\s72\sbytes\smoving\sthe\spRight\sfield\sinside\sthe\n"x"\sunion.\s\sThis\sis\san\sincremental\scheck-in\sthat\sstill\shas\sissues.
+D 2018-09-19T14:54:38.166
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334
@@ -438,7 +438,7 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
 F src/alter.c 2269dd2f37ba963fde4c51e9e83542f126c86a8e10357c17f48137c6bee5299b
 F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9
-F src/attach.c 8b8e52590fca04bed868461aadc5d38de7542f005310ced863e032c83e1b1b6a
+F src/attach.c d06bf7ab9efceb7c679ba8beaeeb3082ce3defde482f54de50ac175469f7c4ca
 F src/auth.c 32a5bbe3b755169ab6c66311c5225a3cd4f75a46c041f7fb117e0cbb68055114
 F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
 F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
@@ -454,7 +454,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
 F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3
 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91
 F src/delete.c 07a7ecf18a64478be7241cbb332bc26321586384c750e47fb566f678c5aee512
-F src/expr.c d48bca738efa75f4a8731c55db8425d275e6367163ca0149bed9b6117eab5e32
+F src/expr.c cc72d25fe9c2f3d6e8bdf9d519ab20135a45a8ade37c7712155af5d88693092e
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c f59253c0be4b1e9dfcb073b6d6d6ab83090ae50c08b5c113b76013c4b157cd6a
 F src/func.c 82aeef69505b67197a476836d44cc16c1a434ee53481f23cffb70a75a1bcbc7a
@@ -491,7 +491,7 @@ F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971
 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
 F src/pager.c a0d8f686ef64549ad5b356fd30429bd9ee7a06dd42b4d6faa096352ff26b1c5b
 F src/pager.h ecc554a55bc55d1c4ba5e17137b72e238e00bd81e72ff2662d8b9c8c10ae3963
-F src/parse.y 15eeb0ead639555727ed81fc61bd8e28968e9379bc074ae9cb48b95c79b50f0d
+F src/parse.y cea885dd89f7c2963aee930b93c8ba14a7a9eb2bb31ba146777a7bbbc5b8a121
 F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
 F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
@@ -500,14 +500,14 @@ F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
 F src/prepare.c f8e260d940a0e08494c0f30744521b2f832d7263eca9d02b050cea0ba144b097
 F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381
 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
-F src/resolve.c 301eadb8bf5afcd0b673d4db3c85c179334e19970af276187932e5b0a97b90ec
+F src/resolve.c 1f8444d1155b4711cbe2fc1fcd40ecace3f71faa1cf593472581e17b9b39e6af
 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
-F src/select.c af9efbeea79c7eaa21f51c2640f9f8e21d1c9dbcea236d5af68bb8f0313d9b1e
+F src/select.c f3070ba3c6a591799c62eed45cce83ec458e77f39567debf92e90b022bd2f05a
 F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1f
 F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 305adca1b5da4a33ce2db5bd236935768e951d5651bfe5560ed55cfcdbce6a63
-F src/sqliteInt.h 0aed6451d241a43814ac54d93f7d2b8645826ffa9e35e7289240dd38e967b813
+F src/sqliteInt.h b8a598f500ce81be682730b30b5d0dbdc4c1ec70a8ef640b7893d0edcadb5bdd
 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
 F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -566,7 +566,7 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
 F src/tokenize.c 9f55961518f77793edd56eee860ecf035d4370ebbb0726ad2f6cada6637fd16b
-F src/treeview.c b6f459831c544d697e4b38471b98b972d9dd3b4611d0e8c6338632c7ad926d12
+F src/treeview.c 1bc9fc4ebd661bea19b4f39dd32f34b609faf2250112d83d7ffa40ab1c3b386b
 F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd
 F src/update.c 682f112c49247d2fe5950c9fe2226046c6bc497cf114f74d58766926914216ff
 F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
@@ -577,7 +577,7 @@ F src/vdbe.c 80603eb66708c2f27879912a4e9456900e66491c3409ca5e392109114e8f6337
 F src/vdbe.h 5081dcc497777efe5e9ebe7330d283a044a005e4bdda2e2e984f03bf89a0d907
 F src/vdbeInt.h f1f35f70460698d8f5a2bdef1001114babf318e2983a067804e2ae077d8e9827
 F src/vdbeapi.c 2ba821c5929a2769e4b217dd85843479c718b8989d414723ec8af0616a83d611
-F src/vdbeaux.c c3c397274380f13db702baa3506ba87379446a4d71135a1177b624f73dd3c830
+F src/vdbeaux.c 43ee58196823e17093601388993bbea03456c6ffbbd83d516096af71346d93e3
 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
 F src/vdbemem.c 81329ab760e4ec0162119d9cd10193e0303c45c5935bb20c7ae9139d44dd6641
 F src/vdbesort.c 90aad5a92608f2dd771c96749beabdb562c9d881131a860a7a5bccf66dc3be7f
@@ -586,11 +586,11 @@ F src/vtab.c 8665561f244c137a2d17b5c3e5910d7303054fe841c5d510e53f23beb0089594
 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
 F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f
 F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
-F src/walker.c b2d62136868f1f939a7778bdce8b372bb4e314862cd2b33bd1ec9614eef0b44c
-F src/where.c c90c392c7c8c8ea3e36592dba9800cee35eeadd36c512ab904da8245c334b148
+F src/walker.c 4ba292cadd145b8b77e8b2128a363beff0bd87c7f9abfe090c0948eb0330d727
+F src/where.c 33a546a918b0439e3e174351ca00c9158f26d73c5a8bb54c6c3cf5bae20b7499
 F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4
-F src/wherecode.c 75a3b20d28a5c9f88e6c6dd9037ffeacdd786feaba8013245f7d8576a093dcf4
-F src/whereexpr.c c08b5afce2e7b9046c65f5edc3302888d79e8c541907a97df089c135895b25f0
+F src/wherecode.c 4c3ec236bfeaf2229e5d862e3ff9a2ac22d7cc3ce69c56892d3d25582bece577
+F src/whereexpr.c ba56a077649e8b0f4453eabfe57f3077c85bc6c9b7b3884bf2223c04f57fbca5
 F src/window.c 4b503da928dace3e845b891381a4d98eeb8c5744313ae3643df8d8d21fdcca65
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
@@ -1767,7 +1767,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 8849a463d67d79ec60c74a08835c176c08da651a82731558a1dceac2781cd75d
-R db879ad69540fd8a785f584d64935c70
+P de02a1d97a860f780d9b75cddf008a8b1824cf0483f7891e6ed55b83e2d32d91
+R 48c3dc53a777e2b3895af501d46c8ac1
 U drh
-Z 1294c1f2dad466247d6550207298ec20
+Z 0905558528608b1236ee1840013b25d6
index 56e8b35607c4fef1a118cca07b619fa5d128cf02..18d732395100adbfec7b8a606f510826b3c6930c 100644 (file)
@@ -1 +1 @@
-de02a1d97a860f780d9b75cddf008a8b1824cf0483f7891e6ed55b83e2d32d91
\ No newline at end of file
+147c61a6d4b2a17d6c1da3584e3f29f2bc441e81fbea9d19110a9169c38fbd5f
\ No newline at end of file
index 9d77d83c4758b5a86d04606c3ccaec43e4851818..073d74c8b1c514a480d9de9a27d6dc48cea169b6 100644 (file)
@@ -573,9 +573,10 @@ int sqlite3FixExpr(
         if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
         break;
       }
-    }
-    if( sqlite3FixExpr(pFix, pExpr->pRight) ){
-      return 1;
+      case EX_Right: {
+        if( sqlite3FixExpr(pFix, pExpr->x.pRight) ) return 1;
+        break;
+      }
     }
     pExpr = pExpr->pLeft;
   }
index 82dd06d8e19a6b05f93ceb6bbd71fb0768637198..43f116aab8ecb3bbe30a83a898aaaaddb9717cf2 100644 (file)
@@ -166,7 +166,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
       if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){
         p = p->pLeft;
       }else{
-        Expr *pNext  = p->pRight;
+        Expr *pNext = 0;
         /* p->flags holds EP_Collate and p->pLeft->flags does not.  And
         ** p->x.pSelect cannot.  So if p->x.pLeft exists, it must hold at
         ** least one EP_Collate. Thus the following two ALWAYS. */
@@ -178,6 +178,8 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
               break;
             }
           }
+        }else if( p->eX==EX_Right ){
+          pNext = p->x.pRight;
         }
         p = pNext;
       }
@@ -256,8 +258,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( pExpr->eX==EX_Right ){
+    aff = sqlite3CompareAffinity(pExpr->x.pRight, aff);
   }else if( pExpr->eX==EX_Select ){
     aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
   }else if( aff==0 ){
@@ -305,8 +307,12 @@ static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
 **
 ** Argument pRight (but not pLeft) may be a null pointer. In this case,
 ** it is not considered.
+**
+** The second form (sqlite3BinaryExprCollSeq()) uses the Expr.pLeft
+** and Expr.x.pRight pointer from the second argument instead of separate
+** pointers.
 */
-CollSeq *sqlite3BinaryCompareCollSeq(
+CollSeq *sqlite3ComparisonCollSeq(
   Parse *pParse, 
   Expr *pLeft, 
   Expr *pRight
@@ -325,6 +331,13 @@ CollSeq *sqlite3BinaryCompareCollSeq(
   }
   return pColl;
 }
+CollSeq *sqlite3ComparisonExprCollSeq(Parse *pParse, Expr *pExpr){
+  if( pExpr->eX==EX_Right ){
+    return sqlite3ComparisonCollSeq(pParse, pExpr->pLeft, pExpr->x.pRight);
+  }else{
+    return sqlite3ComparisonCollSeq(pParse, pExpr->pLeft, 0);
+  }
+}
 
 /*
 ** Generate code for a comparison operator.
@@ -342,7 +355,7 @@ static int codeCompare(
   int addr;
   CollSeq *p4;
 
-  p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
+  p4 = sqlite3ComparisonCollSeq(pParse, pLeft, pRight);
   p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
   addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
                            (void*)p4, P4_COLLSEQ);
@@ -545,7 +558,7 @@ static void codeVectorCompare(
 ){
   Vdbe *v = pParse->pVdbe;
   Expr *pLeft = pExpr->pLeft;
-  Expr *pRight = pExpr->pRight;
+  Expr *pRight = pExpr->x.pRight;
   int nLeft = sqlite3ExprVectorSize(pLeft);
   int i;
   int regLeft = 0;
@@ -679,12 +692,20 @@ static void heightOfSelect(Select *pSelect, int *pnHeight){
 static void exprSetHeight(Expr *p){
   int nHeight = 0;
   heightOfExpr(p->pLeft, &nHeight);
-  heightOfExpr(p->pRight, &nHeight);
-  if( p->eX==EX_Select ){
-    heightOfSelect(p->x.pSelect, &nHeight);
-  }else if( p->eX==EX_List ){
-    heightOfExprList(p->x.pList, &nHeight);
-    p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
+  switch( p->eX ){
+    case EX_Select: {
+      heightOfSelect(p->x.pSelect, &nHeight);
+      break;
+    }
+    case EX_List: {
+      heightOfExprList(p->x.pList, &nHeight);
+      p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
+      break;
+    }
+    case EX_Right: {
+      heightOfExpr(p->x.pRight, &nHeight);
+      break;
+    }
   }
   p->nHeight = nHeight + 1;
 }
@@ -823,7 +844,9 @@ void sqlite3ExprAttachSubtrees(
     sqlite3ExprDelete(db, pRight);
   }else{
     if( pRight ){
-      pRoot->pRight = pRight;
+      assert( pRoot->eX==EX_None );
+      pRoot->x.pRight = pRight;
+      pRoot->eX = EX_Right;
       pRoot->flags |= EP_Propagate & pRight->flags;
     }
     if( pLeft ){
@@ -1076,36 +1099,32 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
 #ifdef SQLITE_DEBUG
   if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){
     assert( p->pLeft==0 );
-    assert( p->pRight==0 );
     assert( p->eX==EX_None );
   }
   if( !ExprHasProperty(p, EP_TokenOnly) ){
     assert( p->op!=TK_FUNCTION || p->pLeft==0 );
-    assert( p->pRight==0 || p->x.pSelect==0 );
   }
   if( !ExprHasProperty(p, (EP_TokenOnly|EP_Reduced)) ){
     assert( p->pWin==0 || p->pLeft==0 );
     assert( p->pWin==0 || p->pTab==0 );
     assert( p->pWin==0 || p->op==TK_FUNCTION );
-    assert( p->pTab==0 || (p->pRight==0 && p->eX==EX_None) );
+    assert( p->pTab==0 || p->eX==EX_None );
   }
 #endif
   if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){
-    /* The Expr.x union is never used at the same time as Expr.pRight */
-    assert( p->x.pList==0 || p->pRight==0 );
     if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
-    if( p->pRight ){
-      sqlite3ExprDeleteNN(db, p->pRight);
-    }else{
-      switch( p->eX ){
-        case EX_Select: {
-          sqlite3SelectDelete(db, p->x.pSelect);
-          break;
-        }
-        case EX_List: {
-          sqlite3ExprListDelete(db, p->x.pList);
-          break;
-        }
+    switch( p->eX ){
+      case EX_Select: {
+        sqlite3SelectDelete(db, p->x.pSelect);
+        break;
+      }
+      case EX_List: {
+        sqlite3ExprListDelete(db, p->x.pList);
+        break;
+      }
+      case EX_Right: {
+        sqlite3ExprDelete(db, p->x.pRight);
+        break;
       }
     }
     if( !ExprHasProperty(p, EP_Reduced) ){
@@ -1182,10 +1201,9 @@ static int dupedExprStructSize(Expr *p, int flags){
     assert( !ExprHasProperty(p, EP_FromJoin) ); 
     assert( !ExprHasProperty(p, EP_MemToken) );
     assert( !ExprHasProperty(p, EP_NoReduce) );
-    if( p->pLeft || p->x.pList ){
+    if( p->pLeft || p->eX!=EX_None ){
       nSize = EXPR_REDUCEDSIZE | EP_Reduced;
     }else{
-      assert( p->pRight==0 );
       nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
     }
   }
@@ -1223,7 +1241,8 @@ 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( p->eX==EX_Right ) nByte += dupedExprSize(p->x.pRight, flags);
     }
   }
   return nByte;
@@ -1233,7 +1252,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 past the
 ** portion of the buffer copied into by this function.
 */
@@ -1313,14 +1332,15 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
       }
     }
 
-    /* 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, dupFlags);
       if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){
         pNew->pLeft = p->pLeft ?
                       exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0;
-        pNew->pRight = p->pRight ?
-                       exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0;
+        if( p->eX==EX_Right ){
+          pNew->x.pRight = exprDup(db, p->x.pRight, EXPRDUP_REDUCE, &zAlloc);
+        }
       }
       if( pzBuffer ){
         *pzBuffer = zAlloc;
@@ -1336,12 +1356,14 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
       if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
         if( pNew->op==TK_SELECT_COLUMN ){
           pNew->pLeft = p->pLeft;
-          assert( p->iColumn==0 || p->pRight==0 );
-          assert( p->pRight==0  || p->pRight==p->pLeft );
+          assert( p->iColumn==0 || p->eX!=EX_Right );
+          /* OLD: assert( p->pRight==0  || p->x.pRight==p->pLeft ); */
         }else{
           pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
         }
-        pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
+        if( p->eX==EX_Right ){
+          pNew->x.pRight = sqlite3ExprDup(db, p->x.pRight, 0);
+        }
       }
     }
   }
@@ -1418,8 +1440,8 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
     ){
       assert( pNewExpr->iColumn==0 || i>0 );
       if( pNewExpr->iColumn==0 ){
-        assert( pOldExpr->pLeft==pOldExpr->pRight );
-        pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
+        assert( pOldExpr->pLeft==pOldExpr->x.pRight );
+        pPriorSelectCol = pNewExpr->pLeft = pNewExpr->x.pRight;
       }else{
         assert( i>0 );
         assert( pItem[-1].pExpr!=0 );
@@ -1665,7 +1687,9 @@ ExprList *sqlite3ExprListAppendVector(
      
     /* Store the SELECT statement in pRight so it will be deleted when
     ** sqlite3ExprListDelete() is called */
-    pFirst->pRight = pExpr;
+    assert( pFirst->eX==EX_None );
+    pFirst->x.pRight = pExpr;
+    pFirst->eX = EX_Right;
     pExpr = 0;
 
     /* Remember the size of the LHS in iTable so that we can check that
@@ -2477,7 +2501,7 @@ int sqlite3FindInIndex(
           for(i=0; i<nExpr; i++){
             Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i);
             Expr *pRhs = pEList->a[i].pExpr;
-            CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
+            CollSeq *pReq = sqlite3ComparisonCollSeq(pParse, pLhs, pRhs);
             int j;
   
             assert( pReq!=0 || pRhs->iColumn==XN_ROWID || pParse->nErr );
@@ -2759,7 +2783,7 @@ int sqlite3CodeSubselect(
           assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
           for(i=0; i<nVal; i++){
             Expr *p = sqlite3VectorFieldSubexpr(pLeft, i);
-            pKeyInfo->aColl[i] = sqlite3BinaryCompareCollSeq(
+            pKeyInfo->aColl[i] = sqlite3ComparisonCollSeq(
                 pParse, p, pEList->a[i].pExpr
             );
           }
@@ -3543,8 +3567,9 @@ expr_code_doover:
         codeVectorCompare(pParse, pExpr, target, op, p5);
       }else{
         r1 = sqlite3ExprCodeTemp(pParse, pLeft, &regFree1);
-        r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
-        codeCompare(pParse, pLeft, pExpr->pRight, op,
+        assert( pExpr->eX==EX_Right );
+        r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, &regFree2);
+        codeCompare(pParse, pLeft, pExpr->x.pRight, op,
             r1, r2, inReg, SQLITE_STOREP2 | p5);
         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);
@@ -3581,7 +3606,8 @@ expr_code_doover:
       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( pExpr->eX==EX_Right );
+      r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, &regFree2);
       sqlite3VdbeAddOp3(v, op, r2, r1, target);
       testcase( regFree1==0 );
       testcase( regFree2==0 );
@@ -3625,7 +3651,8 @@ expr_code_doover:
       int bNormal;   /* IS TRUE or IS FALSE */
       r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
       testcase( regFree1==0 );
-      isTrue = sqlite3ExprTruthValue(pExpr->pRight);
+      assert( pExpr->eX==EX_Right );
+      isTrue = sqlite3ExprTruthValue(pExpr->x.pRight);
       bNormal = pExpr->op2==TK_IS;
       testcase( isTrue && bNormal);
       testcase( !isTrue && bNormal);
@@ -4012,7 +4039,8 @@ expr_code_doover:
       for(i=0; i<nExpr-1; i=i+2){
         if( pX ){
           assert( pTest!=0 );
-          opCompare.pRight = aListelem[i].pExpr;
+          opCompare.x.pRight = aListelem[i].pExpr;
+          opCompare.eX = EX_Right;
         }else{
           pTest = aListelem[i].pExpr;
         }
@@ -4325,13 +4353,16 @@ static void exprCodeBetween(
   exprX = *pExpr->pLeft;
   exprAnd.op = TK_AND;
   exprAnd.pLeft = &compLeft;
-  exprAnd.pRight = &compRight;
+  exprAnd.x.pRight = &compRight;
+  exprAnd.eX = EX_Right;
   compLeft.op = TK_GE;
   compLeft.pLeft = &exprX;
-  compLeft.pRight = pExpr->x.pList->a[0].pExpr;
+  compLeft.x.pRight = pExpr->x.pList->a[0].pExpr;
+  compLeft.eX = EX_Right;
   compRight.op = TK_LE;
   compRight.pLeft = &exprX;
-  compRight.pRight = pExpr->x.pList->a[1].pExpr;
+  compRight.x.pRight = pExpr->x.pList->a[1].pExpr;
+  compRight.eX = EX_Right;
   exprToRegister(&exprX, exprCodeVector(pParse, &exprX, &regFree1));
   if( xJump ){
     xJump(pParse, &exprAnd, dest, jumpIfNull);
@@ -4388,14 +4419,16 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
       int d2 = sqlite3VdbeMakeLabel(v);
       testcase( jumpIfNull==0 );
       sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
-      sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
+      assert( pExpr->eX==EX_Right );
+      sqlite3ExprIfTrue(pParse, pExpr->x.pRight, dest, jumpIfNull);
       sqlite3VdbeResolveLabel(v, d2);
       break;
     }
     case TK_OR: {
       testcase( jumpIfNull==0 );
       sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
-      sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
+      assert( pExpr->eX==EX_Right );
+      sqlite3ExprIfTrue(pParse, pExpr->x.pRight, dest, jumpIfNull);
       break;
     }
     case TK_NOT: {
@@ -4408,7 +4441,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
       int isTrue;     /* IS TRUE or IS NOT TRUE */
       testcase( jumpIfNull==0 );
       isNot = pExpr->op2==TK_ISNOT;
-      isTrue = sqlite3ExprTruthValue(pExpr->pRight);
+      assert( pExpr->eX==EX_Right );
+      isTrue = sqlite3ExprTruthValue(pExpr->x.pRight);
       testcase( isTrue && isNot );
       testcase( !isTrue && isNot );
       if( isTrue ^ isNot ){
@@ -4436,8 +4470,9 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
       if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
       testcase( jumpIfNull==0 );
       r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
-      r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
-      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
+      assert( pExpr->eX==EX_Right );
+      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);
@@ -4554,14 +4589,16 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
     case TK_AND: {
       testcase( jumpIfNull==0 );
       sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
-      sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
+      assert( pExpr->eX==EX_Right );
+      sqlite3ExprIfFalse(pParse, pExpr->x.pRight, dest, jumpIfNull);
       break;
     }
     case TK_OR: {
       int d2 = sqlite3VdbeMakeLabel(v);
       testcase( jumpIfNull==0 );
       sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
-      sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
+      assert( pExpr->eX==EX_Right );
+      sqlite3ExprIfFalse(pParse, pExpr->x.pRight, dest, jumpIfNull);
       sqlite3VdbeResolveLabel(v, d2);
       break;
     }
@@ -4575,7 +4612,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
       int isTrue;  /* IS TRUE or IS NOT TRUE */
       testcase( jumpIfNull==0 );
       isNot = pExpr->op2==TK_ISNOT;
-      isTrue = sqlite3ExprTruthValue(pExpr->pRight);
+      assert( pExpr->eX==EX_Right );
+      isTrue = sqlite3ExprTruthValue(pExpr->x.pRight);
       testcase( isTrue && isNot );
       testcase( !isTrue && isNot );
       if( isTrue ^ isNot ){
@@ -4606,8 +4644,9 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
       if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
       testcase( jumpIfNull==0 );
       r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
-      r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
-      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
+      assert( pExpr->eX==EX_Right );
+      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);
@@ -4786,7 +4825,9 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
     if( pA->eX==EX_Select || pA->eX!=pB->eX ) return 2;
     if( (combinedFlags & EP_FixedCol)==0
      && sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
-    if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2;
+    if( pA->eX==EX_Right ){
+      if( sqlite3ExprCompare(pParse,pA->x.pRight,pB->x.pRight,iTab) ) return 2;
+    }
     if( pA->eX==EX_List ){
       if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
     }
@@ -4884,9 +4925,10 @@ int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){
   if( sqlite3ExprCompare(pParse, pE1, pE2, iTab)==0 ){
     return 1;
   }
+  assert( pE2->op!=TK_OR || pE2->eX==EX_Right );
   if( pE2->op==TK_OR
    && (sqlite3ExprImpliesExpr(pParse, pE1, pE2->pLeft, iTab)
-             || sqlite3ExprImpliesExpr(pParse, pE1, pE2->pRight, iTab) )
+             || sqlite3ExprImpliesExpr(pParse, pE1, pE2->x.pRight, iTab) )
   ){
     return 1;
   }
@@ -4954,8 +4996,9 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
       testcase( pExpr->op==TK_LE );
       testcase( pExpr->op==TK_GT );
       testcase( pExpr->op==TK_GE );
+      assert( pExpr->eX==EX_Right );
       if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab))
-       || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab))
+       || (pExpr->x.pRight->op==TK_COLUMN && IsVirtual(pExpr->x.pRight->pTab))
       ){
        return WRC_Prune;
       }
index aaa2f91787137d131ba6b92d5428c648630b47a4..c489c7e393126e8c12ded1b23b35426d73254316 100644 (file)
@@ -939,7 +939,7 @@ idlist(A) ::= nm(Y).
       p->eX = EX_None;
       p->flags = EP_Leaf;
       p->iAgg = -1;
-      p->pLeft = p->pRight = 0;
+      p->pLeft = 0;
       p->pAggInfo = 0;
       p->pTab = 0;
       p->op2 = 0;
@@ -1100,10 +1100,11 @@ expr(A) ::= expr(A) NOT NULL.    {A = sqlite3PExpr(pParse,TK_NOTNULL,A,0);}
   ** unary TK_ISNULL or TK_NOTNULL expression. */
   static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){
     sqlite3 *db = pParse->db;
-    if( pA && pY && pY->op==TK_NULL && !IN_RENAME_OBJECT ){
+    if( pA && pY && pY->op==TK_NULL && pA->eX==EX_Right && !IN_RENAME_OBJECT ){
       pA->op = (u8)op;
-      sqlite3ExprDelete(db, pA->pRight);
-      pA->pRight = 0;
+      sqlite3ExprDelete(db, pA->x.pRight);
+      pA->x.pRight = 0;
+      pA->eX = EX_None;
     }
   }
 }
index 6b2111af298ea3fdd9a165d43cbb333b2ab44c69..53bd8165a8201ec15f3d5301cce80bf5947cce0f 100644 (file)
@@ -164,7 +164,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
@@ -429,7 +429,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 );
           assert( pExpr->eX==EX_None );
           pOrig = pEList->a[j].pExpr;
           if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){
@@ -521,8 +521,11 @@ static int lookupName(
   */
   sqlite3ExprDelete(db, pExpr->pLeft);
   pExpr->pLeft = 0;
-  sqlite3ExprDelete(db, pExpr->pRight);
-  pExpr->pRight = 0;
+  if( pExpr->eX==EX_Right ){
+    sqlite3ExprDelete(db, pExpr->x.pRight);
+    pExpr->x.pRight = 0;
+    pExpr->eX = EX_None;
+  }
   pExpr->op = eNewExprOp;
   ExprSetProperty(pExpr, EP_Leaf);
 lookupname_end:
@@ -676,14 +679,16 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
       }else{
         Expr *pLeft = pExpr->pLeft;
         notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
-        pRight = pExpr->pRight;
+        assert( pExpr->eX==EX_Right );
+        pRight = pExpr->x.pRight;
         if( pRight->op==TK_ID ){
           zDb = 0;
         }else{
           assert( pRight->op==TK_DOT );
+          assert( pRight->eX==EX_Right );
           zDb = pLeft->u.zToken;
           pLeft = pRight->pLeft;
-          pRight = pRight->pRight;
+          pRight = pRight->x.pRight;
         }
         zTable = pLeft->u.zToken;
         zColumn = pRight->u.zToken;
@@ -904,7 +909,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
       assert( !ExprHasProperty(pExpr, EP_Reduced) );
       /* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE",
       ** and "x IS NOT FALSE". */
-      if( (pRight = pExpr->pRight)->op==TK_ID ){
+      assert( pExpr->eX==EX_Right );
+      if( (pRight = pExpr->x.pRight)->op==TK_ID ){
         int rc = resolveExprStep(pWalker, pRight);
         if( rc==WRC_Abort ) return WRC_Abort;
         if( pRight->op==TK_TRUEFALSE ){
@@ -932,8 +938,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
           nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr);
         }
       }else{
-        assert( pExpr->pRight!=0 );
-        nRight = sqlite3ExprVectorSize(pExpr->pRight);
+        assert( pExpr->eX==EX_Right );
+        nRight = sqlite3ExprVectorSize(pExpr->x.pRight);
       }
       if( nLeft!=nRight ){
         testcase( pExpr->op==TK_EQ );
index 17ba72c76de38ea7320ded53db7d80c373838006..864e5a6e7c454e41969e368640e0e72f101b0b97 100644 (file)
@@ -390,14 +390,14 @@ static void setJoinExpr(Expr *p, int iTable){
     assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
     ExprSetVVAProperty(p, EP_NoReduce);
     p->iRightJoinTable = (i16)iTable;
-    if( p->op==TK_FUNCTION && p->x.pList ){
+    if( p->op==TK_FUNCTION && p->eX==EX_List ){
       int i;
       for(i=0; i<p->x.pList->nExpr; i++){
         setJoinExpr(p->x.pList->a[i].pExpr, iTable);
       }
     }
     setJoinExpr(p->pLeft, iTable);
-    p = p->pRight;
+    p = p->eX==EX_Right ? p->x.pRight : 0;
   } 
 }
 
@@ -413,14 +413,14 @@ static void unsetJoinExpr(Expr *p, int iTable){
      && (iTable<0 || p->iRightJoinTable==iTable) ){
       ExprClearProperty(p, EP_FromJoin);
     }
-    if( p->op==TK_FUNCTION && p->x.pList ){
+    if( p->op==TK_FUNCTION && p->eX==EX_List ){
       int i;
       for(i=0; i<p->x.pList->nExpr; i++){
         unsetJoinExpr(p->x.pList->a[i].pExpr, iTable);
       }
     }
     unsetJoinExpr(p->pLeft, iTable);
-    p = p->pRight;
+    p = p->eX==EX_Right ? p->x.pRight : 0;
   } 
 }
 
@@ -1957,7 +1957,8 @@ int sqlite3ColumnsFromExprList(
     }else{
       Expr *pColExpr = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
       while( pColExpr->op==TK_DOT ){
-        pColExpr = pColExpr->pRight;
+        assert( pColExpr->eX==EX_Right );
+        pColExpr = pColExpr->x.pRight;
         assert( pColExpr!=0 );
       }
       assert( pColExpr->op!=TK_AGG_COLUMN );
@@ -2125,7 +2126,7 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
 
 /*
 ** Compute the iLimit and iOffset fields of the SELECT based on the
-** pLimit expressions.  pLimit->pLeft and pLimit->pRight hold the expressions
+** pLimit expressions.  pLimit->pLeft and pLimit->x,pRight hold the expressions
 ** that appear in the original SQL statement after the LIMIT and OFFSET
 ** keywords.  Or NULL if those keywords are omitted. iLimit and iOffset 
 ** are the integer memory register numbers for counters used to compute 
@@ -2133,7 +2134,7 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
 ** iLimit and iOffset are negative.
 **
 ** This routine changes the values of iLimit and iOffset only if
-** a limit or offset is defined by pLimit->pLeft and pLimit->pRight.  iLimit
+** a limit or offset is defined by pLimit->pLeft and pLimit->x.pRight.  iLimit
 ** and iOffset should have been preset to appropriate default values (zero)
 ** prior to calling this routine.
 **
@@ -2182,10 +2183,10 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
       VdbeComment((v, "LIMIT counter"));
       sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v);
     }
-    if( pLimit->pRight ){
+    if( pLimit->eX==EX_Right ){
       p->iOffset = iOffset = ++pParse->nMem;
       pParse->nMem++;   /* Allocate an extra register for limit+offset */
-      sqlite3ExprCode(pParse, pLimit->pRight, iOffset);
+      sqlite3ExprCode(pParse, pLimit->x.pRight, iOffset);
       sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v);
       VdbeComment((v, "OFFSET counter"));
       sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset);
@@ -3442,7 +3443,7 @@ static Expr *substExpr(
       Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
       Expr ifNullRow;
       assert( pSubst->pEList!=0 && pExpr->iColumn<pSubst->pEList->nExpr );
-      assert( pExpr->pRight==0 );
+      assert( pExpr->eX!=EX_Right );
       if( sqlite3ExprIsVector(pCopy) ){
         sqlite3VectorErrorMsg(pSubst->pParse, pCopy);
       }else{
@@ -3471,7 +3472,6 @@ static Expr *substExpr(
       pExpr->iTable = pSubst->iNewTable;
     }
     pExpr->pLeft = substExpr(pSubst, pExpr->pLeft);
-    pExpr->pRight = substExpr(pSubst, pExpr->pRight);
     switch( pExpr->eX ){
       case EX_Select: {
         substSelect(pSubst, pExpr->x.pSelect, 1);
@@ -3481,6 +3481,10 @@ static Expr *substExpr(
         substExprList(pSubst, pExpr->x.pList);
         break;
       }
+      case EX_Right: {
+        pExpr->x.pRight = substExpr(pSubst, pExpr->x.pRight);
+        break;
+      }
     }
   }
   return pExpr;
@@ -3720,7 +3724,9 @@ static int flattenSubquery(
   ** became arbitrary expressions, we were forced to add restrictions (13)
   ** and (14). */
   if( pSub->pLimit && p->pLimit ) return 0;              /* Restriction (13) */
-  if( pSub->pLimit && pSub->pLimit->pRight ) return 0;   /* Restriction (14) */
+  if( pSub->pLimit && pSub->pLimit->eX==EX_Right ){
+    return 0;                                            /* Restriction (14) */
+  }
   if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){
     return 0;                                            /* Restriction (15) */
   }
@@ -4115,26 +4121,28 @@ static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
   if( pExpr==0 ) return;
   if( ExprHasProperty(pExpr, EP_FromJoin) ) return;
   if( pExpr->op==TK_AND ){
-    findConstInWhere(pConst, pExpr->pRight);
+    assert( pExpr->eX==EX_Right );
+    findConstInWhere(pConst, pExpr->x.pRight);
     findConstInWhere(pConst, pExpr->pLeft);
     return;
   }
   if( pExpr->op!=TK_EQ ) return;
-  pRight = pExpr->pRight;
+  assert( pExpr->eX==EX_Right );
+  pRight = pExpr->x.pRight;
   pLeft = pExpr->pLeft;
   assert( pRight!=0 );
   assert( pLeft!=0 );
   if( pRight->op==TK_COLUMN
    && !ExprHasProperty(pRight, EP_FixedCol)
    && sqlite3ExprIsConstant(pLeft)
-   && sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
+   && sqlite3IsBinary(sqlite3ComparisonCollSeq(pConst->pParse,pLeft,pRight))
   ){
     constInsert(pConst, pRight, pLeft);
   }else
   if( pLeft->op==TK_COLUMN
    && !ExprHasProperty(pLeft, EP_FixedCol)
    && sqlite3ExprIsConstant(pRight)
-   && sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
+   && sqlite3IsBinary(sqlite3ComparisonCollSeq(pConst->pParse,pLeft,pRight))
   ){
     constInsert(pConst, pLeft, pRight);
   }
@@ -4321,7 +4329,8 @@ static int pushDownWhereTerms(
     return 0; /* restriction (3) */
   }
   while( pWhere->op==TK_AND ){
-    nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight,
+    assert( pWhere->eX==EX_Right );
+    nChng += pushDownWhereTerms(pParse, pSubq, pWhere->x.pRight,
                                 iCursor, isLeftJoin);
     pWhere = pWhere->pLeft;
   }
@@ -4907,9 +4916,9 @@ static int selectExpander(Walker *pWalker, Select *p){
   for(k=0; k<pEList->nExpr; k++){
     pE = pEList->a[k].pExpr;
     if( pE->op==TK_ASTERISK ) break;
-    assert( pE->op!=TK_DOT || pE->pRight!=0 );
+    assert( pE->op!=TK_DOT || pE->eX==EX_Right );
     assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
-    if( pE->op==TK_DOT && pE->pRight->op==TK_ASTERISK ) break;
+    if( pE->op==TK_DOT && pE->x.pRight->op==TK_ASTERISK ) break;
     elistFlags |= pE->flags;
   }
   if( k<pEList->nExpr ){
@@ -4927,7 +4936,7 @@ static int selectExpander(Walker *pWalker, Select *p){
     for(k=0; k<pEList->nExpr; k++){
       pE = a[k].pExpr;
       elistFlags |= pE->flags;
-      pRight = pE->pRight;
+      pRight = pE->eX==EX_Right ? pE->x.pRight : 0;
       assert( pE->op!=TK_DOT || pRight!=0 );
       if( pE->op!=TK_ASTERISK
        && (pE->op!=TK_DOT || pRight->op!=TK_ASTERISK)
index 5779f4d3c3871da74a105d7bf3a261675419d23d..0efbecf8445a55076605f6a2abe285420525962f 100644 (file)
@@ -2433,8 +2433,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;
@@ -4402,7 +4402,8 @@ int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
 void sqlite3ParserReset(Parse*);
 int sqlite3Reprepare(Vdbe*);
 void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
-CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
+CollSeq *sqlite3ComparisonCollSeq(Parse*,Expr*,Expr*);
+CollSeq *sqlite3ComparisonExprCollSeq(Parse*,Expr*);
 int sqlite3TempInMemory(const sqlite3*);
 const char *sqlite3JournalModename(int);
 #ifndef SQLITE_OMIT_WAL
index 713fc13b5b718008cc9858047b738963a84e89c0..44fc5b595c4021b0006befafd6288d831e490b14 100644 (file)
@@ -238,10 +238,10 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
     }
     if( p->pLimit ){
       sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
-      sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
-      if( p->pLimit->pRight ){
+      sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->eX==EX_Right);
+      if( p->pLimit->eX==EX_Right ){
         sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
-        sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
+        sqlite3TreeViewExpr(pView, p->pLimit->x.pRight, 0);
         sqlite3TreeViewPop(pView);
       }
       sqlite3TreeViewPop(pView);
@@ -468,9 +468,9 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
          "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE"
       };
       assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT );
-      assert( pExpr->pRight );
-      assert( pExpr->pRight->op==TK_TRUEFALSE );
-      x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);
+      assert( pExpr->eX==EX_Right );
+      assert( pExpr->x.pRight->op==TK_TRUEFALSE );
+      x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->x.pRight);
       zUniOp = azOp[x];
       break;
     }
@@ -601,7 +601,8 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
     case TK_MATCH: {
       sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s",
                           pExpr->iTable, pExpr->iColumn, zFlgs);
-      sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
+      assert( pExpr->eX==EX_Right );
+      sqlite3TreeViewExpr(pView, pExpr->x.pRight, 0);
       break;
     }
     case TK_VECTOR: {
@@ -626,7 +627,8 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
   if( zBinOp ){
     sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs);
     sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
-    sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
+    assert( pExpr->eX==EX_Right );
+    sqlite3TreeViewExpr(pView, pExpr->x.pRight, 0);
   }else if( zUniOp ){
     sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);
     sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
index 5ec3d131e0a635818d2ffb87f64701ee0edfe2ce..aca5692e49f205929b77f612cd0810c344c3d877 100644 (file)
@@ -1375,9 +1375,9 @@ static void displayP4Expr(StrAccum *p, Expr *pExpr){
   if( zOp ){
     sqlite3_str_appendf(p, "%s(", zOp);
     displayP4Expr(p, pExpr->pLeft);
-    if( pExpr->pRight ){
+    if( pExpr->eX==EX_Right ){
       sqlite3_str_append(p, ",", 1);
-      displayP4Expr(p, pExpr->pRight);
+      displayP4Expr(p, pExpr->x.pRight);
     }
     sqlite3_str_append(p, ")", 1);
   }
index 4c6701f1c7377751b4ddf80ef7595b884be43d66..f6c773b69dc8b8ab4a2b668c15ca208074c74807 100644 (file)
@@ -45,20 +45,18 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
     if( rc ) return rc & WRC_Abort;
     if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
       if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
-       assert( pExpr->x.pList==0 || pExpr->pRight==0 );
-      if( pExpr->pRight ){
-        pExpr = pExpr->pRight;
-        continue;
-      }else{
-        switch( pExpr->eX ){
-          case EX_Select: {
-            if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
-            break;
-          }
-          case EX_List: {
-            if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
-            break;
-          }
+      switch( pExpr->eX ){
+        case EX_Right: {
+          pExpr = pExpr->x.pRight;
+          continue;
+        }
+        case EX_Select: {
+          if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
+          break;
+        }
+        case EX_List: {
+          if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
+          break;
         }
       }
 #ifndef SQLITE_OMIT_WINDOWFUNC
index 2a195f8affabf86fcfc04d0238195df899213b61..ef78e5dec65001b7cb5d28da369d25cafd1cea37 100644 (file)
@@ -253,7 +253,9 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
         ){
           if( (pTerm->eOperator & WO_EQUIV)!=0
            && pScan->nEquiv<ArraySize(pScan->aiCur)
-           && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN
+           && ALWAYS(pTerm->pExpr->eX==EX_Right)
+           && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->x.pRight))->op
+                       ==TK_COLUMN
           ){
             int j;
             for(j=0; j<pScan->nEquiv; j++){
@@ -278,15 +280,15 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
                 continue;
               }
               assert(pX->pLeft);
-              pColl = sqlite3BinaryCompareCollSeq(pParse,
-                                                  pX->pLeft, pX->pRight);
+              pColl = sqlite3ComparisonExprCollSeq(pParse, pX);
               if( pColl==0 ) pColl = pParse->db->pDfltColl;
               if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
                 continue;
               }
             }
             if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0
-             && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN
+             && ALWAYS(pTerm->pExpr->eX==EX_Right)
+             && (pX = pTerm->pExpr->x.pRight)->op==TK_COLUMN
              && pX->iTable==pScan->aiCur[0]
              && pX->iColumn==pScan->aiColumn[0]
             ){
@@ -789,7 +791,7 @@ static void constructAutomaticIndex(
         Expr *pX = pTerm->pExpr;
         idxCols |= cMask;
         pIdx->aiColumn[n] = pTerm->u.leftColumn;
-        pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
+        pColl = sqlite3ComparisonExprCollSeq(pParse, pX);
         pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
         n++;
       }
@@ -1006,7 +1008,8 @@ static sqlite3_index_info *allocateIndexInfo(
       assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
 
       if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
-       && sqlite3ExprIsVector(pTerm->pExpr->pRight) 
+       && ALWAYS(pTerm->pExpr->eX==EX_Right)
+       && sqlite3ExprIsVector(pTerm->pExpr->x.pRight) 
       ){
         if( i<16 ) mNoOmit |= (1 << i);
         if( op==WO_LT ) pIdxCons[j].op = WO_LE;
@@ -1366,11 +1369,13 @@ static int whereRangeSkipScanEst(
 
   pColl = sqlite3LocateCollSeq(pParse, p->azColl[nEq]);
   if( pLower ){
-    rc = sqlite3Stat4ValueFromExpr(pParse, pLower->pExpr->pRight, aff, &p1);
+    assert( pLower->pExpr->eX==EX_Right );
+    rc = sqlite3Stat4ValueFromExpr(pParse, pLower->pExpr->x.pRight, aff, &p1);
     nLower = 0;
   }
   if( pUpper && rc==SQLITE_OK ){
-    rc = sqlite3Stat4ValueFromExpr(pParse, pUpper->pExpr->pRight, aff, &p2);
+    assert( pUpper->pExpr->eX==EX_Right );
+    rc = sqlite3Stat4ValueFromExpr(pParse, pUpper->pExpr->x.pRight, aff, &p2);
     nUpper = p2 ? 0 : p->nSample;
   }
 
@@ -1532,7 +1537,9 @@ static int whereRangeScanEst(
       /* If possible, improve on the iLower estimate using ($P:$L). */
       if( pLower ){
         int n;                    /* Values extracted from pExpr */
-        Expr *pExpr = pLower->pExpr->pRight;
+        Expr *pExpr;
+        assert( pLower->pExpr->eX==EX_Right );
+        pExpr = pLower->pExpr->x.pRight;
         rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nBtm, nEq, &n);
         if( rc==SQLITE_OK && n ){
           tRowcnt iNew;
@@ -1549,7 +1556,9 @@ static int whereRangeScanEst(
       /* If possible, improve on the iUpper estimate using ($P:$U). */
       if( pUpper ){
         int n;                    /* Values extracted from pExpr */
-        Expr *pExpr = pUpper->pExpr->pRight;
+        Expr *pExpr;
+        assert( pUpper->pExpr->eX==EX_Right );
+        pExpr = pUpper->pExpr->x.pRight;
         rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nTop, nEq, &n);
         if( rc==SQLITE_OK && n ){
           tRowcnt iNew;
@@ -2279,7 +2288,9 @@ static void whereLoopOutputAdjust(
         ** guess a reasonable truth probability. */
         pLoop->nOut--;
         if( pTerm->eOperator&(WO_EQ|WO_IS) ){
-          Expr *pRight = pTerm->pExpr->pRight;
+          Expr *pRight;
+          assert( pTerm->pExpr->eX==EX_Right );
+          pRight = pTerm->pExpr->x.pRight;
           testcase( pTerm->pExpr->op==TK_IS );
           if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){
             k = 10;
@@ -2328,8 +2339,11 @@ static int whereRangeVectorLen(
     char aff;                     /* Comparison affinity */
     char idxaff = 0;              /* Indexed columns affinity */
     CollSeq *pColl;               /* Comparison collation sequence */
-    Expr *pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr;
-    Expr *pRhs = pTerm->pExpr->pRight;
+    Expr *pLhs;
+    Expr *pRhs;
+    pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr;
+    assert( pTerm->pExpr->eX==EX_Right );
+    pRhs = pTerm->pExpr->x.pRight;
     assert( pRhs->eX==EX_Select || pRhs->eX==EX_List );
     if( pRhs->eX==EX_Select ){
       pRhs = pRhs->x.pSelect->pEList->a[i].pExpr;
@@ -2354,7 +2368,7 @@ static int whereRangeVectorLen(
     idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn);
     if( aff!=idxaff ) break;
 
-    pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
+    pColl = sqlite3ComparisonCollSeq(pParse, pLhs, pRhs);
     if( pColl==0 ) break;
     if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break;
   }
@@ -2630,12 +2644,13 @@ static int whereLoopAddBtreeIndex(
          && OptimizationEnabled(db, SQLITE_Stat34)
         ){
           Expr *pExpr = pTerm->pExpr;
-          if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){
+          if( (eOp & (WO_EQ|WO_IS))!=0 ){
             testcase( eOp & WO_EQ );
             testcase( eOp & WO_IS );
             testcase( eOp & WO_ISNULL );
-            rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut);
-          }else{
+            assert( pExpr->eX==EX_Right );
+            rc = whereEqualScanEst(pParse, pBuilder, pExpr->x.pRight, &nOut);
+          }else if( pExpr->eX==EX_List ){
             rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
           }
           if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
@@ -2789,7 +2804,8 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
   Parse *pParse = pWC->pWInfo->pParse;
   while( pWhere->op==TK_AND ){
     if( !whereUsablePartialIndex(iTab,pWC,pWhere->pLeft) ) return 0;
-    pWhere = pWhere->pRight;
+    assert( pWhere->eX==EX_Right );
+    pWhere = pWhere->x.pRight;
   }
   if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
   for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
@@ -3244,7 +3260,7 @@ const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int iCons){
     int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset;
     Expr *pX = pHidden->pWC->a[iTerm].pExpr;
     if( pX->pLeft ){
-      pC = sqlite3BinaryCompareCollSeq(pHidden->pParse, pX->pLeft, pX->pRight);
+      pC = sqlite3ComparisonExprCollSeq(pHidden->pParse,pX);
     }
     zRet = (pC ? pC->zName : sqlite3StrBINARY);
   }
index 84174ea5957ec838cf94ffa55d68188f1959f68d..f0f1287b083f07431e8d3baf632bb7badcb40e13 100644 (file)
@@ -504,7 +504,8 @@ static int codeEqualityTerm(
   assert( pLevel->pWLoop->aLTerm[iEq]==pTerm );
   assert( iTarget>0 );
   if( pX->op==TK_EQ || pX->op==TK_IS ){
-    iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
+    assert( pX->eX==EX_Right );
+    iReg = sqlite3ExprCodeTarget(pParse, pX->x.pRight, iTarget);
   }else if( pX->op==TK_ISNULL ){
     iReg = iTarget;
     sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
@@ -744,7 +745,9 @@ static int codeAllEqualityTerms(
         if( zAff ) zAff[j] = SQLITE_AFF_BLOB;
       }
     }else if( (pTerm->eOperator & WO_ISNULL)==0 ){
-      Expr *pRight = pTerm->pExpr->pRight;
+      Expr *pRight;
+      assert( pTerm->pExpr->eX==EX_Right );
+      pRight = pTerm->pExpr->x.pRight;
       if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){
         sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
         VdbeCoverage(v);
@@ -1263,8 +1266,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
       if( pTerm->eOperator & WO_IN ){
         codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
         addrNotFound = pLevel->addrNxt;
-      }else{
-        Expr *pRight = pTerm->pExpr->pRight;
+      }else if( pTerm->pExpr->eX==EX_Right ){
+        Expr *pRight;
+        pRight = pTerm->pExpr->x.pRight;
         codeExprOrVector(pParse, pRight, iTarget, 1);
       }
     }
@@ -1309,8 +1313,11 @@ Bitmask sqlite3WhereCodeOneLoopStart(
         assert( pCompare!=0 || db->mallocFailed );
         if( pCompare ){
           pCompare->pLeft = pTerm->pExpr->pLeft;
-          pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0);
+          assert( pCompare->eX==EX_None );
+          pRight = sqlite3Expr(db, TK_REGISTER, 0);
           if( pRight ){
+            pCompare->x.pRight = pRight;
+            pCompare->eX = EX_Right;
             pRight->iTable = iReg+j+2;
             sqlite3ExprIfFalse(pParse, pCompare, pLevel->addrCont, 0);
           }
@@ -1395,9 +1402,10 @@ Bitmask sqlite3WhereCodeOneLoopStart(
       pX = pStart->pExpr;
       assert( pX!=0 );
       testcase( pStart->leftCursor!=iCur ); /* transitive constraints */
-      if( sqlite3ExprIsVector(pX->pRight) ){
+      assert( pX->eX==EX_Right );
+      if( sqlite3ExprIsVector(pX->x.pRight) ){
         r1 = rTemp = sqlite3GetTempReg(pParse);
-        codeExprOrVector(pParse, pX->pRight, r1, 1);
+        codeExprOrVector(pParse, pX->x.pRight, r1, 1);
         testcase( pX->op==TK_GT );
         testcase( pX->op==TK_GE );
         testcase( pX->op==TK_LT );
@@ -1408,7 +1416,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
         assert( pX->op!=TK_LT || op==OP_SeekLE );
         assert( pX->op!=TK_LE || op==OP_SeekLE );
       }else{
-        r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp);
+        r1 = sqlite3ExprCodeTemp(pParse, pX->x.pRight, &rTemp);
         disableTerm(pLevel, pStart);
         op = aMoveOp[(pX->op - TK_GT)];
       }
@@ -1428,19 +1436,20 @@ Bitmask sqlite3WhereCodeOneLoopStart(
       Expr *pX;
       pX = pEnd->pExpr;
       assert( pX!=0 );
+      assert( pX->eX==EX_Right );
       assert( (pEnd->wtFlags & TERM_VNULL)==0 );
       testcase( pEnd->leftCursor!=iCur ); /* Transitive constraints */
       testcase( pEnd->wtFlags & TERM_VIRTUAL );
       memEndValue = ++pParse->nMem;
-      codeExprOrVector(pParse, pX->pRight, memEndValue, 1);
-      if( 0==sqlite3ExprIsVector(pX->pRight) 
+      codeExprOrVector(pParse, pX->x.pRight, memEndValue, 1);
+      if( 0==sqlite3ExprIsVector(pX->x.pRight) 
        && (pX->op==TK_LT || pX->op==TK_GT) 
       ){
         testOp = bRev ? OP_Le : OP_Ge;
       }else{
         testOp = bRev ? OP_Lt : OP_Gt;
       }
-      if( 0==sqlite3ExprIsVector(pX->pRight) ){
+      if( 0==sqlite3ExprIsVector(pX->x.pRight) ){
         disableTerm(pLevel, pEnd);
       }
     }
@@ -1624,7 +1633,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
     /* Seek the index cursor to the start of the range. */
     nConstraint = nEq;
     if( pRangeStart ){
-      Expr *pRight = pRangeStart->pExpr->pRight;
+      Expr *pRight;
+      assert( pRangeStart->pExpr->eX==EX_Right );
+      pRight = pRangeStart->pExpr->x.pRight;
       codeExprOrVector(pParse, pRight, regBase+nEq, nBtm);
       whereLikeOptimizationStringFixup(v, pLevel, pRangeStart);
       if( (pRangeStart->wtFlags & TERM_VNULL)==0
@@ -1676,7 +1687,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
     */
     nConstraint = nEq;
     if( pRangeEnd ){
-      Expr *pRight = pRangeEnd->pExpr->pRight;
+      Expr *pRight;
+      assert( pRangeEnd->pExpr->eX==EX_Right );
+      pRight = pRangeEnd->pExpr->x.pRight;
       codeExprOrVector(pParse, pRight, regBase+nEq, nTop);
       whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd);
       if( (pRangeEnd->wtFlags & TERM_VNULL)==0
index 16d441c52bbe9fcc4db7ffd8ed1e36bec0ab3530..b609521f7d2bafdcd53f3e0b1ebbdf45edf9b62d 100644 (file)
@@ -119,15 +119,17 @@ static int allowedOp(int op){
 ** is not commuted.
 */
 static void exprCommute(Parse *pParse, Expr *pExpr){
-  u16 expRight = (pExpr->pRight->flags & EP_Collate);
-  u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
+  u16 expRight, expLeft;
+  assert( pExpr->eX==EX_Right );
+  expRight = (pExpr->x.pRight->flags & EP_Collate);
+  expLeft = (pExpr->pLeft->flags & EP_Collate);
   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
@@ -135,7 +137,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 );
@@ -426,7 +428,7 @@ static int isAuxiliaryVtabOperator(
   }else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
     int res = 0;
     Expr *pLeft = pExpr->pLeft;
-    Expr *pRight = pExpr->pRight;
+    Expr *pRight = pExpr->x.pRight;
     if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){
       res++;
     }
@@ -516,10 +518,14 @@ static void whereCombineDisjuncts(
   if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
   if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
    && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return;
-  assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 );
-  assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 );
-  if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return;
-  if( sqlite3ExprCompare(0,pOne->pExpr->pRight, pTwo->pExpr->pRight,-1) )return;
+  assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->eX==EX_Right );
+  assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->eX==EX_Right );
+  if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ){
+    return;
+  }
+  if( sqlite3ExprCompare(0,pOne->pExpr->x.pRight, pTwo->pExpr->x.pRight,-1) ){
+    return;
+  }
   /* If we reach this point, it means the two subterms can be combined */
   if( (eOp & (eOp-1))!=0 ){
     if( eOp & (WO_LT|WO_LE) ){
@@ -827,7 +833,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( pOrTerm->pExpr->eX==EX_Right );
+          affRight = sqlite3ExprAffinity(pOrTerm->pExpr->x.pRight);
           affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft);
           if( affRight!=0 && affRight!=affLeft ){
             okToChngToIN = 0;
@@ -853,7 +860,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( pOrTerm->pExpr->eX==EX_Right );
+        pDup = sqlite3ExprDup(db, pOrTerm->pExpr->x.pRight, 0);
         pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
         pLeft = pOrTerm->pExpr->pLeft;
       }
@@ -902,15 +910,16 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr){
   if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
   if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0;
   aff1 = sqlite3ExprAffinity(pExpr->pLeft);
-  aff2 = sqlite3ExprAffinity(pExpr->pRight);
+  assert( pExpr->eX==EX_Right );
+  aff2 = sqlite3ExprAffinity(pExpr->x.pRight);
   if( aff1!=aff2
    && (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2))
   ){
     return 0;
   }
-  pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
+  pColl = sqlite3ComparisonExprCollSeq(pParse, pExpr);
   if( sqlite3IsBinary(pColl) ) return 1;
-  return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
+  return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->x.pRight);
 }
 
 /*
@@ -1055,7 +1064,7 @@ static void exprAnalyze(
   prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft);
   op = pExpr->op;
   if( op==TK_IN ){
-    assert( pExpr->pRight==0 );
+    assert( pExpr->eX!=EX_Right );
     if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
     switch( pExpr->eX ){
       case EX_Select: {
@@ -1067,10 +1076,13 @@ static void exprAnalyze(
         break;
       }
     }
-  }else if( op==TK_ISNULL ){
-    pTerm->prereqRight = 0;
   }else{
-    pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight);
+    assert( op!=TK_ISNULL || pExpr->eX!=EX_Right );
+    if( pExpr->eX==EX_Right ){
+      pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->x.pRight);
+    }else{
+      pTerm->prereqRight = 0;
+    }
   }
   pMaskSet->bVarSelect = 0;
   prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr);
@@ -1091,10 +1103,16 @@ static void exprAnalyze(
   pTerm->eOperator = 0;
   if( allowedOp(op) ){
     int aiCurCol[2];
-    Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
-    Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
-    u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
+    Expr *pLeft, *pRight;
+    u16 opMask;
 
+    pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
+    if( pExpr->eX==EX_Right ){
+      pRight = sqlite3ExprSkipCollate(pExpr->x.pRight);
+    }else{
+      pRight = 0;
+    }
+    opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
     if( pTerm->iField>0 ){
       assert( op==TK_IN );
       assert( pLeft->op==TK_VECTOR );
@@ -1335,16 +1353,18 @@ static void exprAnalyze(
   if( pWC->op==TK_AND 
   && (pExpr->op==TK_EQ || pExpr->op==TK_IS)
   && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
-  && sqlite3ExprVectorSize(pExpr->pRight)==nLeft
-  && ( pExpr->pLeft->eX!=EX_Select || pExpr->pRight->eX!=EX_Select )
+  && ALWAYS(pExpr->eX==EX_Right)
+  && sqlite3ExprVectorSize(pExpr->x.pRight)==nLeft
+  && ( pExpr->pLeft->eX!=EX_Select || pExpr->x.pRight->eX!=EX_Select )
   ){
     int i;
     for(i=0; i<nLeft; i++){
       int idxNew;
-      Expr *pNew;
-      Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
-      Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
+      Expr *pNew, *pLeft, *pRight;
 
+      pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
+      assert( pExpr->eX==EX_Right );
+      pRight = sqlite3ExprForVectorField(pParse, pExpr->x.pRight, i);
       pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
       transferJoinMarkings(pNew, pExpr);
       idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
@@ -1452,8 +1472,9 @@ void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
   if( pE2->op!=op ){
     whereClauseInsert(pWC, pExpr, 0);
   }else{
+    assert( pE2->eX==EX_Right );
     sqlite3WhereSplit(pWC, pE2->pLeft, op);
-    sqlite3WhereSplit(pWC, pE2->pRight, op);
+    sqlite3WhereSplit(pWC, pE2->x.pRight, op);
   }
 }
 
@@ -1512,20 +1533,19 @@ Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
   }
   mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0;
   if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft);
-  if( p->pRight ){
-    mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pRight);
-    assert( p->x.pList==0 );
-  }else{
-    switch( p->eX ){
-      case EX_Select: {
-        if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
-        mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
-        break;
-      }
-      case EX_List: {
-        mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
-        break;
-      }
+  switch( p->eX ){
+    case EX_Right: {
+      mask |= sqlite3WhereExprUsageNN(pMaskSet, p->x.pRight);
+      break;
+    }
+    case EX_Select: {
+      if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
+      mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
+      break;
+    }
+    case EX_List: {
+      mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
+      break;
     }
   }
   return mask;