]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
In the Expr object, the Expr.eX field determines what value is stored in the
authordrh <drh@noemail.net>
Tue, 18 Sep 2018 21:35:31 +0000 (21:35 +0000)
committerdrh <drh@noemail.net>
Tue, 18 Sep 2018 21:35:31 +0000 (21:35 +0000)
Expr.x union.  This mostly works, but there are issues identified by valgrind.

FossilOrigin-Name: 8849a463d67d79ec60c74a08835c176c08da651a82731558a1dceac2781cd75d

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

index 97749237ef447965b3230326c6a54ae81f6e12a3..3e59128139b59d62dcebe2636732084407e20aa0 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Merge\sall\srecent\strunk\senhancements.
-D 2018-09-18T18:08:01.839
+C In\sthe\sExpr\sobject,\sthe\sExpr.eX\sfield\sdetermines\swhat\svalue\sis\sstored\sin\sthe\nExpr.x\sunion.\s\sThis\smostly\sworks,\sbut\sthere\sare\sissues\sidentified\sby\svalgrind.
+D 2018-09-18T21:35:31.300
 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 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a
+F src/attach.c 8b8e52590fca04bed868461aadc5d38de7542f005310ced863e032c83e1b1b6a
 F src/auth.c 32a5bbe3b755169ab6c66311c5225a3cd4f75a46c041f7fb117e0cbb68055114
 F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
 F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
@@ -453,11 +453,11 @@ F src/ctime.c b157b01081f92442f8b0218ddb93ddce8ebddad36dbddeecfdd771561dd4f387
 F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
 F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3
 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91
-F src/delete.c 107e28d3ef8bd72fd11953374ca9107cd74e8b09c3ded076a6048742d26ce7d2
-F src/expr.c 83c279eda8f3a888141e2432633051f644db68fdb7882c12e0ef00894d7f8ade
+F src/delete.c 07a7ecf18a64478be7241cbb332bc26321586384c750e47fb566f678c5aee512
+F src/expr.c c7d6ce81a4363fc3be403ac05a86a6ea3ed63c5c6668d9c774fd4bb714f07911
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c f59253c0be4b1e9dfcb073b6d6d6ab83090ae50c08b5c113b76013c4b157cd6a
-F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f
+F src/func.c 82aeef69505b67197a476836d44cc16c1a434ee53481f23cffb70a75a1bcbc7a
 F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128
 F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
 F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
@@ -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 4118dbf9c37c410e5c4775c033b1aaf67ac8ff7965df7a4bb429dd5db2dbe374
+F src/parse.y 15eeb0ead639555727ed81fc61bd8e28968e9379bc074ae9cb48b95c79b50f0d
 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 352c6af1a99441206ff62a6f7429dbf537827f42c428639695220b9c8639e33b
+F src/resolve.c 301eadb8bf5afcd0b673d4db3c85c179334e19970af276187932e5b0a97b90ec
 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
-F src/select.c 8afcc2b56a6ef76717bb59b6109cd3de0f6fae2803894d6f806640c0aa24dfac
+F src/select.c af9efbeea79c7eaa21f51c2640f9f8e21d1c9dbcea236d5af68bb8f0313d9b1e
 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 83ee9b55db521b70294b2858872e69b96d0a4810d8221796def3e99cca5ee663
+F src/sqliteInt.h 0aed6451d241a43814ac54d93f7d2b8645826ffa9e35e7289240dd38e967b813
 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 e7a7f90552bb418533cdd0309b5eb71d4effa50165b880fc8c2001e613577e5f
+F src/treeview.c b6f459831c544d697e4b38471b98b972d9dd3b4611d0e8c6338632c7ad926d12
 F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd
 F src/update.c 682f112c49247d2fe5950c9fe2226046c6bc497cf114f74d58766926914216ff
 F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
@@ -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 ba7225773931760cf60bf22f34d0cce2588df7ce5ce0f215a52eb88234b55ac4
-F src/where.c 2019126801437944c38cc62a99491e98591460b7cc07ab57eb66165f710a289b
+F src/walker.c b2d62136868f1f939a7778bdce8b372bb4e314862cd2b33bd1ec9614eef0b44c
+F src/where.c c90c392c7c8c8ea3e36592dba9800cee35eeadd36c512ab904da8245c334b148
 F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4
-F src/wherecode.c 4f88f5b39ad4aeb5bdd47a546d74149bb902ef49ca9f02a45b2a5bd2dd70b6bd
-F src/whereexpr.c eb462ebe085f6cbb6bdda797a041fbd7e3724586203344043d1088a2117d8e44
+F src/wherecode.c 75a3b20d28a5c9f88e6c6dd9037ffeacdd786feaba8013245f7d8576a093dcf4
+F src/whereexpr.c c08b5afce2e7b9046c65f5edc3302888d79e8c541907a97df089c135895b25f0
 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 81f25d5c84e4d2d0cd3c6a7c105c7c93d310218feeea4e023dbc32e7e96b2a52 e461cb281959d8517296e3e4e934eba8206770b1a592cd7655b6567268da1634
-R da6eee78fa2fbbeca2d219d82da2f3c5
+P 655f065404e08083ad5eb9b22a036f410b46eb5eb2bcfb0fbc953b4e152c95e7
+R cc9722e20d1a4071193f4dca3fb58785
 U drh
-Z d193f19d8649854bc581fb0b4773613d
+Z bb5fe9a1a876c7e1afc567f393930991
index 8575e39ee7e68606d749f5d9ee4eb820900f6a2b..2102aadff2bc6258a1160dc5517993bc7fe95206 100644 (file)
@@ -1 +1 @@
-655f065404e08083ad5eb9b22a036f410b46eb5eb2bcfb0fbc953b4e152c95e7
\ No newline at end of file
+8849a463d67d79ec60c74a08835c176c08da651a82731558a1dceac2781cd75d
\ No newline at end of file
index 42ae53694269c128cb74cf7153b628edbf3524da..9d77d83c4758b5a86d04606c3ccaec43e4851818 100644 (file)
@@ -564,10 +564,15 @@ int sqlite3FixExpr(
       }
     }
     if( ExprHasProperty(pExpr, EP_TokenOnly|EP_Leaf) ) break;
-    if( ExprHasProperty(pExpr, EP_xIsSelect) ){
-      if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
-    }else{
-      if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
+    switch( pExpr->eX ){
+      case EX_Select: {
+        if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
+        break;
+      }
+      case EX_List: {
+        if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
+        break;
+      }
     }
     if( sqlite3FixExpr(pFix, pExpr->pRight) ){
       return 1;
index 746f6725b90bdf805c98a33511273b61dc57ec85..cd6254aae8b0e18de8ada3705a47ef86fa516a0e 100644 (file)
@@ -185,9 +185,7 @@ Expr *sqlite3LimitWhere(
         pEList = sqlite3ExprListAppend(pParse, pEList, p);
       }
       pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
-      if( pLhs ){
-        pLhs->x.pList = sqlite3ExprListDup(db, pEList, 0);
-      }
+      sqlite3PExprAddExprList(pParse, pLhs, pEList);
     }
   }
 
index 063627505b4d35527fb486ce9ed9f5e579748c9d..0053c9fbd69b6986345372cb7f69e3d793ceb105 100644 (file)
@@ -48,7 +48,7 @@ char sqlite3ExprAffinity(Expr *pExpr){
   if( pExpr->flags & EP_Generic ) return 0;
   op = pExpr->op;
   if( op==TK_SELECT ){
-    assert( pExpr->flags&EP_xIsSelect );
+    assert( pExpr->eX==EX_Select );
     return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
   }
   if( op==TK_REGISTER ) op = pExpr->op2;
@@ -62,7 +62,7 @@ char sqlite3ExprAffinity(Expr *pExpr){
     return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
   }
   if( op==TK_SELECT_COLUMN ){
-    assert( pExpr->pLeft->flags&EP_xIsSelect );
+    assert( pExpr->pLeft->eX==EX_Select );
     return sqlite3ExprAffinity(
         pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
     );
@@ -108,7 +108,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( pExpr->eX==EX_List );
       assert( pExpr->x.pList->nExpr>0 );
       assert( pExpr->op==TK_FUNCTION );
       pExpr = pExpr->x.pList->a[0].pExpr;
@@ -167,12 +167,10 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
         p = p->pLeft;
       }else{
         Expr *pNext  = p->pRight;
-        /* The Expr.x union is never used at the same time as Expr.pRight */
-        assert( p->x.pList==0 || p->pRight==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. */
-        if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){
+        if( p->eX==EX_List ){
           int i;
           for(i=0; ALWAYS(i<p->x.pList->nExpr); i++){
             if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){
@@ -260,7 +258,7 @@ static char comparisonAffinity(Expr *pExpr){
   aff = sqlite3ExprAffinity(pExpr->pLeft);
   if( pExpr->pRight ){
     aff = sqlite3CompareAffinity(pExpr->pRight, aff);
-  }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+  }else if( pExpr->eX==EX_Select ){
     aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
   }else if( aff==0 ){
     aff = SQLITE_AFF_BLOB;
@@ -439,7 +437,7 @@ Expr *sqlite3ExprForVectorField(
 ){
   Expr *pRet;
   if( pVector->op==TK_SELECT ){
-    assert( pVector->flags & EP_xIsSelect );
+    assert( pVector->eX==EX_Select );
     /* The TK_SELECT_COLUMN Expr node:
     **
     ** pLeft:           pVector containing TK_SELECT.  Not deleted.
@@ -682,9 +680,9 @@ static void exprSetHeight(Expr *p){
   int nHeight = 0;
   heightOfExpr(p->pLeft, &nHeight);
   heightOfExpr(p->pRight, &nHeight);
-  if( ExprHasProperty(p, EP_xIsSelect) ){
+  if( p->eX==EX_Select ){
     heightOfSelect(p->x.pSelect, &nHeight);
-  }else if( p->x.pList ){
+  }else if( p->eX==EX_List ){
     heightOfExprList(p->x.pList, &nHeight);
     p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
   }
@@ -700,7 +698,7 @@ static void exprSetHeight(Expr *p){
 ** Expr.flags. 
 */
 void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
-  if( pParse->nErr ) return;
+  if( p==0 || pParse->nErr ) return;
   exprSetHeight(p);
   sqlite3ExprCheckHeight(pParse, p->nHeight);
 }
@@ -720,7 +718,7 @@ int sqlite3SelectExprHeight(Select *p){
 ** Expr.flags. 
 */
 void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
-  if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){
+  if( p && p->eX==EX_List ){
     p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
   }
 }
@@ -873,9 +871,11 @@ Expr *sqlite3PExpr(
 ** do a memory allocation failure) then delete the pSelect object.
 */
 void sqlite3PExprAddSelect(Parse *pParse, Expr *pExpr, Select *pSelect){
-  if( pExpr ){
+  if( pExpr && pSelect ){
+    assert( pExpr->eX==EX_None );
+    pExpr->eX = EX_Select;
     pExpr->x.pSelect = pSelect;
-    ExprSetProperty(pExpr, EP_xIsSelect|EP_Subquery);
+    ExprSetProperty(pExpr, EP_Subquery);
     sqlite3ExprSetHeightAndFlags(pParse, pExpr);
   }else{
     assert( pParse->db->mallocFailed );
@@ -883,6 +883,22 @@ void sqlite3PExprAddSelect(Parse *pParse, Expr *pExpr, Select *pSelect){
   }
 }
 
+/*
+** Add ExprList to the Expr.x.pList field.  Or, if pExpr is NULL (due
+** do a memory allocation failure) then delete the pSelect object.
+*/
+void sqlite3PExprAddExprList(Parse *pParse, Expr *pExpr, ExprList *pList){
+  if( pExpr && pList ){
+    assert( pExpr->eX==EX_None );
+    pExpr->eX = EX_List;
+    pExpr->x.pList = pList;
+    /* sqlite3ExprSetHeightAndFlags(pParse, pExpr); // done by caller */
+  }else{
+    assert( pParse->db->mallocFailed );
+    sqlite3ExprListDelete(pParse->db, pList);
+  }
+}
+
 
 /*
 ** If the expression is always either TRUE or FALSE (respectively),
@@ -956,9 +972,12 @@ Expr *sqlite3ExprFunction(
   if( pList && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
     sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken);
   }
-  pNew->x.pList = pList;
+  assert( pNew->eX==EX_None );
+  if( pList ){
+    pNew->eX = EX_List;
+    pNew->x.pList = pList;
+  }
   ExprSetProperty(pNew, EP_HasFunc);
-  assert( !ExprHasProperty(pNew, EP_xIsSelect) );
   sqlite3ExprSetHeightAndFlags(pParse, pNew);
   if( eDistinct==SF_Distinct ) ExprSetProperty(pNew, EP_Distinct);
   return pNew;
@@ -1052,11 +1071,13 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
   assert( p!=0 );
   /* Sanity check: Assert that the IntValue is non-negative if it exists */
   assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
+  assert( p->eX!=EX_Select || p->x.pSelect!=0 );
+  assert( p->eX!=EX_List || p->x.pList!=0 );
 #ifdef SQLITE_DEBUG
   if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){
     assert( p->pLeft==0 );
     assert( p->pRight==0 );
-    assert( p->x.pSelect==0 );
+    assert( p->eX==EX_None );
   }
   if( !ExprHasProperty(p, EP_TokenOnly) ){
     assert( p->op!=TK_FUNCTION || p->pLeft==0 );
@@ -1066,8 +1087,7 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
     assert( p->pWin==0 || p->pLeft==0 );
     assert( p->pWin==0 || p->pTab==0 );
     assert( p->pWin==0 || p->op==TK_FUNCTION );
-    assert( p->pWin==0 || !ExprHasProperty(p, EP_xIsSelect) );
-    assert( p->pTab==0 || (p->pRight==0 && p->x.pSelect==0) );
+    assert( p->pTab==0 || (p->pRight==0 && p->eX==EX_None) );
   }
 #endif
   if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){
@@ -1076,10 +1096,17 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
     if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
     if( p->pRight ){
       sqlite3ExprDeleteNN(db, p->pRight);
-    }else if( ExprHasProperty(p, EP_xIsSelect) ){
-      sqlite3SelectDelete(db, p->x.pSelect);
     }else{
-      sqlite3ExprListDelete(db, p->x.pList);
+      switch( p->eX ){
+        case EX_Select: {
+          sqlite3SelectDelete(db, p->x.pSelect);
+          break;
+        }
+        case EX_List: {
+          sqlite3ExprListDelete(db, p->x.pList);
+          break;
+        }
+      }
     }
     if( !ExprHasProperty(p, EP_Reduced) ){
       sqlite3WindowDelete(db, p->pWin);
@@ -1259,6 +1286,8 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
     pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken);
     pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
     pNew->flags |= staticFlag;
+    assert( pNew->eX==p->eX );
+    assert( pNew->eV==p->eV );
 
     /* Copy the p->u.zToken string, if any. */
     if( nToken ){
@@ -1268,10 +1297,19 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
 
     if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){
       /* Fill in the pNew->x.pSelect or pNew->x.pList member. */
-      if( ExprHasProperty(p, EP_xIsSelect) ){
-        pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags);
-      }else{
-        pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags);
+      switch( p->eX ){
+        case EX_Select: {
+          assert( pNew->eX==EX_Select );
+          pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags);
+          if( pNew->x.pSelect==0 ) pNew->eX = EX_None;
+          break;
+        }
+        case EX_List: {
+          assert( pNew->eX==EX_List );
+          pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags);
+          if( pNew->x.pList==0 ) pNew->eX = EX_None;
+          break;
+        }
       }
     }
 
@@ -1965,7 +2003,7 @@ static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
   }
 
   /* Check if pExpr is a sub-select. If so, consider it variable. */
-  if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+  if( pExpr->eX==EX_Select ){
     pWalker->eCode = 0;
     return WRC_Abort;
   }
@@ -2171,8 +2209,10 @@ static Select *isCandidateForInOpt(Expr *pX){
   ExprList *pEList;
   Table *pTab;
   int i;
-  if( !ExprHasProperty(pX, EP_xIsSelect) ) return 0;  /* Not a subquery */
-  if( ExprHasProperty(pX, EP_VarSelect)  ) return 0;  /* Correlated subq */
+  if( pX->eX!=EX_Select ) return 0;      /* Not a subquery */
+  if( ExprHasProperty(pX, EP_VarSelect) ){
+    return 0;                            /* Correlated subq */
+  }
   p = pX->x.pSelect;
   if( p->pPrior ) return 0;              /* Not a compound SELECT */
   if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
@@ -2230,7 +2270,7 @@ static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){
 static int sqlite3InRhsIsConstant(Expr *pIn){
   Expr *pLHS;
   int res;
-  assert( !ExprHasProperty(pIn, EP_xIsSelect) );
+  assert( pIn->eX!=EX_Select );
   pLHS = pIn->pLeft;
   pIn->pLeft = 0;
   res = sqlite3ExprIsConstant(pIn);
@@ -2341,7 +2381,7 @@ int sqlite3FindInIndex(
   ** or not NULL is actually possible (it may not be, for example, due 
   ** to NOT NULL constraints in the schema). If no NULL values are possible,
   ** set prRhsHasNull to 0 before continuing.  */
-  if( prRhsHasNull && (pX->flags & EP_xIsSelect) ){
+  if( prRhsHasNull && pX->eX==EX_Select ){
     int i;
     ExprList *pEList = pX->x.pSelect->pEList;
     for(i=0; i<pEList->nExpr; i++){
@@ -2494,8 +2534,8 @@ int sqlite3FindInIndex(
   ** the IN operator so return IN_INDEX_NOOP.
   */
   if( eType==0
-   && (inFlags & IN_INDEX_NOOP_OK)
-   && !ExprHasProperty(pX, EP_xIsSelect)
+   && (inFlags & IN_INDEX_NOOP_OK)!=0
+   && pX->eX==EX_List
    && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2)
   ){
     eType = IN_INDEX_NOOP;
@@ -2510,7 +2550,7 @@ int sqlite3FindInIndex(
     eType = IN_INDEX_EPH;
     if( inFlags & IN_INDEX_LOOP ){
       pParse->nQueryLoop = 0;
-      if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
+      if( pX->pLeft->iColumn<0 && pX->eX==EX_List ){
         eType = IN_INDEX_ROWID;
       }
     }else if( prRhsHasNull ){
@@ -2543,7 +2583,7 @@ int sqlite3FindInIndex(
 static char *exprINAffinity(Parse *pParse, Expr *pExpr){
   Expr *pLeft = pExpr->pLeft;
   int nVal = sqlite3ExprVectorSize(pLeft);
-  Select *pSelect = (pExpr->flags & EP_xIsSelect) ? pExpr->x.pSelect : 0;
+  Select *pSelect = (pExpr->eX==EX_Select) ? pExpr->x.pSelect : 0;
   char *zRet;
 
   assert( pExpr->op==TK_IN );
@@ -2591,7 +2631,7 @@ void sqlite3SubselectError(Parse *pParse, int nActual, int nExpect){
 */   
 void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){
 #ifndef SQLITE_OMIT_SUBQUERY
-  if( pExpr->flags & EP_xIsSelect ){
+  if( pExpr->eX==EX_Select ){
     sqlite3SubselectError(pParse, pExpr->x.pSelect->pEList->nExpr, 1);
   }else
 #endif
@@ -2683,7 +2723,8 @@ int sqlite3CodeSubselect(
           pExpr->iTable, (isRowid?0:nVal));
       pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, nVal, 1);
 
-      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+      assert( pExpr->eX==EX_Select || pExpr->eX==EX_List );
+      if( pExpr->eX==EX_Select ){
         /* Case 1:     expr IN (SELECT ...)
         **
         ** Generate code to write the results of the select into the temporary
@@ -2812,7 +2853,7 @@ int sqlite3CodeSubselect(
       testcase( pExpr->op==TK_EXISTS );
       testcase( pExpr->op==TK_SELECT );
       assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
-      assert( ExprHasProperty(pExpr, EP_xIsSelect) );
+      assert( pExpr->eX==EX_Select );
 
       pSel = pExpr->x.pSelect;
       ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY",
@@ -2869,7 +2910,7 @@ int sqlite3CodeSubselect(
 */
 int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){
   int nVector = sqlite3ExprVectorSize(pIn->pLeft);
-  if( (pIn->flags & EP_xIsSelect) ){
+  if( pIn->eX==EX_Select ){
     if( nVector!=pIn->x.pSelect->pEList->nExpr ){
       sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector);
       return 1;
@@ -2999,7 +3040,7 @@ static void sqlite3ExprCodeIN(
     int r2, regToFree;
     int regCkNull = 0;
     int ii;
-    assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+    assert( pExpr->eX==EX_List );
     if( destIfNull!=destIfFalse ){
       regCkNull = sqlite3GetTempReg(pParse);
       sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull);
@@ -3637,7 +3678,7 @@ expr_code_doover:
         ** out of the inner loop, even if that means an extra OP_Copy. */
         return sqlite3ExprCodeAtInit(pParse, pExpr, -1);
       }
-      assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+      assert( pExpr->eX==EX_List || pExpr->eX==EX_None );
       if( ExprHasProperty(pExpr, EP_TokenOnly) ){
         pFarg = 0;
       }else{
@@ -3946,8 +3987,8 @@ expr_code_doover:
       Expr *pX;                         /* The X expression */
       Expr *pTest = 0;                  /* X==Ei (form A) or just Ei (form B) */
 
-      assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
-      assert(pExpr->x.pList->nExpr > 0);
+      assert( pExpr->eX==EX_List );
+      assert( pExpr->x.pList->nExpr > 0);
       pEList = pExpr->x.pList;
       aListelem = pEList->a;
       nExpr = pEList->nExpr;
@@ -4279,7 +4320,7 @@ static void exprCodeBetween(
   memset(&compRight, 0, sizeof(Expr));
   memset(&exprAnd, 0, sizeof(Expr));
 
-  assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+  assert( pExpr->eX==EX_List );
   exprX = *pExpr->pLeft;
   exprAnd.op = TK_AND;
   exprAnd.pLeft = &compLeft;
@@ -4741,11 +4782,13 @@ int sqlite3ExprCompare(Parse *pParse, 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( 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( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
+    if( pA->eX==EX_List ){
+      if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
+    }
     assert( (combinedFlags & EP_Reduced)==0 );
     if( pA->op!=TK_STRING && pA->op!=TK_TRUEFALSE ){
       if( pA->iColumn!=pB->iColumn ) return 2;
@@ -5200,14 +5243,14 @@ 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( pExpr->eX==EX_List || pExpr->eX==EX_None );
             pItem = &pAggInfo->aFunc[i];
             pItem->pExpr = pExpr;
             pItem->iMem = ++pParse->nMem;
             assert( !ExprHasProperty(pExpr, EP_IntValue) );
             pItem->pFunc = sqlite3FindFunction(pParse->db,
                    pExpr->u.zToken, 
-                   pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0);
+                   pExpr->eX==EX_List ? pExpr->x.pList->nExpr : 0, enc, 0);
             if( pExpr->flags & EP_Distinct ){
               pItem->iDistinct = pParse->nTab++;
             }else{
index 0504a8f0266e8e5433a15fe03b96b00589f33df8..9cc744965ad671dc7fd1b617051a7a0e779e925a 100644 (file)
@@ -1848,7 +1848,7 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
   if( pExpr->op!=TK_FUNCTION || !pExpr->x.pList ){
     return 0;
   }
-  assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+  assert( pExpr->eX==EX_List );
   nExpr = pExpr->x.pList->nExpr;
   pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0);
   if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){
index f2cb072948e08dd50224cf445d2747da8c1b325e..aaa2f91787137d131ba6b92d5428c648630b47a4 100644 (file)
@@ -936,10 +936,10 @@ idlist(A) ::= nm(Y).
       /* memset(p, 0, sizeof(Expr)); */
       p->op = (u8)op;
       p->affinity = 0;
+      p->eX = EX_None;
       p->flags = EP_Leaf;
       p->iAgg = -1;
       p->pLeft = p->pRight = 0;
-      p->x.pList = 0;
       p->pAggInfo = 0;
       p->pTab = 0;
       p->op2 = 0;
@@ -1052,11 +1052,7 @@ term(A) ::= CTIME_KW(OP). {
 expr(A) ::= LP nexprlist(X) COMMA expr(Y) RP. {
   ExprList *pList = sqlite3ExprListAppend(pParse, X, Y);
   A = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
-  if( A ){
-    A->x.pList = pList;
-  }else{
-    sqlite3ExprListDelete(pParse->db, pList);
-  }
+  sqlite3PExprAddExprList(pParse, A, pList);
 }
 
 expr(A) ::= expr(A) AND(OP) expr(Y).    {A=sqlite3PExpr(pParse,@OP,A,Y);}
@@ -1143,11 +1139,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
   ExprList *pList = sqlite3ExprListAppend(pParse,0, X);
   pList = sqlite3ExprListAppend(pParse,pList, Y);
   A = sqlite3PExpr(pParse, TK_BETWEEN, A, 0);
-  if( A ){
-    A->x.pList = pList;
-  }else{
-    sqlite3ExprListDelete(pParse->db, pList);
-  } 
+  sqlite3PExprAddExprList(pParse, A, pList);
   if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
 }
 %ifndef SQLITE_OMIT_SUBQUERY
@@ -1195,12 +1187,8 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
       A = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, A, pRHS);
     }else{
       A = sqlite3PExpr(pParse, TK_IN, A, 0);
-      if( A ){
-        A->x.pList = Y;
-        sqlite3ExprSetHeightAndFlags(pParse, A);
-      }else{
-        sqlite3ExprListDelete(pParse->db, Y);
-      }
+      sqlite3PExprAddExprList(pParse, A, Y);
+      sqlite3ExprSetHeightAndFlags(pParse, A);
       if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
     }
   }
@@ -1231,13 +1219,8 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
 /* CASE expressions */
 expr(A) ::= CASE case_operand(X) case_exprlist(Y) case_else(Z) END. {
   A = sqlite3PExpr(pParse, TK_CASE, X, 0);
-  if( A ){
-    A->x.pList = Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y;
-    sqlite3ExprSetHeightAndFlags(pParse, A);
-  }else{
-    sqlite3ExprListDelete(pParse->db, Y);
-    sqlite3ExprDelete(pParse->db, Z);
-  }
+  sqlite3PExprAddExprList(pParse,A,Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y);
+  sqlite3ExprSetHeightAndFlags(pParse, A);
 }
 %type case_exprlist {ExprList*}
 %destructor case_exprlist {sqlite3ExprListDelete(pParse->db, $$);}
index 9fb4d4c63fb50d5fb5079f8a2e5e1922d51b4ad5..6b2111af298ea3fdd9a165d43cbb333b2ab44c69 100644 (file)
@@ -430,8 +430,7 @@ static int lookupName(
         if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
           Expr *pOrig;
           assert( pExpr->pLeft==0 && pExpr->pRight==0 );
-          assert( pExpr->x.pList==0 );
-          assert( pExpr->x.pSelect==0 );
+          assert( pExpr->eX==EX_None );
           pOrig = pEList->a[j].pExpr;
           if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){
             sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
@@ -701,8 +700,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
     /* Resolve function names
     */
     case TK_FUNCTION: {
-      ExprList *pList = pExpr->x.pList;    /* The argument list */
-      int n = pList ? pList->nExpr : 0;    /* Number of arguments */
+      ExprList *pList;            /* The argument list */
+      int n;                      /* Number of arguments */
       int no_such_func = 0;       /* True if no such function exists */
       int wrong_num_args = 0;     /* True if wrong number of arguments */
       int is_agg = 0;             /* True if is an aggregate function */
@@ -711,7 +710,14 @@ 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( pExpr->eX==EX_List || pExpr->eX==EX_None );
+      if( pExpr->eX==EX_List ){
+        pList = pExpr->x.pList;
+        n = pList->nExpr;
+      }else{
+        pList = 0;
+        n = 0;
+      }
       zId = pExpr->u.zToken;
       nId = sqlite3Strlen30(zId);
       pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
@@ -876,7 +882,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
 #endif
     case TK_IN: {
       testcase( pExpr->op==TK_IN );
-      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+      if( pExpr->eX==EX_Select ){
         int nRef = pNC->nRef;
         notValid(pParse, pNC, "subqueries", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
         sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
index bc5960fe49d6bb803e09e3986b40e886da4946ab..17ba72c76de38ea7320ded53db7d80c373838006 100644 (file)
@@ -1736,7 +1736,7 @@ static const char *columnTypeImpl(
       NameContext sNC;
       Select *pS = pExpr->x.pSelect;
       Expr *p = pS->pEList->a[0].pExpr;
-      assert( ExprHasProperty(pExpr, EP_xIsSelect) );
+      assert( pExpr->eX==EX_Select );
       sNC.pSrcList = pS->pSrc;
       sNC.pNext = pNC;
       sNC.pParse = pNC->pParse;
@@ -3472,10 +3472,15 @@ static Expr *substExpr(
     }
     pExpr->pLeft = substExpr(pSubst, pExpr->pLeft);
     pExpr->pRight = substExpr(pSubst, pExpr->pRight);
-    if( ExprHasProperty(pExpr, EP_xIsSelect) ){
-      substSelect(pSubst, pExpr->x.pSelect, 1);
-    }else{
-      substExprList(pSubst, pExpr->x.pList);
+    switch( pExpr->eX ){
+      case EX_Select: {
+        substSelect(pSubst, pExpr->x.pSelect, 1);
+        break;
+      }
+      case EX_List: {
+        substExprList(pSubst, pExpr->x.pList);
+        break;
+      }
     }
   }
   return pExpr;
@@ -5242,8 +5247,8 @@ 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) );
-      if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
+      assert( pE->eX==EX_List || pE->eX==EX_None );
+      if( pE->eX==EX_None || pE->x.pList->nExpr!=1 ){
         sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
            "argument");
         pFunc->iDistinct = -1;
@@ -5266,7 +5271,8 @@ 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( pF->pExpr->eX==EX_List || pF->pExpr->eX==EX_None );
+    assert( pF->pExpr->eX==EX_List || pList==0 );
     sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0);
     sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
   }
@@ -5296,7 +5302,7 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
     int addrNext = 0;
     int regAgg;
     ExprList *pList = pF->pExpr->x.pList;
-    assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
+    assert( pF->pExpr->eX==EX_List || pF->pExpr->eX==EX_None );
     if( pList ){
       nArg = pList->nExpr;
       regAgg = sqlite3GetTempRange(pParse, nArg);
@@ -6186,10 +6192,11 @@ int sqlite3Select(
       minMaxFlag = WHERE_ORDERBY_NORMAL;
     }
     for(i=0; i<sAggInfo.nFunc; i++){
-      assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) );
-      sNC.ncFlags |= NC_InAggFunc;
-      sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);
-      sNC.ncFlags &= ~NC_InAggFunc;
+      if( sAggInfo.aFunc[i].pExpr->eX==EX_List ){
+        sNC.ncFlags |= NC_InAggFunc;
+        sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);
+        sNC.ncFlags &= ~NC_InAggFunc;
+      }
     }
     sAggInfo.mxReg = pParse->nMem;
     if( db->mallocFailed ) goto select_end;
index 74438b5abc49bb6a0b8c72ccaac9ffa1c903cd8b..5779f4d3c3871da74a105d7bf3a261675419d23d 100644 (file)
@@ -2419,6 +2419,8 @@ typedef int ynVar;
 struct Expr {
   u8 op;                 /* Operation performed by this node */
   char affinity;         /* The affinity of the column or 0 if not a column */
+  u8 eV;                 /* Which element of v-union is used */
+  u8 eX;                 /* Which element of x-union is used */
   u32 flags;             /* Various flags.  EP_* See below */
   union {
     char *zToken;          /* Token value. Zero terminated and dequoted */
@@ -2466,6 +2468,20 @@ struct Expr {
 #endif
 };
 
+/*
+** Allowed values for the Expr.eV and Expr.eX fields:
+*/
+#define EV_None     0    /* Expr.v is not used */
+#define EV_Left     1    /* Expr.v.pLeft */
+#define EV_Vector   2    /* Expr.v.pVector */
+#define EV_Win      3    /* Expr.v.pWin */
+
+#define EX_None     0    /* Expr.x is not used */
+#define EX_Right    1    /* Expr.x.pRight */
+#define EX_List     2    /* Expr.x.pList */
+#define EX_Select   3    /* Expr.x.pSelect */
+#define EX_Tab      4    /* Expr.x.pTab */
+
 /*
 ** The following are the meanings of bits in the Expr.flags field.
 */
@@ -2480,7 +2496,7 @@ 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) */
+/*                   0x000800 -- Available for reuse */
 #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 */
@@ -3794,6 +3810,7 @@ Expr *sqlite3Expr(sqlite3*,int,const char*);
 void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
 Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*);
 void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
+void sqlite3PExprAddExprList(Parse*, Expr*, ExprList*);
 Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
 Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
 void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
index cde776d0fa2ee6f4f93ef16dd83b4002e08a5829..713fc13b5b718008cc9858047b738963a84e89c0 100644 (file)
@@ -532,10 +532,15 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
     case TK_IN: {
       sqlite3TreeViewLine(pView, "IN flags=0x%x", pExpr->flags);
       sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
-      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
-        sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
-      }else{
-        sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
+      switch( pExpr->eX ){
+        case EX_Select: {
+          sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
+          break;
+        }
+        case EX_List: {
+          sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
+          break;
+        }
       }
       break;
     }
index b3d4cd805d493fe5dff3bedf42f766110de92f99..4c6701f1c7377751b4ddf80ef7595b884be43d66 100644 (file)
@@ -49,10 +49,17 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
       if( pExpr->pRight ){
         pExpr = pExpr->pRight;
         continue;
-      }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
-        if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
-      }else if( pExpr->x.pList ){
-        if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
+      }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;
+          }
+        }
       }
 #ifndef SQLITE_OMIT_WINDOWFUNC
       if( !ExprHasProperty(pExpr, EP_Reduced) && pExpr->pWin ){
index d8d577d521288cb0c8803963fcea5bb4b9449d3d..2a195f8affabf86fcfc04d0238195df899213b61 100644 (file)
@@ -2330,7 +2330,8 @@ static int whereRangeVectorLen(
     CollSeq *pColl;               /* Comparison collation sequence */
     Expr *pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr;
     Expr *pRhs = pTerm->pExpr->pRight;
-    if( pRhs->flags & EP_xIsSelect ){
+    assert( pRhs->eX==EX_Select || pRhs->eX==EX_List );
+    if( pRhs->eX==EX_Select ){
       pRhs = pRhs->x.pSelect->pEList->a[i].pExpr;
     }else{
       pRhs = pRhs->x.pList->a[i].pExpr;
@@ -2488,24 +2489,29 @@ static int whereLoopAddBtreeIndex(
 
     if( eOp & WO_IN ){
       Expr *pExpr = pTerm->pExpr;
-      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
-        /* "x IN (SELECT ...)":  TUNING: the SELECT returns 25 rows */
-        int i;
-        nIn = 46;  assert( 46==sqlite3LogEst(25) );
-
-        /* The expression may actually be of the form (x, y) IN (SELECT...).
-        ** In this case there is a separate term for each of (x) and (y).
-        ** However, the nIn multiplier should only be applied once, not once
-        ** for each such term. The following loop checks that pTerm is the
-        ** first such term in use, and sets nIn back to 0 if it is not. */
-        for(i=0; i<pNew->nLTerm-1; i++){
-          if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0;
+      switch( pExpr->eX ){
+        case EX_Select: {
+          /* "x IN (SELECT ...)":  TUNING: the SELECT returns 25 rows */
+          int i;
+          nIn = 46;  assert( 46==sqlite3LogEst(25) );
+  
+          /* The expression may actually be of the form (x, y) IN (SELECT...).
+          ** In this case there is a separate term for each of (x) and (y).
+          ** However, the nIn multiplier should only be applied once, not once
+          ** for each such term. The following loop checks that pTerm is the
+          ** first such term in use, and sets nIn back to 0 if it is not. */
+          for(i=0; i<pNew->nLTerm-1; i++){
+            if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0;
+          }
+          break;
+        }
+        case EX_List: {
+          /* "x IN (value, value, ...)" */
+          nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
+          assert( nIn>0 );  /* RHS always has 2 or more terms...  The parser
+                            ** changes "x IN (?)" into "x=?". */
+          break;
         }
-      }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
-        /* "x IN (value, value, ...)" */
-        nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
-        assert( nIn>0 );  /* RHS always has 2 or more terms...  The parser
-                          ** changes "x IN (?)" into "x=?". */
       }
       if( pProbe->hasStat1 ){
         LogEst M, logK, safetyMargin;
@@ -2620,7 +2626,7 @@ static int whereLoopAddBtreeIndex(
         if( nInMul==0 
          && pProbe->nSample 
          && pNew->u.btree.nEq<=pProbe->nSampleCol
-         && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
+         && ((eOp & WO_IN)==0 || pTerm->pExpr->eX==EX_List)
          && OptimizationEnabled(db, SQLITE_Stat34)
         ){
           Expr *pExpr = pTerm->pExpr;
index 65cbc4ca2c801aecc52556b835d00e3c7c4c8619..84174ea5957ec838cf94ffa55d68188f1959f68d 100644 (file)
@@ -435,7 +435,9 @@ static Expr *removeUnindexableInClauseTerms(
     }
     sqlite3ExprListDelete(db, pOrigRhs);
     sqlite3ExprListDelete(db, pOrigLhs);
+    assert( pNew->pLeft->eX==EX_List );
     pNew->pLeft->x.pList = pLhs;
+    if( pLhs==0 ) pNew->pLeft->eX = EX_None;
     pNew->x.pSelect->pEList = pRhs;
     if( pLhs && pLhs->nExpr==1 ){
       /* Take care here not to generate a TK_VECTOR containing only a
@@ -538,7 +540,7 @@ static int codeEqualityTerm(
       if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
     }
 
-    if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){
+    if( pX->eX!=EX_Select || pX->x.pSelect->pEList->nExpr==1 ){
       eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0);
     }else{
       sqlite3 *db = pParse->db;
@@ -734,7 +736,7 @@ static int codeAllEqualityTerms(
       }
     }
     if( pTerm->eOperator & WO_IN ){
-      if( pTerm->pExpr->flags & EP_xIsSelect ){
+      if( pTerm->pExpr->eX==EX_Select ){
         /* No affinity ever needs to be (or should be) applied to a value
         ** from the RHS of an "? IN (SELECT ...)" expression. The 
         ** sqlite3FindInIndex() routine has already ensured that the 
@@ -1074,7 +1076,7 @@ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
   assert( nReg>0 );
   if( p && sqlite3ExprIsVector(p) ){
 #ifndef SQLITE_OMIT_SUBQUERY
-    if( (p->flags & EP_xIsSelect) ){
+    if( p->eX==EX_Select ){
       Vdbe *v = pParse->pVdbe;
       int iSelect = sqlite3CodeSubselect(pParse, p, 0, 0);
       sqlite3VdbeAddOp3(v, OP_Copy, iSelect, iReg, nReg-1);
@@ -2194,7 +2196,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
     if( pAlt==0 ) continue;
     if( pAlt->wtFlags & (TERM_CODED) ) continue;
     if( (pAlt->eOperator & WO_IN) 
-     && (pAlt->pExpr->flags & EP_xIsSelect)
+     && (pAlt->pExpr->eX==EX_Select)
      && (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
     ){
       continue;
index 808c0d21c740c4beef880a38ad075950dd1fd874..16d441c52bbe9fcc4db7ffd8ed1e36bec0ab3530 100644 (file)
@@ -860,18 +860,20 @@ static void exprAnalyzeOrTerm(
       assert( pLeft!=0 );
       pDup = sqlite3ExprDup(db, pLeft, 0);
       pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0);
-      if( pNew ){
+      if( pNew && pList ){
         int idxNew;
         transferJoinMarkings(pNew, pExpr);
-        assert( !ExprHasProperty(pNew, EP_xIsSelect) );
+        assert( pNew->eX==EX_None );
+        pNew->eX = EX_List;
         pNew->x.pList = pList;
         idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
         testcase( idxNew==0 );
         exprAnalyze(pSrc, pWC, idxNew);
-        /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where used again */
+        /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm used again */
         markTermAsChild(pWC, idxNew, idxTerm);
       }else{
         sqlite3ExprListDelete(db, pList);
+        sqlite3ExprDelete(db, pNew);
       }
     }
   }
@@ -1055,10 +1057,15 @@ static void exprAnalyze(
   if( op==TK_IN ){
     assert( pExpr->pRight==0 );
     if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
-    if( ExprHasProperty(pExpr, EP_xIsSelect) ){
-      pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect);
-    }else{
-      pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList);
+    switch( pExpr->eX ){
+      case EX_Select: {
+        pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect);
+        break;
+      }
+      case EX_List: {
+        pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet,pExpr->x.pList);
+        break;
+      }
     }
   }else if( op==TK_ISNULL ){
     pTerm->prereqRight = 0;
@@ -1329,8 +1336,7 @@ static void exprAnalyze(
   && (pExpr->op==TK_EQ || pExpr->op==TK_IS)
   && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
   && sqlite3ExprVectorSize(pExpr->pRight)==nLeft
-  && ( (pExpr->pLeft->flags & EP_xIsSelect)==0 
-    || (pExpr->pRight->flags & EP_xIsSelect)==0)
+  && ( pExpr->pLeft->eX!=EX_Select || pExpr->pRight->eX!=EX_Select )
   ){
     int i;
     for(i=0; i<nLeft; i++){
@@ -1509,11 +1515,18 @@ Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
   if( p->pRight ){
     mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pRight);
     assert( p->x.pList==0 );
-  }else if( ExprHasProperty(p, EP_xIsSelect) ){
-    if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
-    mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
-  }else if( p->x.pList ){
-    mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
+  }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;
+      }
+    }
   }
   return mask;
 }