Protect all accesses to the Expr.x union using nearby assert()s and branches.
FossilOrigin-Name: 8eaa1d4a98b24adf245bbd2fe9212aa6a924a0f09c445906d7f87574f36a7423
This commit is contained in:
parent
9d43db5b5c
commit
a4eeccdfdf
34
manifest
34
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\san\sincorrect\sassert()\son\sPRAGMA\stable_xinfo\sadded\sby\sthe\sprevious\scheck-in.
|
||||
D 2021-10-07T14:19:32.259
|
||||
C Protect\sall\saccesses\sto\sthe\sExpr.x\sunion\susing\snearby\sassert()s\sand\sbranches.
|
||||
D 2021-10-07T17:43:30.167
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -501,10 +501,10 @@ F src/date.c fa928630fecf1d436cdc7a7a5c950c781709023ca782c21b7a43cc7361a9451e
|
||||
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
|
||||
F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d
|
||||
F src/delete.c 3ce6af6b64c8b476de51ccc32da0cb3142d42e65754e1d8118addf65b8bcba15
|
||||
F src/expr.c a2ceac9ee826c43d0943d1412bd8ef668db24fca57d2829453d13c6eb1dccb1c
|
||||
F src/expr.c 19c0b5c7afaf6a305274b7de312f319bd86e802383f08ef6633f0752f51d96a8
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 0c57a9cd2a0ecd04dde0c06e41df46959526f52a68c4409591e0f8c41a577042
|
||||
F src/func.c 315c63812b5ad965158fccdb3c15b155f62d123d064efeda87d35b23fd5d529d
|
||||
F src/func.c 9577175a1459f65c9e3c4bbe7ed0bdf97ee928f693c81ee9f61e2642414c917c
|
||||
F src/global.c 612ea60c9acbcb45754c2ed659b4a56936a06814718e969636fedc7e3b889808
|
||||
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
|
||||
F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
|
||||
@ -547,14 +547,14 @@ F src/pragma.h 87330ed2fbfa2a1274de93ca0ab850fba336189228cb256089202c3b52766fad
|
||||
F src/prepare.c 8f07616db04337057b8498b72d051ee90f73c54615c2e908c05404cef1e060b7
|
||||
F src/printf.c 5901672228f305f7d493cbc4e7d76a61a5caecdbc1cd06b1f9ec42ea4265cf8d
|
||||
F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
|
||||
F src/resolve.c efbb58ab3bf5ce041a8529f08866811148fca2ee079d5b919c7681319b5e5ebc
|
||||
F src/resolve.c 7f8954f49ddf18d16a13866593eb4f51a6deba8b30b2d877e27ef1b385cd94db
|
||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||
F src/select.c 6b33d8197dad64015aca2031ee7ae67968c1532e812662fbce2406b39f46c278
|
||||
F src/select.c 6164779bdafadf23f506e87224095b73f27be519b242579bd9d24a6d6a53d9fb
|
||||
F src/shell.c.in ac685e63c506fb2e39375c83347c88bff84dc48fa5d6a59f508d7d67951693a0
|
||||
F src/sqlite.h.in 4e977a5e2ed1a9e8987ff65a2cab5f99a4298ebf040ea5ff636e1753339ff45a
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510
|
||||
F src/sqliteInt.h 398111a3db45b92158b81d1fb9d7add8907704e83d4190a3560ebcf2bae6a151
|
||||
F src/sqliteInt.h e62e6eab356e01a8cf1c88d0a2ec7e403e5d3b141b4816ec0b5ea23acd1fcd14
|
||||
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
|
||||
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
@ -614,7 +614,7 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c bae853ad129d1129c063de8630a3e99e306283bc40146f359b1bb91be2c08f1e
|
||||
F src/treeview.c f8eaf6e9a237e7666ae18b47d7ff5a9091afdc5c2d2a08a493d41be24ce70c46
|
||||
F src/treeview.c e80a6126f82c0cd0a939aa617c428329c6e2c3351b7d4dabb8b8a83c9b4e7696
|
||||
F src/trigger.c 3f612ce5f0858b6c23460a3c799d01f408b49b0b29d931d8b8e6fc224a8667de
|
||||
F src/update.c 69c4c10bc6873a80c0a77cb578f9fc60ee90003d03f9530bc3370fa24615772d
|
||||
F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937
|
||||
@ -627,7 +627,7 @@ F src/vdbeInt.h 38206c8dd6b60ff03d9fd4f626b1b4fd0eef7cdc44f2fc2c1973b0f932a3f26b
|
||||
F src/vdbeapi.c aa5aaf2c37676b83af5724c6cd8207a3064ed46a217fd180957f75ac84f7a2a5
|
||||
F src/vdbeaux.c 897912feb91ec3cd8dedc3fce21d192fd6d37d299538a13d9d93100b22e4d4a0
|
||||
F src/vdbeblob.c 292e96c01c4219fca71d74e1002906d43eb232af4bd83f7552a3faec741f3eb8
|
||||
F src/vdbemem.c 51cb5d507a0f62cbf2ab6dd1f2042873807146d05920c6943955ecf4cec6529f
|
||||
F src/vdbemem.c 8be0af1060012520381d3296fcb1718e80cd5b99ce04f51f7e1c4dba4072caac
|
||||
F src/vdbesort.c cd5130f683706c1a43e165a74187745fb3351cb56052cf9dc91de820634bbde2
|
||||
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
|
||||
F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
|
||||
@ -635,12 +635,12 @@ F src/vtab.c 3a6640d86d5dfae8f69715a1ee7405bb96d8982b39655b91c1f3648baae476a8
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 2be08331d798237ad5d7ae0b252700ffb2b63189cb18d993496d009a93e2f81c
|
||||
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
|
||||
F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac
|
||||
F src/where.c f71086505c5db78209574eaffdb01c4e7beb745873ccba2cfcd4822232ef4e39
|
||||
F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
|
||||
F src/where.c 56e1902e9b91fb1fe159181a21c34abd59a01e2cb8f5ef4c3e478d32c5d838df
|
||||
F src/whereInt.h 9248161dd004f625ce5d3841ca9b99fed3fc8d61522cf76340fc5217dbe1375b
|
||||
F src/wherecode.c af9bc0608f07f6582affb0e4f30f95815cca080feb5359c2acc4558b48500604
|
||||
F src/whereexpr.c 108a89887ea4943c2573f43c0b37342e4a23afa215d88f5d137d205c7fd2f66a
|
||||
F src/window.c 7bb95e7e6e1c7279ccaf1784c06ccf55c33303c1c2dc37aa4b13fab312b7bd50
|
||||
F src/wherecode.c 6721f5de1d74d952b473c3f2473ea36b4a3aafed2c0ae0edb02c7e8a6b908d43
|
||||
F src/whereexpr.c 01d87dc0d5fb0a18100a65ba5466e399f2b8d96b3ec8a6056cf2aac10436afa5
|
||||
F src/window.c 0dff6fedf61493490d21ced5d7a7b4321d4c0db6c8123f0179c46080a860850a
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
|
||||
F test/affinity3.test eecb0dabee4b7765a8465439d5e99429279ffba23ca74a7eae270a452799f9e7
|
||||
@ -1929,7 +1929,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 9af863f065e0bef491c2ab7525194505f9516f4e6dfc789d2e3a9d2c2438533a
|
||||
R eeba287e3c7adfad939bd3178ae64a7a
|
||||
P f85cb287c52baa729aeb223038e979a3b74a1eb3d97bf59c01f5417998204f84
|
||||
R d1a38de85ec9395d66459f512bc9b39f
|
||||
U drh
|
||||
Z ead3dbf79919d143e014b4c2002fbeb0
|
||||
Z a07d4736a8e9c697e3914dd4948a3735
|
||||
|
@ -1 +1 @@
|
||||
f85cb287c52baa729aeb223038e979a3b74a1eb3d97bf59c01f5417998204f84
|
||||
8eaa1d4a98b24adf245bbd2fe9212aa6a924a0f09c445906d7f87574f36a7423
|
104
src/expr.c
104
src/expr.c
@ -57,7 +57,7 @@ char sqlite3ExprAffinity(const Expr *pExpr){
|
||||
return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
|
||||
}
|
||||
if( op==TK_SELECT ){
|
||||
assert( pExpr->flags&EP_xIsSelect );
|
||||
assert( ExprUseXSelect(pExpr) );
|
||||
assert( pExpr->x.pSelect!=0 );
|
||||
assert( pExpr->x.pSelect->pEList!=0 );
|
||||
assert( pExpr->x.pSelect->pEList->a[0].pExpr!=0 );
|
||||
@ -70,7 +70,7 @@ char sqlite3ExprAffinity(const Expr *pExpr){
|
||||
}
|
||||
#endif
|
||||
if( op==TK_SELECT_COLUMN ){
|
||||
assert( pExpr->pLeft->flags&EP_xIsSelect );
|
||||
assert( pExpr->pLeft!=0 && ExprUseXSelect(pExpr->pLeft) );
|
||||
assert( pExpr->iColumn < pExpr->iTable );
|
||||
assert( pExpr->iTable==pExpr->pLeft->x.pSelect->pEList->nExpr );
|
||||
return sqlite3ExprAffinity(
|
||||
@ -78,6 +78,7 @@ char sqlite3ExprAffinity(const Expr *pExpr){
|
||||
);
|
||||
}
|
||||
if( op==TK_VECTOR ){
|
||||
assert( ExprUseXList(pExpr) );
|
||||
return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr);
|
||||
}
|
||||
return pExpr->affExpr;
|
||||
@ -137,7 +138,7 @@ Expr *sqlite3ExprSkipCollate(Expr *pExpr){
|
||||
Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
|
||||
while( pExpr && ExprHasProperty(pExpr, EP_Skip|EP_Unlikely) ){
|
||||
if( ExprHasProperty(pExpr, EP_Unlikely) ){
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
assert( ExprUseXList(pExpr) );
|
||||
assert( pExpr->x.pList->nExpr>0 );
|
||||
assert( pExpr->op==TK_FUNCTION );
|
||||
pExpr = pExpr->x.pList->a[0].pExpr;
|
||||
@ -187,6 +188,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
|
||||
continue;
|
||||
}
|
||||
if( op==TK_VECTOR ){
|
||||
assert( ExprUseXList(p) );
|
||||
p = p->x.pList->a[0].pExpr;
|
||||
continue;
|
||||
}
|
||||
@ -201,11 +203,9 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
|
||||
}else{
|
||||
Expr *pNext = p->pRight;
|
||||
/* The Expr.x union is never used at the same time as Expr.pRight */
|
||||
assert( ExprUseXList(p) );
|
||||
assert( p->x.pList==0 || p->pRight==0 );
|
||||
if( p->x.pList!=0
|
||||
&& !db->mallocFailed
|
||||
&& ALWAYS(!ExprHasProperty(p, EP_xIsSelect))
|
||||
){
|
||||
if( p->x.pList!=0 && !db->mallocFailed ){
|
||||
int i;
|
||||
for(i=0; ALWAYS(i<p->x.pList->nExpr); i++){
|
||||
if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){
|
||||
@ -288,7 +288,7 @@ static char comparisonAffinity(const Expr *pExpr){
|
||||
aff = sqlite3ExprAffinity(pExpr->pLeft);
|
||||
if( pExpr->pRight ){
|
||||
aff = sqlite3CompareAffinity(pExpr->pRight, aff);
|
||||
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
}else if( ExprUseXSelect(pExpr) ){
|
||||
aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
|
||||
}else if( aff==0 ){
|
||||
aff = SQLITE_AFF_BLOB;
|
||||
@ -428,8 +428,10 @@ int sqlite3ExprVectorSize(const Expr *pExpr){
|
||||
u8 op = pExpr->op;
|
||||
if( op==TK_REGISTER ) op = pExpr->op2;
|
||||
if( op==TK_VECTOR ){
|
||||
assert( ExprUseXList(pExpr) );
|
||||
return pExpr->x.pList->nExpr;
|
||||
}else if( op==TK_SELECT ){
|
||||
assert( ExprUseXSelect(pExpr) );
|
||||
return pExpr->x.pSelect->pEList->nExpr;
|
||||
}else{
|
||||
return 1;
|
||||
@ -456,8 +458,10 @@ Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){
|
||||
if( sqlite3ExprIsVector(pVector) ){
|
||||
assert( pVector->op2==0 || pVector->op==TK_REGISTER );
|
||||
if( pVector->op==TK_SELECT || pVector->op2==TK_SELECT ){
|
||||
assert( ExprUseXSelect(pVector) );
|
||||
return pVector->x.pSelect->pEList->a[i].pExpr;
|
||||
}else{
|
||||
assert( ExprUseXList(pVector) );
|
||||
return pVector->x.pList->a[i].pExpr;
|
||||
}
|
||||
}
|
||||
@ -493,7 +497,7 @@ Expr *sqlite3ExprForVectorField(
|
||||
){
|
||||
Expr *pRet;
|
||||
if( pVector->op==TK_SELECT ){
|
||||
assert( pVector->flags & EP_xIsSelect );
|
||||
assert( ExprUseXSelect(pVector) );
|
||||
/* The TK_SELECT_COLUMN Expr node:
|
||||
**
|
||||
** pLeft: pVector containing TK_SELECT. Not deleted.
|
||||
@ -518,7 +522,9 @@ Expr *sqlite3ExprForVectorField(
|
||||
}
|
||||
}else{
|
||||
if( pVector->op==TK_VECTOR ){
|
||||
Expr **ppVector = &pVector->x.pList->a[iField].pExpr;
|
||||
Expr **ppVector;
|
||||
assert( ExprUseXList(pVector) );
|
||||
ppVector = &pVector->x.pList->a[iField].pExpr;
|
||||
pVector = *ppVector;
|
||||
if( IN_RENAME_OBJECT ){
|
||||
/* This must be a vector UPDATE inside a trigger */
|
||||
@ -582,10 +588,12 @@ static int exprVectorRegister(
|
||||
return pVector->iTable+iField;
|
||||
}
|
||||
if( op==TK_SELECT ){
|
||||
assert( ExprUseXSelect(pVector) );
|
||||
*ppExpr = pVector->x.pSelect->pEList->a[iField].pExpr;
|
||||
return regSelect+iField;
|
||||
}
|
||||
if( op==TK_VECTOR ){
|
||||
assert( ExprUseXList(pVector) );
|
||||
*ppExpr = pVector->x.pList->a[iField].pExpr;
|
||||
return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree);
|
||||
}
|
||||
@ -760,7 +768,7 @@ static void exprSetHeight(Expr *p){
|
||||
int nHeight = 0;
|
||||
heightOfExpr(p->pLeft, &nHeight);
|
||||
heightOfExpr(p->pRight, &nHeight);
|
||||
if( ExprHasProperty(p, EP_xIsSelect) ){
|
||||
if( ExprUseXSelect(p) ){
|
||||
heightOfSelect(p->x.pSelect, &nHeight);
|
||||
}else if( p->x.pList ){
|
||||
heightOfExprList(p->x.pList, &nHeight);
|
||||
@ -799,7 +807,7 @@ int sqlite3SelectExprHeight(const Select *p){
|
||||
*/
|
||||
void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
|
||||
if( pParse->nErr ) return;
|
||||
if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){
|
||||
if( p && ExprUseXList(p) && p->x.pList ){
|
||||
p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
|
||||
}
|
||||
}
|
||||
@ -983,13 +991,20 @@ Select *sqlite3ExprListToValues(Parse *pParse, int nElem, ExprList *pEList){
|
||||
for(ii=0; ii<pEList->nExpr; ii++){
|
||||
Select *pSel;
|
||||
Expr *pExpr = pEList->a[ii].pExpr;
|
||||
int nExprElem = (pExpr->op==TK_VECTOR ? pExpr->x.pList->nExpr : 1);
|
||||
int nExprElem;
|
||||
if( pExpr->op==TK_VECTOR ){
|
||||
assert( ExprUseXList(pExpr) );
|
||||
nExprElem = pExpr->x.pList->nExpr;
|
||||
}else{
|
||||
nExprElem = 1;
|
||||
}
|
||||
if( nExprElem!=nElem ){
|
||||
sqlite3ErrorMsg(pParse, "IN(...) element has %d term%s - expected %d",
|
||||
nExprElem, nExprElem>1?"s":"", nElem
|
||||
);
|
||||
break;
|
||||
}
|
||||
assert( ExprUseXList(pExpr) );
|
||||
pSel = sqlite3SelectNew(pParse, pExpr->x.pList, 0, 0, 0, 0, 0, SF_Values,0);
|
||||
pExpr->x.pList = 0;
|
||||
if( pSel ){
|
||||
@ -1059,7 +1074,7 @@ Expr *sqlite3ExprFunction(
|
||||
}
|
||||
pNew->x.pList = pList;
|
||||
ExprSetProperty(pNew, EP_HasFunc);
|
||||
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
|
||||
assert( ExprUseXList(pNew) );
|
||||
sqlite3ExprSetHeightAndFlags(pParse, pNew);
|
||||
if( eDistinct==SF_Distinct ) ExprSetProperty(pNew, EP_Distinct);
|
||||
return pNew;
|
||||
@ -1195,17 +1210,18 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
|
||||
if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){
|
||||
assert( p->pLeft==0 );
|
||||
assert( p->pRight==0 );
|
||||
assert( p->x.pSelect==0 );
|
||||
assert( !ExprUseXSelect(p) || p->x.pSelect==0 );
|
||||
assert( !ExprUseXList(p) || p->x.pList==0 );
|
||||
}
|
||||
#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 );
|
||||
assert( (ExprUseXList(p) && p->x.pList==0) || p->pRight==0 );
|
||||
if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
|
||||
if( p->pRight ){
|
||||
assert( !ExprHasProperty(p, EP_WinFunc) );
|
||||
sqlite3ExprDeleteNN(db, p->pRight);
|
||||
}else if( ExprHasProperty(p, EP_xIsSelect) ){
|
||||
}else if( ExprUseXSelect(p) ){
|
||||
assert( !ExprHasProperty(p, EP_WinFunc) );
|
||||
sqlite3SelectDelete(db, p->x.pSelect);
|
||||
}else{
|
||||
@ -1436,7 +1452,7 @@ static Expr *exprDup(sqlite3 *db, const 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) ){
|
||||
if( ExprUseXSelect(p) ){
|
||||
pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags);
|
||||
}else{
|
||||
pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags);
|
||||
@ -2285,7 +2301,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( ExprUseXSelect(pExpr) ){
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
@ -2512,7 +2528,7 @@ static Select *isCandidateForInOpt(const Expr *pX){
|
||||
ExprList *pEList;
|
||||
Table *pTab;
|
||||
int i;
|
||||
if( !ExprHasProperty(pX, EP_xIsSelect) ) return 0; /* Not a subquery */
|
||||
if( !ExprUseXSelect(pX) ) 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 */
|
||||
@ -2683,7 +2699,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 && ExprUseXSelect(pX) ){
|
||||
int i;
|
||||
ExprList *pEList = pX->x.pSelect->pEList;
|
||||
for(i=0; i<pEList->nExpr; i++){
|
||||
@ -2839,7 +2855,7 @@ int sqlite3FindInIndex(
|
||||
*/
|
||||
if( eType==0
|
||||
&& (inFlags & IN_INDEX_NOOP_OK)
|
||||
&& !ExprHasProperty(pX, EP_xIsSelect)
|
||||
&& ExprUseXList(pX)
|
||||
&& (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2)
|
||||
){
|
||||
eType = IN_INDEX_NOOP;
|
||||
@ -2887,7 +2903,7 @@ int sqlite3FindInIndex(
|
||||
static char *exprINAffinity(Parse *pParse, const Expr *pExpr){
|
||||
Expr *pLeft = pExpr->pLeft;
|
||||
int nVal = sqlite3ExprVectorSize(pLeft);
|
||||
Select *pSelect = (pExpr->flags & EP_xIsSelect) ? pExpr->x.pSelect : 0;
|
||||
Select *pSelect = ExprUseXSelect(pExpr) ? pExpr->x.pSelect : 0;
|
||||
char *zRet;
|
||||
|
||||
assert( pExpr->op==TK_IN );
|
||||
@ -2937,7 +2953,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( ExprUseXSelect(pExpr) ){
|
||||
sqlite3SubselectError(pParse, pExpr->x.pSelect->pEList->nExpr, 1);
|
||||
}else
|
||||
#endif
|
||||
@ -3001,7 +3017,7 @@ void sqlite3CodeRhsOfIN(
|
||||
*/
|
||||
if( ExprHasProperty(pExpr, EP_Subrtn) ){
|
||||
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
if( ExprUseXSelect(pExpr) ){
|
||||
ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d",
|
||||
pExpr->x.pSelect->selId));
|
||||
}
|
||||
@ -3033,7 +3049,7 @@ void sqlite3CodeRhsOfIN(
|
||||
pExpr->iTable = iTab;
|
||||
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, nVal);
|
||||
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
if( ExprUseXSelect(pExpr) ){
|
||||
VdbeComment((v, "Result of SELECT %u", pExpr->x.pSelect->selId));
|
||||
}else{
|
||||
VdbeComment((v, "RHS of IN operator"));
|
||||
@ -3041,7 +3057,7 @@ void sqlite3CodeRhsOfIN(
|
||||
#endif
|
||||
pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nVal, 1);
|
||||
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
if( ExprUseXSelect(pExpr) ){
|
||||
/* Case 1: expr IN (SELECT ...)
|
||||
**
|
||||
** Generate code to write the results of the select into the temporary
|
||||
@ -3175,7 +3191,7 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
|
||||
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( ExprUseXSelect(pExpr) );
|
||||
pSel = pExpr->x.pSelect;
|
||||
|
||||
/* If this routine has already been coded, then invoke it as a
|
||||
@ -3283,7 +3299,7 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
|
||||
*/
|
||||
int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){
|
||||
int nVector = sqlite3ExprVectorSize(pIn->pLeft);
|
||||
if( (pIn->flags & EP_xIsSelect)!=0 && !pParse->db->mallocFailed ){
|
||||
if( ExprUseXSelect(pIn) && !pParse->db->mallocFailed ){
|
||||
if( nVector!=pIn->x.pSelect->pEList->nExpr ){
|
||||
sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector);
|
||||
return 1;
|
||||
@ -3417,13 +3433,15 @@ static void sqlite3ExprCodeIN(
|
||||
** This is step (1) in the in-operator.md optimized algorithm.
|
||||
*/
|
||||
if( eType==IN_INDEX_NOOP ){
|
||||
ExprList *pList = pExpr->x.pList;
|
||||
CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
|
||||
ExprList *pList;
|
||||
CollSeq *pColl;
|
||||
int labelOk = sqlite3VdbeMakeLabel(pParse);
|
||||
int r2, regToFree;
|
||||
int regCkNull = 0;
|
||||
int ii;
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
assert( ExprUseXList(pExpr) );
|
||||
pList = pExpr->x.pList;
|
||||
pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
|
||||
if( destIfNull!=destIfFalse ){
|
||||
regCkNull = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull);
|
||||
@ -3809,6 +3827,7 @@ static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){
|
||||
int i;
|
||||
iResult = pParse->nMem+1;
|
||||
pParse->nMem += nResult;
|
||||
assert( ExprUseXList(p) );
|
||||
for(i=0; i<nResult; i++){
|
||||
sqlite3ExprCodeFactorable(pParse, p->x.pList->a[i].pExpr, i+iResult);
|
||||
}
|
||||
@ -4315,8 +4334,8 @@ expr_code_doover:
|
||||
** multiple times if we know they always give the same result */
|
||||
return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
|
||||
}
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
assert( !ExprHasProperty(pExpr, EP_TokenOnly) );
|
||||
assert( ExprUseXList(pExpr) );
|
||||
pFarg = pExpr->x.pList;
|
||||
nFarg = pFarg ? pFarg->nExpr : 0;
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
@ -4435,7 +4454,10 @@ expr_code_doover:
|
||||
testcase( op==TK_SELECT );
|
||||
if( pParse->db->mallocFailed ){
|
||||
return 0;
|
||||
}else if( op==TK_SELECT && (nCol = pExpr->x.pSelect->pEList->nExpr)!=1 ){
|
||||
}else if( op==TK_SELECT
|
||||
&& ALWAYS( ExprUseXSelect(pExpr) )
|
||||
&& (nCol = pExpr->x.pSelect->pEList->nExpr)!=1
|
||||
){
|
||||
sqlite3SubselectError(pParse, nCol, 1);
|
||||
}else{
|
||||
return sqlite3CodeSubselect(pParse, pExpr);
|
||||
@ -4607,7 +4629,7 @@ expr_code_doover:
|
||||
Expr *pDel = 0;
|
||||
sqlite3 *db = pParse->db;
|
||||
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
|
||||
assert( ExprUseXList(pExpr) && pExpr->x.pList!=0 );
|
||||
assert(pExpr->x.pList->nExpr > 0);
|
||||
pEList = pExpr->x.pList;
|
||||
aListelem = pEList->a;
|
||||
@ -4952,7 +4974,7 @@ static void exprCodeBetween(
|
||||
memset(&compRight, 0, sizeof(Expr));
|
||||
memset(&exprAnd, 0, sizeof(Expr));
|
||||
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
assert( ExprUseXList(pExpr) );
|
||||
pDel = sqlite3ExprDup(db, pExpr->pLeft, 0);
|
||||
if( db->mallocFailed==0 ){
|
||||
exprAnd.op = TK_AND;
|
||||
@ -5539,12 +5561,13 @@ static int exprImpliesNotNull(
|
||||
switch( p->op ){
|
||||
case TK_IN: {
|
||||
if( seenNot && ExprHasProperty(p, EP_xIsSelect) ) return 0;
|
||||
assert( ExprHasProperty(p,EP_xIsSelect)
|
||||
|| (p->x.pList!=0 && p->x.pList->nExpr>0) );
|
||||
assert( ExprUseXSelect(p) || (p->x.pList!=0 && p->x.pList->nExpr>0) );
|
||||
return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
|
||||
}
|
||||
case TK_BETWEEN: {
|
||||
ExprList *pList = p->x.pList;
|
||||
ExprList *pList;
|
||||
assert( ExprUseXList(p) );
|
||||
pList = p->x.pList;
|
||||
assert( pList!=0 );
|
||||
assert( pList->nExpr==2 );
|
||||
if( seenNot ) return 0;
|
||||
@ -5908,6 +5931,7 @@ int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
|
||||
cnt.iSrcInner = (pSrcList&&pSrcList->nSrc)?pSrcList->a[0].iCursor:0x7FFFFFFF;
|
||||
cnt.nThis = 0;
|
||||
cnt.nOther = 0;
|
||||
assert( ExprUseXList(pExpr) );
|
||||
sqlite3WalkExprList(&w, pExpr->x.pList);
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
if( ExprHasProperty(pExpr, EP_WinFunc) ){
|
||||
@ -6112,7 +6136,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
||||
pItem = &pAggInfo->aFunc[i];
|
||||
pItem->pFExpr = pExpr;
|
||||
pItem->iMem = ++pParse->nMem;
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
assert( ExprUseUToken(pExpr) );
|
||||
pItem->pFunc = sqlite3FindFunction(pParse->db,
|
||||
pExpr->u.zToken,
|
||||
pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0);
|
||||
|
@ -1935,10 +1935,10 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
|
||||
int nExpr;
|
||||
assert( pExpr!=0 );
|
||||
assert( pExpr->op==TK_FUNCTION );
|
||||
assert( ExprUseXList(pExpr) );
|
||||
if( !pExpr->x.pList ){
|
||||
return 0;
|
||||
}
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
nExpr = pExpr->x.pList->nExpr;
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0);
|
||||
|
@ -518,8 +518,8 @@ static int lookupName(
|
||||
){
|
||||
Expr *pOrig;
|
||||
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
|
||||
assert( pExpr->x.pList==0 );
|
||||
assert( pExpr->x.pSelect==0 );
|
||||
assert( ExprUseXList(pExpr)==0 || pExpr->x.pList==0 );
|
||||
assert( ExprUseXSelect(pExpr)==0 || pExpr->x.pSelect==0 );
|
||||
pOrig = pEList->a[j].pExpr;
|
||||
if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){
|
||||
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
|
||||
@ -1120,7 +1120,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
#endif
|
||||
case TK_IN: {
|
||||
testcase( pExpr->op==TK_IN );
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
if( ExprUseXSelect(pExpr) ){
|
||||
int nRef = pNC->nRef;
|
||||
testcase( pNC->ncFlags & NC_IsCheck );
|
||||
testcase( pNC->ncFlags & NC_PartIdx );
|
||||
@ -1177,6 +1177,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
assert( pExpr->pLeft!=0 );
|
||||
nLeft = sqlite3ExprVectorSize(pExpr->pLeft);
|
||||
if( pExpr->op==TK_BETWEEN ){
|
||||
assert( ExprUseXList(pExpr) );
|
||||
nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[0].pExpr);
|
||||
if( nRight==nLeft ){
|
||||
nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr);
|
||||
|
58
src/select.c
58
src/select.c
@ -391,10 +391,13 @@ void sqlite3SetJoinExpr(Expr *p, int iTable){
|
||||
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
|
||||
ExprSetVVAProperty(p, EP_NoReduce);
|
||||
p->iRightJoinTable = iTable;
|
||||
if( p->op==TK_FUNCTION && p->x.pList ){
|
||||
int i;
|
||||
for(i=0; i<p->x.pList->nExpr; i++){
|
||||
sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable);
|
||||
if( p->op==TK_FUNCTION ){
|
||||
assert( ExprUseXList(p) );
|
||||
if( p->x.pList ){
|
||||
int i;
|
||||
for(i=0; i<p->x.pList->nExpr; i++){
|
||||
sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3SetJoinExpr(p->pLeft, iTable);
|
||||
@ -417,10 +420,13 @@ static void unsetJoinExpr(Expr *p, int iTable){
|
||||
if( p->op==TK_COLUMN && p->iTable==iTable ){
|
||||
ExprClearProperty(p, EP_CanBeNull);
|
||||
}
|
||||
if( p->op==TK_FUNCTION && p->x.pList ){
|
||||
int i;
|
||||
for(i=0; i<p->x.pList->nExpr; i++){
|
||||
unsetJoinExpr(p->x.pList->a[i].pExpr, iTable);
|
||||
if( p->op==TK_FUNCTION ){
|
||||
assert( ExprUseXList(p) );
|
||||
if( p->x.pList ){
|
||||
int i;
|
||||
for(i=0; i<p->x.pList->nExpr; i++){
|
||||
unsetJoinExpr(p->x.pList->a[i].pExpr, iTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
unsetJoinExpr(p->pLeft, iTable);
|
||||
@ -1866,9 +1872,11 @@ static const char *columnTypeImpl(
|
||||
** statement.
|
||||
*/
|
||||
NameContext sNC;
|
||||
Select *pS = pExpr->x.pSelect;
|
||||
Expr *p = pS->pEList->a[0].pExpr;
|
||||
assert( ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
Select *pS;
|
||||
Expr *p;
|
||||
assert( ExprUseXSelect(pExpr) );
|
||||
pS = pExpr->x.pSelect;
|
||||
p = pS->pEList->a[0].pExpr;
|
||||
sNC.pSrcList = pS->pSrc;
|
||||
sNC.pNext = pNC;
|
||||
sNC.pParse = pNC->pParse;
|
||||
@ -3675,7 +3683,7 @@ static Expr *substExpr(
|
||||
}
|
||||
pExpr->pLeft = substExpr(pSubst, pExpr->pLeft);
|
||||
pExpr->pRight = substExpr(pSubst, pExpr->pRight);
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
if( ExprUseXSelect(pExpr) ){
|
||||
substSelect(pSubst, pExpr->x.pSelect, 1);
|
||||
}else{
|
||||
substExprList(pSubst, pExpr->x.pList);
|
||||
@ -4886,7 +4894,7 @@ static int pushDownWhereTerms(
|
||||
*/
|
||||
static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
|
||||
int eRet = WHERE_ORDERBY_NORMAL; /* Return value */
|
||||
ExprList *pEList = pFunc->x.pList; /* Arguments to agg function */
|
||||
ExprList *pEList; /* Arguments to agg function */
|
||||
const char *zFunc; /* Name of aggregate function pFunc */
|
||||
ExprList *pOrderBy;
|
||||
u8 sortFlags = 0;
|
||||
@ -4894,6 +4902,8 @@ static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
|
||||
assert( *ppMinMax==0 );
|
||||
assert( pFunc->op==TK_AGG_FUNCTION );
|
||||
assert( !IsWindowFunc(pFunc) );
|
||||
assert( ExprUseXList(pFunc) );
|
||||
pEList = pFunc->x.pList;
|
||||
if( pEList==0
|
||||
|| pEList->nExpr!=1
|
||||
|| ExprHasProperty(pFunc, EP_WinFunc)
|
||||
@ -5870,7 +5880,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
|
||||
for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
|
||||
if( pFunc->iDistinct>=0 ){
|
||||
Expr *pE = pFunc->pFExpr;
|
||||
assert( !ExprHasProperty(pE, EP_xIsSelect) );
|
||||
assert( ExprUseXList(pE) );
|
||||
if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
|
||||
sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
|
||||
"argument");
|
||||
@ -5895,8 +5905,9 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
|
||||
int i;
|
||||
struct AggInfo_func *pF;
|
||||
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
|
||||
ExprList *pList = pF->pFExpr->x.pList;
|
||||
assert( !ExprHasProperty(pF->pFExpr, EP_xIsSelect) );
|
||||
ExprList *pList;
|
||||
assert( ExprUseXList(pF->pFExpr) );
|
||||
pList = pF->pFExpr->x.pList;
|
||||
sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0);
|
||||
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
|
||||
}
|
||||
@ -5930,9 +5941,10 @@ static void updateAccumulator(
|
||||
int nArg;
|
||||
int addrNext = 0;
|
||||
int regAgg;
|
||||
ExprList *pList = pF->pFExpr->x.pList;
|
||||
assert( !ExprHasProperty(pF->pFExpr, EP_xIsSelect) );
|
||||
ExprList *pList;
|
||||
assert( ExprUseXList(pF->pFExpr) );
|
||||
assert( !IsWindowFunc(pF->pFExpr) );
|
||||
pList = pF->pFExpr->x.pList;
|
||||
if( ExprHasProperty(pF->pFExpr, EP_WinFunc) ){
|
||||
Expr *pFilter = pF->pFExpr->y.pWin->pFilter;
|
||||
if( pAggInfo->nAccumulator
|
||||
@ -6178,8 +6190,9 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
|
||||
if( p->pGroupBy ) return 0;
|
||||
pExpr = p->pEList->a[0].pExpr;
|
||||
if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
assert( ExprUseUToken(pExpr) );
|
||||
if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Is count() */
|
||||
assert( ExprUseXList(pExpr) );
|
||||
if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */
|
||||
if( p->pSrc->nSrc!=1 ) return 0; /* One table in FROM */
|
||||
pSub = p->pSrc->a[0].pSelect;
|
||||
@ -6994,7 +7007,7 @@ int sqlite3Select(
|
||||
}
|
||||
for(i=0; i<pAggInfo->nFunc; i++){
|
||||
Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
assert( ExprUseXList(pExpr) );
|
||||
sNC.ncFlags |= NC_InAggFunc;
|
||||
sqlite3ExprAnalyzeAggList(&sNC, pExpr->x.pList);
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
@ -7049,7 +7062,9 @@ int sqlite3Select(
|
||||
|
||||
if( pAggInfo->nFunc==1
|
||||
&& pAggInfo->aFunc[0].iDistinct>=0
|
||||
&& pAggInfo->aFunc[0].pFExpr->x.pList
|
||||
&& ALWAYS(pAggInfo->aFunc[0].pFExpr!=0)
|
||||
&& ALWAYS(ExprUseXList(pAggInfo->aFunc[0].pFExpr))
|
||||
&& pAggInfo->aFunc[0].pFExpr->x.pList!=0
|
||||
){
|
||||
Expr *pExpr = pAggInfo->aFunc[0].pFExpr->x.pList->a[0].pExpr;
|
||||
pExpr = sqlite3ExprDup(db, pExpr, 0);
|
||||
@ -7370,6 +7385,7 @@ int sqlite3Select(
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
|
||||
}
|
||||
}else if( pAggInfo->nFunc==1 && pAggInfo->aFunc[0].iDistinct>=0 ){
|
||||
assert( ExprUseXList(pAggInfo->aFunc[0].pFExpr) );
|
||||
pDistinct = pAggInfo->aFunc[0].pFExpr->x.pList;
|
||||
distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
|
||||
}
|
||||
|
@ -2886,6 +2886,16 @@ struct Expr {
|
||||
#define ExprAlwaysTrue(E) (((E)->flags&(EP_FromJoin|EP_IsTrue))==EP_IsTrue)
|
||||
#define ExprAlwaysFalse(E) (((E)->flags&(EP_FromJoin|EP_IsFalse))==EP_IsFalse)
|
||||
|
||||
/*
|
||||
** Macros used to ensure that the correct members of unions are accessed.
|
||||
*/
|
||||
#define ExprUseUToken(E) (((E)->flags&EP_IntValue)==0)
|
||||
#define ExprUseUValue(E) (((E)->flags&EP_IntValue)!=0)
|
||||
#define ExprUseXList(E) (((E)->flags&EP_xIsSelect)==0)
|
||||
#define ExprUseXSelect(E) (((E)->flags&EP_xIsSelect)!=0)
|
||||
#define ExprUseYTab(E) ((E)->op==TK_COLUMN)
|
||||
#define ExprUseYWin(E) ((E)->flags&EP_WinFunc)!=0)
|
||||
#define ExprUseYSub(E) ((E)->op==TK_IN||(E)->op==TK_SELECT||(E)->op==TK_EXISTS)
|
||||
|
||||
/* Flags for use with Expr.vvaFlags
|
||||
*/
|
||||
|
@ -583,6 +583,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
pFarg = 0;
|
||||
pWin = 0;
|
||||
}else{
|
||||
assert( ExprUseXList(pExpr) );
|
||||
pFarg = pExpr->x.pList;
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
pWin = ExprHasProperty(pExpr, EP_WinFunc) ? pExpr->y.pWin : 0;
|
||||
@ -622,11 +623,13 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
}
|
||||
#ifndef SQLITE_OMIT_SUBQUERY
|
||||
case TK_EXISTS: {
|
||||
assert( ExprUseXSelect(pExpr) );
|
||||
sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags);
|
||||
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
||||
break;
|
||||
}
|
||||
case TK_SELECT: {
|
||||
assert( ExprUseXSelect(pExpr) );
|
||||
sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags);
|
||||
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
||||
break;
|
||||
@ -634,7 +637,7 @@ 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) ){
|
||||
if( ExprUseXSelect(pExpr) ){
|
||||
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
||||
}else{
|
||||
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
|
||||
@ -655,9 +658,12 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
** Z is stored in pExpr->pList->a[1].pExpr.
|
||||
*/
|
||||
case TK_BETWEEN: {
|
||||
Expr *pX = pExpr->pLeft;
|
||||
Expr *pY = pExpr->x.pList->a[0].pExpr;
|
||||
Expr *pZ = pExpr->x.pList->a[1].pExpr;
|
||||
const Expr *pX, *pY, *pZ;
|
||||
pX = pExpr->pLeft;
|
||||
assert( ExprUseXList(pExpr) );
|
||||
assert( pExpr->x.pList->nExpr==2 );
|
||||
pY = pExpr->x.pList->a[0].pExpr;
|
||||
pZ = pExpr->x.pList->a[1].pExpr;
|
||||
sqlite3TreeViewLine(pView, "BETWEEN");
|
||||
sqlite3TreeViewExpr(pView, pX, 1);
|
||||
sqlite3TreeViewExpr(pView, pY, 1);
|
||||
@ -679,6 +685,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
case TK_CASE: {
|
||||
sqlite3TreeViewLine(pView, "CASE");
|
||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
|
||||
assert( ExprUseXList(pExpr) );
|
||||
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
|
||||
break;
|
||||
}
|
||||
@ -704,6 +711,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
}
|
||||
case TK_VECTOR: {
|
||||
char *z = sqlite3_mprintf("VECTOR%s",zFlgs);
|
||||
assert( ExprUseXList(pExpr) );
|
||||
sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);
|
||||
sqlite3_free(z);
|
||||
break;
|
||||
@ -712,6 +720,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
sqlite3TreeViewLine(pView, "SELECT-COLUMN %d of [0..%d]%s",
|
||||
pExpr->iColumn, pExpr->iTable-1,
|
||||
pExpr->pRight==pExpr->pLeft ? " (SELECT-owner)" : "");
|
||||
assert( ExprUseXSelect(pExpr->pLeft) );
|
||||
sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
|
||||
break;
|
||||
}
|
||||
|
@ -1418,6 +1418,7 @@ static int valueFromFunction(
|
||||
|
||||
assert( pCtx!=0 );
|
||||
assert( (p->flags & EP_TokenOnly)==0 );
|
||||
assert( ExprUseXList(p) );
|
||||
pList = p->x.pList;
|
||||
if( pList ) nVal = pList->nExpr;
|
||||
assert( !ExprHasProperty(p, EP_IntValue) );
|
||||
|
@ -75,7 +75,7 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
|
||||
assert( !ExprHasProperty(pExpr, EP_WinFunc) );
|
||||
pExpr = pExpr->pRight;
|
||||
continue;
|
||||
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
}else if( ExprUseXSelect(pExpr) ){
|
||||
assert( !ExprHasProperty(pExpr, EP_WinFunc) );
|
||||
if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
|
||||
}else{
|
||||
|
13
src/where.c
13
src/where.c
@ -2419,9 +2419,12 @@ 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;
|
||||
if( pRhs->flags & EP_xIsSelect ){
|
||||
Expr *pLhs, *pRhs;
|
||||
|
||||
assert( ExprUseXList(pTerm->pExpr->pLeft) );
|
||||
pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr;
|
||||
pRhs = pTerm->pExpr->pRight;
|
||||
if( ExprUseXSelect(pRhs) ){
|
||||
pRhs = pRhs->x.pSelect->pEList->a[i].pExpr;
|
||||
}else{
|
||||
pRhs = pRhs->x.pList->a[i].pExpr;
|
||||
@ -2582,7 +2585,7 @@ static int whereLoopAddBtreeIndex(
|
||||
|
||||
if( eOp & WO_IN ){
|
||||
Expr *pExpr = pTerm->pExpr;
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
if( ExprUseXSelect(pExpr) ){
|
||||
/* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
|
||||
int i;
|
||||
nIn = 46; assert( 46==sqlite3LogEst(25) );
|
||||
@ -2723,7 +2726,7 @@ static int whereLoopAddBtreeIndex(
|
||||
if( nInMul==0
|
||||
&& pProbe->nSample
|
||||
&& ALWAYS(pNew->u.btree.nEq<=pProbe->nSampleCol)
|
||||
&& ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
|
||||
&& ((eOp & WO_IN)==0 || ExprUseXList(pTerm->pExpr))
|
||||
&& OptimizationEnabled(db, SQLITE_Stat4)
|
||||
){
|
||||
Expr *pExpr = pTerm->pExpr;
|
||||
|
@ -416,13 +416,18 @@ static Expr *removeUnindexableInClauseTerms(
|
||||
Expr *pNew;
|
||||
pNew = sqlite3ExprDup(db, pX, 0);
|
||||
if( db->mallocFailed==0 ){
|
||||
ExprList *pOrigRhs = pNew->x.pSelect->pEList; /* Original unmodified RHS */
|
||||
ExprList *pOrigLhs = pNew->pLeft->x.pList; /* Original unmodified LHS */
|
||||
ExprList *pOrigRhs; /* Original unmodified RHS */
|
||||
ExprList *pOrigLhs; /* Original unmodified LHS */
|
||||
ExprList *pRhs = 0; /* New RHS after modifications */
|
||||
ExprList *pLhs = 0; /* New LHS after mods */
|
||||
int i; /* Loop counter */
|
||||
Select *pSelect; /* Pointer to the SELECT on the RHS */
|
||||
|
||||
assert( ExprUseXSelect(pNew) );
|
||||
pOrigRhs = pNew->x.pSelect->pEList;
|
||||
assert( pNew->pLeft!=0 );
|
||||
assert( ExprUseXList(pNew->pLeft) );
|
||||
pOrigLhs = pNew->pLeft->x.pList;
|
||||
for(i=iEq; i<pLoop->nLTerm; i++){
|
||||
if( pLoop->aLTerm[i]->pExpr==pX ){
|
||||
int iField = pLoop->aLTerm[i]->u.x.iField - 1;
|
||||
@ -540,7 +545,7 @@ static int codeEqualityTerm(
|
||||
}
|
||||
|
||||
iTab = 0;
|
||||
if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){
|
||||
if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
|
||||
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
|
||||
}else{
|
||||
sqlite3 *db = pParse->db;
|
||||
@ -1105,7 +1110,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( ExprUseXSelect(p) ){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int iSelect;
|
||||
assert( p->op==TK_SELECT );
|
||||
@ -1115,7 +1120,9 @@ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
|
||||
#endif
|
||||
{
|
||||
int i;
|
||||
ExprList *pList = p->x.pList;
|
||||
const ExprList *pList;
|
||||
assert( ExprUseXList(p) );
|
||||
pList = p->x.pList;
|
||||
assert( nReg<=pList->nExpr );
|
||||
for(i=0; i<nReg; i++){
|
||||
sqlite3ExprCode(pParse, pList->a[i].pExpr, iReg+i);
|
||||
@ -2461,7 +2468,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
if( pAlt==0 ) continue;
|
||||
if( pAlt->wtFlags & (TERM_CODED) ) continue;
|
||||
if( (pAlt->eOperator & WO_IN)
|
||||
&& (pAlt->pExpr->flags & EP_xIsSelect)
|
||||
&& ExprUseXSelect(pAlt->pExpr)
|
||||
&& (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
|
||||
){
|
||||
continue;
|
||||
|
@ -195,6 +195,7 @@ static int isLikeOrGlob(
|
||||
#ifdef SQLITE_EBCDIC
|
||||
if( *pnoCase ) return 0;
|
||||
#endif
|
||||
assert( ExprUseXList(pExpr) );
|
||||
pList = pExpr->x.pList;
|
||||
pLeft = pList->a[1].pExpr;
|
||||
|
||||
@ -368,6 +369,7 @@ static int isAuxiliaryVtabOperator(
|
||||
Expr *pCol; /* Column reference */
|
||||
int i;
|
||||
|
||||
assert( ExprUseXList(pExpr) );
|
||||
pList = pExpr->x.pList;
|
||||
if( pList==0 || pList->nExpr!=2 ){
|
||||
return 0;
|
||||
@ -873,7 +875,7 @@ static void exprAnalyzeOrTerm(
|
||||
if( pNew ){
|
||||
int idxNew;
|
||||
transferJoinMarkings(pNew, pExpr);
|
||||
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
|
||||
assert( ExprUseXList(pNew) );
|
||||
pNew->x.pList = pList;
|
||||
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
|
||||
testcase( idxNew==0 );
|
||||
@ -1001,6 +1003,7 @@ static int exprMightBeIndexed(
|
||||
assert( TK_IS<TK_GE && TK_ISNULL<TK_GE && TK_IN<TK_GE );
|
||||
assert( op<=TK_GE );
|
||||
if( pExpr->op==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){
|
||||
assert( ExprUseXList(pExpr) );
|
||||
pExpr = pExpr->x.pList->a[0].pExpr;
|
||||
|
||||
}
|
||||
@ -1067,7 +1070,7 @@ static void exprAnalyze(
|
||||
if( op==TK_IN ){
|
||||
assert( pExpr->pRight==0 );
|
||||
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
if( ExprUseXSelect(pExpr) ){
|
||||
pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect);
|
||||
}else{
|
||||
pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList);
|
||||
@ -1103,6 +1106,7 @@ static void exprAnalyze(
|
||||
if( pTerm->u.x.iField>0 ){
|
||||
assert( op==TK_IN );
|
||||
assert( pLeft->op==TK_VECTOR );
|
||||
assert( ExprUseXList(pLeft) );
|
||||
pLeft = pLeft->x.pList->a[pTerm->u.x.iField-1].pExpr;
|
||||
}
|
||||
|
||||
@ -1181,9 +1185,11 @@ static void exprAnalyze(
|
||||
** BETWEEN term is skipped.
|
||||
*/
|
||||
else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){
|
||||
ExprList *pList = pExpr->x.pList;
|
||||
ExprList *pList;
|
||||
int i;
|
||||
static const u8 ops[] = {TK_GE, TK_LE};
|
||||
assert( ExprUseXList(pExpr) );
|
||||
pList = pExpr->x.pList;
|
||||
assert( pList!=0 );
|
||||
assert( pList->nExpr==2 );
|
||||
for(i=0; i<2; i++){
|
||||
@ -1276,6 +1282,7 @@ static void exprAnalyze(
|
||||
const char *zCollSeqName; /* Name of collating sequence */
|
||||
const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC;
|
||||
|
||||
assert( ExprUseXList(pExpr) );
|
||||
pLeft = pExpr->x.pList->a[1].pExpr;
|
||||
pStr2 = sqlite3ExprDup(db, pStr1, 0);
|
||||
assert( pStr1==0 || !ExprHasProperty(pStr1, EP_IntValue) );
|
||||
@ -1380,6 +1387,7 @@ static void exprAnalyze(
|
||||
else if( pExpr->op==TK_IN
|
||||
&& pTerm->u.x.iField==0
|
||||
&& pExpr->pLeft->op==TK_VECTOR
|
||||
&& ALWAYS( ExprUseXSelect(pExpr) )
|
||||
&& pExpr->x.pSelect->pPrior==0
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
&& pExpr->x.pSelect->pWin==0
|
||||
@ -1543,7 +1551,7 @@ 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) ){
|
||||
}else if( ExprUseXSelect(p) ){
|
||||
if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
|
||||
mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
|
||||
}else if( p->x.pList ){
|
||||
|
19
src/window.c
19
src/window.c
@ -1030,7 +1030,9 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
|
||||
** window function - one for the accumulator, another for interim
|
||||
** results. */
|
||||
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
|
||||
ExprList *pArgs = pWin->pOwner->x.pList;
|
||||
ExprList *pArgs;
|
||||
assert( ExprUseXList(pWin->pOwner) );
|
||||
pArgs = pWin->pOwner->x.pList;
|
||||
if( pWin->pFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){
|
||||
selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist);
|
||||
pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
|
||||
@ -1423,8 +1425,11 @@ void sqlite3WindowCodeInit(Parse *pParse, Select *pSelect){
|
||||
** regApp+1: integer value used to ensure keys are unique
|
||||
** regApp+2: output of MakeRecord
|
||||
*/
|
||||
ExprList *pList = pWin->pOwner->x.pList;
|
||||
KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pList, 0, 0);
|
||||
ExprList *pList;
|
||||
KeyInfo *pKeyInfo;
|
||||
assert( ExprUseXList(pWin->pOwner) );
|
||||
pList = pWin->pOwner->x.pList;
|
||||
pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pList, 0, 0);
|
||||
pWin->csrApp = pParse->nTab++;
|
||||
pWin->regApp = pParse->nMem+1;
|
||||
pParse->nMem += 3;
|
||||
@ -1512,7 +1517,9 @@ static void windowCheckValue(Parse *pParse, int reg, int eCond){
|
||||
** with the object passed as the only argument to this function.
|
||||
*/
|
||||
static int windowArgCount(Window *pWin){
|
||||
ExprList *pList = pWin->pOwner->x.pList;
|
||||
const ExprList *pList;
|
||||
assert( ExprUseXList(pWin->pOwner) );
|
||||
pList = pWin->pOwner->x.pList;
|
||||
return (pList ? pList->nExpr : 0);
|
||||
}
|
||||
|
||||
@ -1697,6 +1704,7 @@ static void windowAggStep(
|
||||
int addrIf = 0;
|
||||
if( pWin->pFilter ){
|
||||
int regTmp;
|
||||
assert( ExprUseXList(pWin->pOwner) );
|
||||
assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr );
|
||||
assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 );
|
||||
regTmp = sqlite3GetTempReg(pParse);
|
||||
@ -1710,6 +1718,7 @@ static void windowAggStep(
|
||||
int iOp = sqlite3VdbeCurrentAddr(v);
|
||||
int iEnd;
|
||||
|
||||
assert( ExprUseXList(pWin->pOwner) );
|
||||
nArg = pWin->pOwner->x.pList->nExpr;
|
||||
regArg = sqlite3GetTempRange(pParse, nArg);
|
||||
sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0);
|
||||
@ -1724,6 +1733,7 @@ static void windowAggStep(
|
||||
if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
|
||||
CollSeq *pColl;
|
||||
assert( nArg>0 );
|
||||
assert( ExprUseXList(pWin->pOwner) );
|
||||
pColl = sqlite3ExprNNCollSeq(pParse, pWin->pOwner->x.pList->a[0].pExpr);
|
||||
sqlite3VdbeAddOp4(v, OP_CollSeq, 0,0,0, (const char*)pColl, P4_COLLSEQ);
|
||||
}
|
||||
@ -1909,6 +1919,7 @@ static void windowReturnOneRow(WindowCodeArg *p){
|
||||
|
||||
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
|
||||
FuncDef *pFunc = pWin->pFunc;
|
||||
assert( ExprUseXList(pWin->pOwner) );
|
||||
if( pFunc->zName==nth_valueName
|
||||
|| pFunc->zName==first_valueName
|
||||
){
|
||||
|
Loading…
Reference in New Issue
Block a user