-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
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
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
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
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
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
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
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
-655f065404e08083ad5eb9b22a036f410b46eb5eb2bcfb0fbc953b4e152c95e7
\ No newline at end of file
+8849a463d67d79ec60c74a08835c176c08da651a82731558a1dceac2781cd75d
\ No newline at end of file
}
}
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;
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);
}
}
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;
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
);
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;
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) ){
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;
){
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.
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);
}
** Expr.flags.
*/
void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
- if( pParse->nErr ) return;
+ if( p==0 || pParse->nErr ) return;
exprSetHeight(p);
sqlite3ExprCheckHeight(pParse, p->nHeight);
}
** 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);
}
}
** 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 );
}
}
+/*
+** 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),
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;
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 );
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)) ){
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);
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 ){
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;
+ }
}
}
}
/* 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;
}
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) ){
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);
** 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++){
** 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;
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 ){
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 );
*/
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
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
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",
*/
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;
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);
** 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{
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;
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;
}
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;
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{
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 ){
/* 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;
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);}
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
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);
}
}
/* 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, $$);}
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);
/* 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 */
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);
#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);
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;
}
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;
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;
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);
}
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);
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;
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 */
#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.
*/
#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 */
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);
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;
}
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 ){
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;
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;
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;
}
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
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;
}
}
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
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);
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;
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);
}
}
}
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;
&& (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++){
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;
}