Compare commits

...

8 Commits

Author SHA1 Message Date
drh 8477f7f79c Reduce the size of Expr to 64-bytes. This works somewhat, but there are
test failures.  More importantly, the size reduction from 80- to 64-bytes has
not lowered the schema memory usage, but it has made the code a little bigger
and a little slower.  So the initial evidence is that this Expr refactoring
experiment is not working...

FossilOrigin-Name: 24b0f66ac611e26f55ffeaff459b0d7ab53e6fa8d72765bea77c3b50634357e8
2018-09-19 20:14:48 +00:00
drh ee9d4d7fed Fix an issue in virtual table handling associated with the new Expr.x.pRight
field.

FossilOrigin-Name: 8487f84af00a8afde4ae24c4925e0f8ac9f38e86ea8b453dccedb3ee10f7f667
2018-09-19 17:24:00 +00:00
drh 53872e7259 Make sure Expr.eX changes back to EX_None after Expr.x.pRight is set to NULL
due to an OOM.

FossilOrigin-Name: e4129cd3a04bff314d2318f33d7ca02c05de35d35f6c650dddb5cabc7c430017
2018-09-19 16:35:38 +00:00
drh 3d6bedf14f Reduce the size of Expr from 80 to 72 bytes moving the pRight field inside the
"x" union.  This is an incremental check-in that still has issues.

FossilOrigin-Name: 147c61a6d4b2a17d6c1da3584e3f29f2bc441e81fbea9d19110a9169c38fbd5f
2018-09-19 14:54:38 +00:00
drh 12b0fabde2 Make sure temporary Expr objects are fully initialized prior to sending them
into sqlite3ExprCodeTemp().

FossilOrigin-Name: de02a1d97a860f780d9b75cddf008a8b1824cf0483f7891e6ed55b83e2d32d91
2018-09-19 11:59:15 +00:00
drh 3b3c86ade2 In the Expr object, the Expr.eX field determines what value is stored in the
Expr.x union.  This mostly works, but there are issues identified by valgrind.

FossilOrigin-Name: 8849a463d67d79ec60c74a08835c176c08da651a82731558a1dceac2781cd75d
2018-09-18 21:35:31 +00:00
drh 110e3afd11 Merge all recent trunk enhancements.
FossilOrigin-Name: 655f065404e08083ad5eb9b22a036f410b46eb5eb2bcfb0fbc953b4e152c95e7
2018-09-18 18:08:01 +00:00
drh 35284b6c48 Add assert() statements to sqlite3ExprDelete() that prove various symmetry
properties of the Expr object that might be exploited to make the Expr object
smaller and faster.

FossilOrigin-Name: 81f25d5c84e4d2d0cd3c6a7c105c7c93d310218feeea4e023dbc32e7e96b2a52
2018-07-28 01:30:43 +00:00
20 changed files with 649 additions and 385 deletions
+24 -24
View File
@@ -1,5 +1,5 @@
C Avoid\sincrementing\sthe\sSQLITE_LOOKASIDE_MISS_SIZE\sstat\sbefore\ssqlite3_open()\nreturns.\sFix\stest\sscript\sproblem\sin\slookaside.test.
D 2018-09-18T17:50:34.415
C Reduce\sthe\ssize\sof\sExpr\sto\s64-bytes.\s\sThis\sworks\ssomewhat,\sbut\sthere\sare\ntest\sfailures.\s\sMore\simportantly,\sthe\ssize\sreduction\sfrom\s80-\sto\s64-bytes\shas\nnot\slowered\sthe\sschema\smemory\susage,\sbut\sit\shas\smade\sthe\scode\sa\slittle\sbigger\nand\sa\slittle\sslower.\s\sSo\sthe\sinitial\sevidence\sis\sthat\sthis\sExpr\srefactoring\nexperiment\sis\snot\sworking...
D 2018-09-19T20:14:48.730
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334
@@ -436,9 +436,9 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 2269dd2f37ba963fde4c51e9e83542f126c86a8e10357c17f48137c6bee5299b
F src/alter.c 3a859149c15cc78a446e0d632a1a9d24786e230ed1de53d8b88ca2c96f90ace0
F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9
F src/attach.c 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a
F src/attach.c d06bf7ab9efceb7c679ba8beaeeb3082ce3defde482f54de50ac175469f7c4ca
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 92dc4e104b06d06ffeacbd1a4dc0a520daf37f6156278fb6ece5e90e2ca6b610
F src/delete.c 07a7ecf18a64478be7241cbb332bc26321586384c750e47fb566f678c5aee512
F src/expr.c 5814b4b5d4b9e615faba427a554de5152c972cc0132f6968a13250c07b709372
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c f59253c0be4b1e9dfcb073b6d6d6ab83090ae50c08b5c113b76013c4b157cd6a
F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f
F src/fkey.c 234d4e9fb2a35a11d6ee831dbc19e74fb8bfaf5e09b310ce3cffbf37d6eb57e0
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 96a86b76766af46ac9e64afc1576ea7cb0f7219d2f3a7b6c03bb07043017bdf5
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 adfb08e3e31243433ed60613bd244ba0bef63c80ca0f2fee754db02a831b5811
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
F src/select.c 8afcc2b56a6ef76717bb59b6109cd3de0f6fae2803894d6f806640c0aa24dfac
F src/select.c 6bacf10a3a65b692586e80ffda8114ce485d47b0bc1fe18a001f39c5c054db81
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 5cf4c8f1687b8a2042da2259ee8a5a14bf8aa7914a124afa2010afd2c759ccb2
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 1bc9fc4ebd661bea19b4f39dd32f34b609faf2250112d83d7ffa40ab1c3b386b
F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd
F src/update.c 682f112c49247d2fe5950c9fe2226046c6bc497cf114f74d58766926914216ff
F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
@@ -577,20 +577,20 @@ F src/vdbe.c 80603eb66708c2f27879912a4e9456900e66491c3409ca5e392109114e8f6337
F src/vdbe.h 5081dcc497777efe5e9ebe7330d283a044a005e4bdda2e2e984f03bf89a0d907
F src/vdbeInt.h f1f35f70460698d8f5a2bdef1001114babf318e2983a067804e2ae077d8e9827
F src/vdbeapi.c 2ba821c5929a2769e4b217dd85843479c718b8989d414723ec8af0616a83d611
F src/vdbeaux.c c3c397274380f13db702baa3506ba87379446a4d71135a1177b624f73dd3c830
F src/vdbeaux.c 43ee58196823e17093601388993bbea03456c6ffbbd83d516096af71346d93e3
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
F src/vdbemem.c 81329ab760e4ec0162119d9cd10193e0303c45c5935bb20c7ae9139d44dd6641
F src/vdbesort.c 90aad5a92608f2dd771c96749beabdb562c9d881131a860a7a5bccf66dc3be7f
F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
F src/vtab.c 8665561f244c137a2d17b5c3e5910d7303054fe841c5d510e53f23beb0089594
F src/vtab.c 0d613164d56f43aca041de072ceba541f35fc29eeb7085e69f84829249d7fc46
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 4ba292cadd145b8b77e8b2128a363beff0bd87c7f9abfe090c0948eb0330d727
F src/where.c 33a546a918b0439e3e174351ca00c9158f26d73c5a8bb54c6c3cf5bae20b7499
F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4
F src/wherecode.c 4f88f5b39ad4aeb5bdd47a546d74149bb902ef49ca9f02a45b2a5bd2dd70b6bd
F src/whereexpr.c eb462ebe085f6cbb6bdda797a041fbd7e3724586203344043d1088a2117d8e44
F src/wherecode.c ab5992174e31e30f4624fbd57ddffce63db69c861c09811871e0cbab739a2a91
F src/whereexpr.c c88f2047c493c36a11116b524c0c9b621253f512930386e81ea96309d7740fd6
F src/window.c 4b503da928dace3e845b891381a4d98eeb8c5744313ae3643df8d8d21fdcca65
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
@@ -665,7 +665,7 @@ F test/bestindex1.test 852170bddbb21daa121fabcc274640ff83d7d8705912e8b5fe7ed2c5a
F test/bestindex2.test 9a0ccd320b6525eec3a706aae6cdab7e1b7b5abca75027e39f39f755e76e5928
F test/bestindex3.test 001788a114ad96d81d5154fe77c7f1e26e84b3a2b5635ca29e4f96f6decc534e
F test/bestindex4.test 4cb5ff7dbaebadb87d366f51969271778423b455
F test/bestindex5.test 412b42f8036b28d8b2f3534d89389ad946a4b1a65a12263f51936f7424296f1b
F test/bestindex5.test 0b61fc294997a6b5f869a9f7e111a64c0437b5cef2f6a3d1fb2bba4af6f7c1b0
F test/bestindex6.test d856a9bb63d927493575823eed44053bc36251e241aa364e54d0f2a2d302e1d4
F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
@@ -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 de2e3cbd08c00d235106c040fa472ec267ef8f1ec13c34ed7d16deac8d50b6cc
R 87b8b2ee28b1a1a8366c364e4fdd6314
U dan
Z 971302d914167dfdeae1d53b5caa351e
P 8487f84af00a8afde4ae24c4925e0f8ac9f38e86ea8b453dccedb3ee10f7f667
R dc50e2519bfa1235f8e5a29ec2577516
U drh
Z a9cd90cadb1b1e1e79d944ecc746eecf
+1 -1
View File
@@ -1 +1 @@
e461cb281959d8517296e3e4e934eba8206770b1a592cd7655b6567268da1634
24b0f66ac611e26f55ffeaff459b0d7ab53e6fa8d72765bea77c3b50634357e8
+7 -3
View File
@@ -803,7 +803,8 @@ static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
}else if( pExpr->op==TK_COLUMN
&& pExpr->iColumn==p->iCol
&& p->pTab==pExpr->pTab
&& ALWAYS(pExpr->eX==EX_Tab)
&& p->pTab==pExpr->x.pTab
){
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
}
@@ -1341,8 +1342,11 @@ renameColumnFunc_done:
*/
static int renameTableExprCb(Walker *pWalker, Expr *pExpr){
RenameCtx *p = pWalker->u.pRename;
if( pExpr->op==TK_COLUMN && p->pTab==pExpr->pTab ){
renameTokenFind(pWalker->pParse, p, (void*)&pExpr->pTab);
if( pExpr->op==TK_COLUMN
&& ALWAYS(pExpr->eX==EX_Tab)
&& p->pTab==pExpr->x.pTab
){
renameTokenFind(pWalker->pParse, p, (void*)&pExpr->x.pTab);
}
return WRC_Continue;
}
+13 -7
View File
@@ -564,13 +564,19 @@ 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;
}
if( sqlite3FixExpr(pFix, pExpr->pRight) ){
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;
}
case EX_Right: {
if( sqlite3FixExpr(pFix, pExpr->x.pRight) ) return 1;
break;
}
}
pExpr = pExpr->pLeft;
}
+1 -3
View 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);
}
}
+241 -111
View 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;
@@ -58,11 +58,12 @@ char sqlite3ExprAffinity(Expr *pExpr){
return sqlite3AffinityType(pExpr->u.zToken, 0);
}
#endif
if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){
return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
if( (op==TK_AGG_COLUMN || op==TK_COLUMN)
&& ALWAYS(pExpr->eX==EX_Tab) && pExpr->x.pTab ){
return sqlite3TableColumnAffinity(pExpr->x.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 +109,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;
@@ -143,13 +144,14 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
if( p->flags & EP_Generic ) break;
if( (op==TK_AGG_COLUMN || op==TK_COLUMN
|| op==TK_REGISTER || op==TK_TRIGGER)
&& p->pTab!=0
&& p->eX==EX_Tab
&& p->x.pTab!=0
){
/* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
** a TK_COLUMN but was previously evaluated and cached in a register */
int j = p->iColumn;
if( j>=0 ){
const char *zColl = p->pTab->aCol[j].zColl;
const char *zColl = p->x.pTab->aCol[j].zColl;
pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
}
break;
@@ -166,13 +168,11 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){
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 );
Expr *pNext = 0;
/* p->flags holds EP_Collate and p->pLeft->flags does not. And
** p->x.pSelect cannot. So if p->x.pLeft exists, it must hold at
** least one EP_Collate. Thus the following two ALWAYS. */
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) ){
@@ -180,6 +180,8 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
break;
}
}
}else if( p->eX==EX_Right ){
pNext = p->x.pRight;
}
p = pNext;
}
@@ -258,9 +260,9 @@ static char comparisonAffinity(Expr *pExpr){
pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT );
assert( pExpr->pLeft );
aff = sqlite3ExprAffinity(pExpr->pLeft);
if( pExpr->pRight ){
aff = sqlite3CompareAffinity(pExpr->pRight, aff);
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
if( pExpr->eX==EX_Right ){
aff = sqlite3CompareAffinity(pExpr->x.pRight, aff);
}else if( pExpr->eX==EX_Select ){
aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
}else if( aff==0 ){
aff = SQLITE_AFF_BLOB;
@@ -307,8 +309,12 @@ static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
**
** Argument pRight (but not pLeft) may be a null pointer. In this case,
** it is not considered.
**
** The second form (sqlite3BinaryExprCollSeq()) uses the Expr.pLeft
** and Expr.x.pRight pointer from the second argument instead of separate
** pointers.
*/
CollSeq *sqlite3BinaryCompareCollSeq(
CollSeq *sqlite3ComparisonCollSeq(
Parse *pParse,
Expr *pLeft,
Expr *pRight
@@ -327,6 +333,13 @@ CollSeq *sqlite3BinaryCompareCollSeq(
}
return pColl;
}
CollSeq *sqlite3ComparisonExprCollSeq(Parse *pParse, Expr *pExpr){
if( pExpr->eX==EX_Right ){
return sqlite3ComparisonCollSeq(pParse, pExpr->pLeft, pExpr->x.pRight);
}else{
return sqlite3ComparisonCollSeq(pParse, pExpr->pLeft, 0);
}
}
/*
** Generate code for a comparison operator.
@@ -344,7 +357,7 @@ static int codeCompare(
int addr;
CollSeq *p4;
p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
p4 = sqlite3ComparisonCollSeq(pParse, pLeft, pRight);
p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
(void*)p4, P4_COLLSEQ);
@@ -439,7 +452,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.
@@ -547,7 +560,7 @@ static void codeVectorCompare(
){
Vdbe *v = pParse->pVdbe;
Expr *pLeft = pExpr->pLeft;
Expr *pRight = pExpr->pRight;
Expr *pRight = pExpr->x.pRight;
int nLeft = sqlite3ExprVectorSize(pLeft);
int i;
int regLeft = 0;
@@ -681,12 +694,20 @@ static void heightOfSelect(Select *pSelect, int *pnHeight){
static void exprSetHeight(Expr *p){
int nHeight = 0;
heightOfExpr(p->pLeft, &nHeight);
heightOfExpr(p->pRight, &nHeight);
if( ExprHasProperty(p, EP_xIsSelect) ){
heightOfSelect(p->x.pSelect, &nHeight);
}else if( p->x.pList ){
heightOfExprList(p->x.pList, &nHeight);
p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
switch( p->eX ){
case EX_Select: {
heightOfSelect(p->x.pSelect, &nHeight);
break;
}
case EX_List: {
heightOfExprList(p->x.pList, &nHeight);
p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
break;
}
case EX_Right: {
heightOfExpr(p->x.pRight, &nHeight);
break;
}
}
p->nHeight = nHeight + 1;
}
@@ -700,7 +721,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 +741,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);
}
}
@@ -825,7 +846,9 @@ void sqlite3ExprAttachSubtrees(
sqlite3ExprDelete(db, pRight);
}else{
if( pRight ){
pRoot->pRight = pRight;
assert( pRoot->eX==EX_None );
pRoot->x.pRight = pRight;
pRoot->eX = EX_Right;
pRoot->flags |= EP_Propagate & pRight->flags;
}
if( pLeft ){
@@ -873,9 +896,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 +908,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 +997,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,23 +1096,36 @@ 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 || p->eX==EX_Tab );
}
if( !ExprHasProperty(p, EP_TokenOnly) ){
assert( p->op!=TK_FUNCTION || p->pLeft==0 );
}
if( !ExprHasProperty(p, (EP_TokenOnly|EP_Reduced)) ){
assert( p->pWin==0 || p->pLeft==0 );
assert( p->pWin==0 || p->op==TK_FUNCTION );
}
#endif
if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){
/* The Expr.x union is never used at the same time as Expr.pRight */
assert( p->x.pList==0 || p->pRight==0 );
if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
if( p->pRight ){
sqlite3ExprDeleteNN(db, p->pRight);
}else 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;
}
case EX_Right: {
sqlite3ExprDelete(db, p->x.pRight);
break;
}
}
if( !ExprHasProperty(p, EP_Reduced) ){
sqlite3WindowDelete(db, p->pWin);
@@ -1083,6 +1140,29 @@ void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p ) sqlite3ExprDeleteNN(db, p);
}
void sqlite3ExprClearXUnion(sqlite3 *db, Expr *p){
switch( p->eX ){
case EX_Select: {
sqlite3SelectDelete(db, p->x.pSelect);
break;
}
case EX_List: {
sqlite3ExprListDelete(db, p->x.pList);
break;
}
case EX_Right: {
sqlite3ExprDelete(db, p->x.pRight);
break;
}
}
p->eX = EX_None;
}
void sqlite3ExprAddTab(sqlite3 *db, Expr *pExpr, Table *pTab){
sqlite3ExprClearXUnion(db, pExpr);
pExpr->eX = EX_Tab;
pExpr->x.pTab = pTab;
}
/*
** Return the number of bytes allocated for the expression structure
** passed as the first argument. This is always one of EXPR_FULLSIZE,
@@ -1144,10 +1224,9 @@ static int dupedExprStructSize(Expr *p, int flags){
assert( !ExprHasProperty(p, EP_FromJoin) );
assert( !ExprHasProperty(p, EP_MemToken) );
assert( !ExprHasProperty(p, EP_NoReduce) );
if( p->pLeft || p->x.pList ){
if( p->pLeft || p->eX!=EX_None ){
nSize = EXPR_REDUCEDSIZE | EP_Reduced;
}else{
assert( p->pRight==0 );
nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
}
}
@@ -1185,7 +1264,8 @@ static int dupedExprSize(Expr *p, int flags){
if( p ){
nByte = dupedExprNodeSize(p, flags);
if( flags&EXPRDUP_REDUCE ){
nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags);
nByte += dupedExprSize(p->pLeft, flags);
if( p->eX==EX_Right ) nByte += dupedExprSize(p->x.pRight, flags);
}
}
return nByte;
@@ -1195,7 +1275,7 @@ static int dupedExprSize(Expr *p, int flags){
** This function is similar to sqlite3ExprDup(), except that if pzBuffer
** is not NULL then *pzBuffer is assumed to point to a buffer large enough
** to store the copy of expression p, the copies of p->u.zToken
** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
** (if applicable), and the copies of the p->pLeft and p->x.pRight expressions,
** if any. Before returning, *pzBuffer is set to the first byte past the
** portion of the buffer copied into by this function.
*/
@@ -1248,6 +1328,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 ){
@@ -1257,21 +1339,31 @@ 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;
}
}
}
/* Fill in pNew->pLeft and pNew->pRight. */
/* Fill in pNew->pLeft and pNew->x.pRight. */
if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
zAlloc += dupedExprNodeSize(p, dupFlags);
if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){
pNew->pLeft = p->pLeft ?
exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0;
pNew->pRight = p->pRight ?
exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0;
if( p->eX==EX_Right ){
pNew->x.pRight = exprDup(db, p->x.pRight, EXPRDUP_REDUCE, &zAlloc);
}
}
if( pzBuffer ){
*pzBuffer = zAlloc;
@@ -1287,12 +1379,15 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
if( pNew->op==TK_SELECT_COLUMN ){
pNew->pLeft = p->pLeft;
assert( p->iColumn==0 || p->pRight==0 );
assert( p->pRight==0 || p->pRight==p->pLeft );
assert( p->iColumn==0 || p->eX!=EX_Right );
/* OLD: assert( p->pRight==0 || p->x.pRight==p->pLeft ); */
}else{
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
}
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
if( p->eX==EX_Right ){
pNew->x.pRight = sqlite3ExprDup(db, p->x.pRight, 0);
if( pNew->x.pRight==0 ) pNew->eX = EX_None;
}
}
}
}
@@ -1369,8 +1464,8 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
){
assert( pNewExpr->iColumn==0 || i>0 );
if( pNewExpr->iColumn==0 ){
assert( pOldExpr->pLeft==pOldExpr->pRight );
pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
assert( pOldExpr->pLeft==pOldExpr->x.pRight );
pPriorSelectCol = pNewExpr->pLeft = pNewExpr->x.pRight;
}else{
assert( i>0 );
assert( pItem[-1].pExpr!=0 );
@@ -1616,7 +1711,9 @@ ExprList *sqlite3ExprListAppendVector(
/* Store the SELECT statement in pRight so it will be deleted when
** sqlite3ExprListDelete() is called */
pFirst->pRight = pExpr;
assert( pFirst->eX==EX_None );
pFirst->x.pRight = pExpr;
pFirst->eX = EX_Right;
pExpr = 0;
/* Remember the size of the LHS in iTable so that we can check that
@@ -1954,7 +2051,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;
}
@@ -2088,9 +2185,10 @@ int sqlite3ExprCanBeNull(const Expr *p){
case TK_BLOB:
return 0;
case TK_COLUMN:
assert( p->eX==EX_Tab );
return ExprHasProperty(p, EP_CanBeNull) ||
p->pTab==0 || /* Reference to column of index on expression */
(p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0);
p->x.pTab==0 || /* Reference to column of index on expression */
(p->iColumn>=0 && p->x.pTab->aCol[p->iColumn].notNull==0);
default:
return 1;
}
@@ -2160,8 +2258,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) ){
@@ -2219,7 +2319,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);
@@ -2330,7 +2430,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++){
@@ -2426,7 +2526,7 @@ int sqlite3FindInIndex(
for(i=0; i<nExpr; i++){
Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i);
Expr *pRhs = pEList->a[i].pExpr;
CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
CollSeq *pReq = sqlite3ComparisonCollSeq(pParse, pLhs, pRhs);
int j;
assert( pReq!=0 || pRhs->iColumn==XN_ROWID || pParse->nErr );
@@ -2483,8 +2583,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;
@@ -2499,7 +2599,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 ){
@@ -2532,7 +2632,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 );
@@ -2580,7 +2680,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
@@ -2672,7 +2772,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
@@ -2707,7 +2808,7 @@ int sqlite3CodeSubselect(
assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
for(i=0; i<nVal; i++){
Expr *p = sqlite3VectorFieldSubexpr(pLeft, i);
pKeyInfo->aColl[i] = sqlite3BinaryCompareCollSeq(
pKeyInfo->aColl[i] = sqlite3ComparisonCollSeq(
pParse, p, pEList->a[i].pExpr
);
}
@@ -2801,7 +2902,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",
@@ -2858,7 +2959,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;
@@ -2988,7 +3089,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);
@@ -3377,8 +3478,10 @@ expr_code_doover:
** datatype by applying the Affinity of the table column to the
** constant.
*/
int aff;
int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
int aff = sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
assert( pExpr->eX==EX_Tab );
aff = sqlite3TableColumnAffinity(pExpr->x.pTab, pExpr->iColumn);
if( aff!=SQLITE_AFF_BLOB ){
static const char zAff[] = "B\000C\000D\000E";
assert( SQLITE_AFF_BLOB=='A' );
@@ -3402,7 +3505,8 @@ expr_code_doover:
iTab = pParse->iSelfTab - 1;
}
}
return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
assert( pExpr->eX==EX_Tab );
return sqlite3ExprCodeGetColumn(pParse, pExpr->x.pTab,
pExpr->iColumn, iTab, target,
pExpr->op2);
}
@@ -3491,8 +3595,9 @@ expr_code_doover:
codeVectorCompare(pParse, pExpr, target, op, p5);
}else{
r1 = sqlite3ExprCodeTemp(pParse, pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pLeft, pExpr->pRight, op,
assert( pExpr->eX==EX_Right );
r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, &regFree2);
codeCompare(pParse, pLeft, pExpr->x.pRight, op,
r1, r2, inReg, SQLITE_STOREP2 | p5);
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
@@ -3529,7 +3634,8 @@ expr_code_doover:
assert( TK_RSHIFT==OP_ShiftRight ); testcase( op==TK_RSHIFT );
assert( TK_CONCAT==OP_Concat ); testcase( op==TK_CONCAT );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
assert( pExpr->eX==EX_Right );
r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, &regFree2);
sqlite3VdbeAddOp3(v, op, r2, r1, target);
testcase( regFree1==0 );
testcase( regFree2==0 );
@@ -3548,6 +3654,7 @@ expr_code_doover:
return target;
#endif
}else{
memset(&tempX, 0, sizeof(tempX));
tempX.op = TK_INTEGER;
tempX.flags = EP_IntValue|EP_TokenOnly;
tempX.u.iValue = 0;
@@ -3572,7 +3679,8 @@ expr_code_doover:
int bNormal; /* IS TRUE or IS FALSE */
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
testcase( regFree1==0 );
isTrue = sqlite3ExprTruthValue(pExpr->pRight);
assert( pExpr->eX==EX_Right );
isTrue = sqlite3ExprTruthValue(pExpr->x.pRight);
bNormal = pExpr->op2==TK_IS;
testcase( isTrue && bNormal);
testcase( !isTrue && bNormal);
@@ -3626,7 +3734,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{
@@ -3860,7 +3968,9 @@ expr_code_doover:
** p1==1 -> old.a p1==4 -> new.a
** p1==2 -> old.b p1==5 -> new.b
*/
Table *pTab = pExpr->pTab;
Table *pTab;
assert( pExpr->eX==EX_Tab );
pTab = pExpr->x.pTab;
int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;
assert( pExpr->iTable==0 || pExpr->iTable==1 );
@@ -3869,9 +3979,10 @@ expr_code_doover:
assert( p1>=0 && p1<(pTab->nCol*2+2) );
sqlite3VdbeAddOp2(v, OP_Param, p1, target);
assert( pExpr->eX==EX_Tab );
VdbeComment((v, "r[%d]=%s.%s", target,
(pExpr->iTable ? "new" : "old"),
(pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName)
(pExpr->iColumn<0 ? "rowid" : pExpr->x.pTab->aCol[pExpr->iColumn].zName)
));
#ifndef SQLITE_OMIT_FLOATING_POINT
@@ -3935,8 +4046,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;
@@ -3959,7 +4070,8 @@ expr_code_doover:
for(i=0; i<nExpr-1; i=i+2){
if( pX ){
assert( pTest!=0 );
opCompare.pRight = aListelem[i].pExpr;
opCompare.x.pRight = aListelem[i].pExpr;
opCompare.eX = EX_Right;
}else{
pTest = aListelem[i].pExpr;
}
@@ -4268,17 +4380,20 @@ 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;
exprAnd.pRight = &compRight;
exprAnd.x.pRight = &compRight;
exprAnd.eX = EX_Right;
compLeft.op = TK_GE;
compLeft.pLeft = &exprX;
compLeft.pRight = pExpr->x.pList->a[0].pExpr;
compLeft.x.pRight = pExpr->x.pList->a[0].pExpr;
compLeft.eX = EX_Right;
compRight.op = TK_LE;
compRight.pLeft = &exprX;
compRight.pRight = pExpr->x.pList->a[1].pExpr;
compRight.x.pRight = pExpr->x.pList->a[1].pExpr;
compRight.eX = EX_Right;
exprToRegister(&exprX, exprCodeVector(pParse, &exprX, &regFree1));
if( xJump ){
xJump(pParse, &exprAnd, dest, jumpIfNull);
@@ -4335,14 +4450,16 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
int d2 = sqlite3VdbeMakeLabel(v);
testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
assert( pExpr->eX==EX_Right );
sqlite3ExprIfTrue(pParse, pExpr->x.pRight, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2);
break;
}
case TK_OR: {
testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
assert( pExpr->eX==EX_Right );
sqlite3ExprIfTrue(pParse, pExpr->x.pRight, dest, jumpIfNull);
break;
}
case TK_NOT: {
@@ -4355,7 +4472,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
int isTrue; /* IS TRUE or IS NOT TRUE */
testcase( jumpIfNull==0 );
isNot = pExpr->op2==TK_ISNOT;
isTrue = sqlite3ExprTruthValue(pExpr->pRight);
assert( pExpr->eX==EX_Right );
isTrue = sqlite3ExprTruthValue(pExpr->x.pRight);
testcase( isTrue && isNot );
testcase( !isTrue && isNot );
if( isTrue ^ isNot ){
@@ -4383,8 +4501,9 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
testcase( jumpIfNull==0 );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
assert( pExpr->eX==EX_Right );
r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->x.pRight, op,
r1, r2, dest, jumpIfNull);
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
@@ -4501,14 +4620,16 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
case TK_AND: {
testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
assert( pExpr->eX==EX_Right );
sqlite3ExprIfFalse(pParse, pExpr->x.pRight, dest, jumpIfNull);
break;
}
case TK_OR: {
int d2 = sqlite3VdbeMakeLabel(v);
testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
assert( pExpr->eX==EX_Right );
sqlite3ExprIfFalse(pParse, pExpr->x.pRight, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2);
break;
}
@@ -4522,7 +4643,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
int isTrue; /* IS TRUE or IS NOT TRUE */
testcase( jumpIfNull==0 );
isNot = pExpr->op2==TK_ISNOT;
isTrue = sqlite3ExprTruthValue(pExpr->pRight);
assert( pExpr->eX==EX_Right );
isTrue = sqlite3ExprTruthValue(pExpr->x.pRight);
testcase( isTrue && isNot );
testcase( !isTrue && isNot );
if( isTrue ^ isNot ){
@@ -4553,8 +4675,9 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
testcase( jumpIfNull==0 );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
assert( pExpr->eX==EX_Right );
r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->x.pRight, op,
r1, r2, dest, jumpIfNull);
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
@@ -4730,11 +4853,15 @@ 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_Right ){
if( sqlite3ExprCompare(pParse,pA->x.pRight,pB->x.pRight,iTab) ) return 2;
}
if( pA->eX==EX_List ){
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
}
assert( (combinedFlags & EP_Reduced)==0 );
if( pA->op!=TK_STRING && pA->op!=TK_TRUEFALSE ){
if( pA->iColumn!=pB->iColumn ) return 2;
@@ -4829,9 +4956,10 @@ int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){
if( sqlite3ExprCompare(pParse, pE1, pE2, iTab)==0 ){
return 1;
}
assert( pE2->op!=TK_OR || pE2->eX==EX_Right );
if( pE2->op==TK_OR
&& (sqlite3ExprImpliesExpr(pParse, pE1, pE2->pLeft, iTab)
|| sqlite3ExprImpliesExpr(pParse, pE1, pE2->pRight, iTab) )
|| sqlite3ExprImpliesExpr(pParse, pE1, pE2->x.pRight, iTab) )
){
return 1;
}
@@ -4899,8 +5027,9 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_LE );
testcase( pExpr->op==TK_GT );
testcase( pExpr->op==TK_GE );
if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab))
|| (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab))
assert( pExpr->eX==EX_Right );
if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->x.pTab))
|| (pExpr->x.pRight->op==TK_COLUMN && IsVirtual(pExpr->x.pRight->x.pTab))
){
return WRC_Prune;
}
@@ -5131,7 +5260,8 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
&& (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
){
pCol = &pAggInfo->aCol[k];
pCol->pTab = pExpr->pTab;
assert( pExpr->eX==EX_Tab );
pCol->pTab = pExpr->x.pTab;
pCol->iTable = pExpr->iTable;
pCol->iColumn = pExpr->iColumn;
pCol->iMem = ++pParse->nMem;
@@ -5189,14 +5319,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{
+5 -1
View File
@@ -502,7 +502,11 @@ static Expr *exprTableColumn(
){
Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0);
if( pExpr ){
pExpr->pTab = pTab;
assert( pExpr->eX==EX_None );
if( pTab ){
pExpr->x.pTab = pTab;
pExpr->eX = EX_Tab;
}
pExpr->iTable = iCursor;
pExpr->iColumn = iCol;
}
+1 -1
View 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 ){
+12 -29
View File
@@ -936,12 +936,11 @@ 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->pLeft = 0;
p->pAggInfo = 0;
p->pTab = 0;
p->op2 = 0;
p->iTable = 0;
p->iColumn = 0;
@@ -1052,11 +1051,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);}
@@ -1104,10 +1099,11 @@ expr(A) ::= expr(A) NOT NULL. {A = sqlite3PExpr(pParse,TK_NOTNULL,A,0);}
** unary TK_ISNULL or TK_NOTNULL expression. */
static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){
sqlite3 *db = pParse->db;
if( pA && pY && pY->op==TK_NULL && !IN_RENAME_OBJECT ){
if( pA && pY && pY->op==TK_NULL && pA->eX==EX_Right && !IN_RENAME_OBJECT ){
pA->op = (u8)op;
sqlite3ExprDelete(db, pA->pRight);
pA->pRight = 0;
sqlite3ExprDelete(db, pA->x.pRight);
pA->x.pRight = 0;
pA->eX = EX_None;
}
}
}
@@ -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, $$);}
+36 -27
View File
@@ -164,7 +164,7 @@ int sqlite3MatchSpanName(
** pExpr->iColumn Set to the column number within the table.
** pExpr->op Set to TK_COLUMN.
** pExpr->pLeft Any expression this points to is deleted
** pExpr->pRight Any expression this points to is deleted.
** pExpr->x.pRight Any expression this points to is deleted.
**
** The zDb variable is the name of the database (the "X"). This value may be
** NULL meaning that name is of the form Y.Z or Z. Any available database
@@ -203,7 +203,6 @@ static int lookupName(
/* Initialize the node to no-match */
pExpr->iTable = -1;
pExpr->pTab = 0;
ExprSetVVAProperty(pExpr, EP_NoReduce);
/* Translate the schema name in zDb into a pointer to the corresponding
@@ -265,7 +264,7 @@ static int lookupName(
continue;
}
if( IN_RENAME_OBJECT && pItem->zAlias ){
sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->pTab);
sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->x.pTab);
}
}
if( 0==(cntTab++) ){
@@ -291,13 +290,13 @@ static int lookupName(
}
if( pMatch ){
pExpr->iTable = pMatch->iCursor;
pExpr->pTab = pMatch->pTab;
sqlite3ExprAddTab(db, pExpr, pMatch->pTab);
/* RIGHT JOIN not (yet) supported */
assert( (pMatch->fg.jointype & JT_RIGHT)==0 );
if( (pMatch->fg.jointype & JT_LEFT)!=0 ){
ExprSetProperty(pExpr, EP_CanBeNull);
}
pSchema = pExpr->pTab->pSchema;
pSchema = pExpr->x.pTab->pSchema;
}
} /* if( pSrcList ) */
@@ -354,7 +353,7 @@ static int lookupName(
testcase( iCol==(-1) );
if( IN_RENAME_OBJECT ){
pExpr->iColumn = iCol;
pExpr->pTab = pTab;
sqlite3ExprAddTab(db, pExpr, pTab);
eNewExprOp = TK_COLUMN;
}else{
pExpr->iTable = pNC->uNC.pUpsert->regData + iCol;
@@ -376,7 +375,7 @@ static int lookupName(
testcase( iCol==32 );
pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
}
pExpr->pTab = pTab;
sqlite3ExprAddTab(db, pExpr, pTab);
pExpr->iColumn = (i16)iCol;
eNewExprOp = TK_TRIGGER;
#endif /* SQLITE_OMIT_TRIGGER */
@@ -429,9 +428,7 @@ static int lookupName(
char *zAs = pEList->a[j].zName;
if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
Expr *pOrig;
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
assert( pExpr->x.pList==0 );
assert( pExpr->x.pSelect==0 );
assert( pExpr->pLeft==0 );
pOrig = pEList->a[j].pExpr;
if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
@@ -476,7 +473,6 @@ static int lookupName(
assert( pExpr->op==TK_ID );
if( ExprHasProperty(pExpr,EP_DblQuoted) ){
pExpr->op = TK_STRING;
pExpr->pTab = 0;
return WRC_Prune;
}
if( sqlite3ExprIdToTrueFalse(pExpr) ){
@@ -522,8 +518,11 @@ static int lookupName(
*/
sqlite3ExprDelete(db, pExpr->pLeft);
pExpr->pLeft = 0;
sqlite3ExprDelete(db, pExpr->pRight);
pExpr->pRight = 0;
if( pExpr->eX==EX_Right ){
sqlite3ExprDelete(db, pExpr->x.pRight);
pExpr->x.pRight = 0;
pExpr->eX = EX_None;
}
pExpr->op = eNewExprOp;
ExprSetProperty(pExpr, EP_Leaf);
lookupname_end:
@@ -554,9 +553,9 @@ Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){
Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
if( p ){
struct SrcList_item *pItem = &pSrc->a[iSrc];
p->pTab = pItem->pTab;
sqlite3ExprAddTab(db, p, pItem->pTab);
p->iTable = pItem->iCursor;
if( p->pTab->iPKey==iCol ){
if( p->x.pTab->iPKey==iCol ){
p->iColumn = -1;
}else{
p->iColumn = (ynVar)iCol;
@@ -677,22 +676,24 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}else{
Expr *pLeft = pExpr->pLeft;
notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
pRight = pExpr->pRight;
assert( pExpr->eX==EX_Right );
pRight = pExpr->x.pRight;
if( pRight->op==TK_ID ){
zDb = 0;
}else{
assert( pRight->op==TK_DOT );
assert( pRight->eX==EX_Right );
zDb = pLeft->u.zToken;
pLeft = pRight->pLeft;
pRight = pRight->pRight;
pRight = pRight->x.pRight;
}
zTable = pLeft->u.zToken;
zColumn = pRight->u.zToken;
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight);
}
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, (void*)&pExpr->pTab, (void*)pLeft);
if( pExpr->eX==EX_Tab ){
sqlite3RenameTokenRemap(pParse, (void*)&pExpr->x.pTab,(void*)pLeft);
}
}
}
return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
@@ -701,8 +702,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 +712,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 +884,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);
@@ -898,7 +906,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
assert( !ExprHasProperty(pExpr, EP_Reduced) );
/* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE",
** and "x IS NOT FALSE". */
if( (pRight = pExpr->pRight)->op==TK_ID ){
assert( pExpr->eX==EX_Right );
if( (pRight = pExpr->x.pRight)->op==TK_ID ){
int rc = resolveExprStep(pWalker, pRight);
if( rc==WRC_Abort ) return WRC_Abort;
if( pRight->op==TK_TRUEFALSE ){
@@ -926,8 +935,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr);
}
}else{
assert( pExpr->pRight!=0 );
nRight = sqlite3ExprVectorSize(pExpr->pRight);
assert( pExpr->eX==EX_Right );
nRight = sqlite3ExprVectorSize(pExpr->x.pRight);
}
if( nLeft!=nRight ){
testcase( pExpr->op==TK_EQ );
+68 -41
View File
@@ -390,14 +390,14 @@ static void setJoinExpr(Expr *p, int iTable){
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(p, EP_NoReduce);
p->iRightJoinTable = (i16)iTable;
if( p->op==TK_FUNCTION && p->x.pList ){
if( p->op==TK_FUNCTION && p->eX==EX_List ){
int i;
for(i=0; i<p->x.pList->nExpr; i++){
setJoinExpr(p->x.pList->a[i].pExpr, iTable);
}
}
setJoinExpr(p->pLeft, iTable);
p = p->pRight;
p = p->eX==EX_Right ? p->x.pRight : 0;
}
}
@@ -413,14 +413,14 @@ static void unsetJoinExpr(Expr *p, int iTable){
&& (iTable<0 || p->iRightJoinTable==iTable) ){
ExprClearProperty(p, EP_FromJoin);
}
if( p->op==TK_FUNCTION && p->x.pList ){
if( p->op==TK_FUNCTION && p->eX==EX_List ){
int i;
for(i=0; i<p->x.pList->nExpr; i++){
unsetJoinExpr(p->x.pList->a[i].pExpr, iTable);
}
}
unsetJoinExpr(p->pLeft, iTable);
p = p->pRight;
p = p->eX==EX_Right ? p->x.pRight : 0;
}
}
@@ -803,8 +803,12 @@ static void selectExprDefer(
struct ExprList_item *pItem = &pEList->a[i];
if( pItem->u.x.iOrderByCol==0 ){
Expr *pExpr = pItem->pExpr;
Table *pTab = pExpr->pTab;
if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab)
Table *pTab;
if( pExpr->op==TK_COLUMN
&& pExpr->iColumn>=0
&& ALWAYS(pExpr->eX==EX_Tab)
&& (pTab = pExpr->x.pTab)!=0
&& !IsVirtual(pTab)
&& (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)
){
int j;
@@ -822,16 +826,18 @@ static void selectExprDefer(
pPk = sqlite3PrimaryKeyIndex(pTab);
nKey = pPk->nKeyCol;
}
assert( pExpr->eX==EX_Tab );
for(k=0; k<nKey; k++){
Expr *pNew = sqlite3PExpr(pParse, TK_COLUMN, 0, 0);
if( pNew ){
pNew->iTable = pExpr->iTable;
pNew->pTab = pExpr->pTab;
pNew->eX = EX_Tab;
pNew->x.pTab = pExpr->x.pTab;
pNew->iColumn = pPk ? pPk->aiColumn[k] : -1;
pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew);
}
}
pSort->aDefer[nDefer].pTab = pExpr->pTab;
pSort->aDefer[nDefer].pTab = pExpr->x.pTab;
pSort->aDefer[nDefer].iCsr = pExpr->iTable;
pSort->aDefer[nDefer].nKey = nKey;
nDefer++;
@@ -1680,7 +1686,7 @@ static const char *columnTypeImpl(
break;
}
assert( pTab && pExpr->pTab==pTab );
assert( pTab && pExpr->eX==EX_Tab && pExpr->x.pTab==pTab );
if( pS ){
/* The "table" is actually a sub-select or a view in the FROM clause
** of the SELECT statement. Return the declaration type and origin
@@ -1736,7 +1742,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;
@@ -1865,7 +1871,8 @@ static void generateColumnNames(
assert( p!=0 );
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering idx not yet coded */
/* Covering idx not yet coded: */
assert( p->op!=TK_COLUMN || (p->eX==EX_Tab && p->x.pTab!=0) );
if( pEList->a[i].zName ){
/* An AS clause always takes first priority */
char *zName = pEList->a[i].zName;
@@ -1873,7 +1880,8 @@ static void generateColumnNames(
}else if( srcName && p->op==TK_COLUMN ){
char *zCol;
int iCol = p->iColumn;
pTab = p->pTab;
assert( p->eX==EX_Tab );
pTab = p->x.pTab;
assert( pTab!=0 );
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
@@ -1957,14 +1965,17 @@ int sqlite3ColumnsFromExprList(
}else{
Expr *pColExpr = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
while( pColExpr->op==TK_DOT ){
pColExpr = pColExpr->pRight;
assert( pColExpr->eX==EX_Right );
pColExpr = pColExpr->x.pRight;
assert( pColExpr!=0 );
}
assert( pColExpr->op!=TK_AGG_COLUMN );
if( pColExpr->op==TK_COLUMN ){
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
Table *pTab = pColExpr->pTab;
Table *pTab;
assert( pColExpr->eX==EX_Tab );
pTab = pColExpr->x.pTab;
assert( pTab!=0 );
if( iCol<0 ) iCol = pTab->iPKey;
zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
@@ -2125,7 +2136,7 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
/*
** Compute the iLimit and iOffset fields of the SELECT based on the
** pLimit expressions. pLimit->pLeft and pLimit->pRight hold the expressions
** pLimit expressions. pLimit->pLeft and pLimit->x,pRight hold the expressions
** that appear in the original SQL statement after the LIMIT and OFFSET
** keywords. Or NULL if those keywords are omitted. iLimit and iOffset
** are the integer memory register numbers for counters used to compute
@@ -2133,7 +2144,7 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
** iLimit and iOffset are negative.
**
** This routine changes the values of iLimit and iOffset only if
** a limit or offset is defined by pLimit->pLeft and pLimit->pRight. iLimit
** a limit or offset is defined by pLimit->pLeft and pLimit->x.pRight. iLimit
** and iOffset should have been preset to appropriate default values (zero)
** prior to calling this routine.
**
@@ -2182,10 +2193,10 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
VdbeComment((v, "LIMIT counter"));
sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v);
}
if( pLimit->pRight ){
if( pLimit->eX==EX_Right ){
p->iOffset = iOffset = ++pParse->nMem;
pParse->nMem++; /* Allocate an extra register for limit+offset */
sqlite3ExprCode(pParse, pLimit->pRight, iOffset);
sqlite3ExprCode(pParse, pLimit->x.pRight, iOffset);
sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v);
VdbeComment((v, "OFFSET counter"));
sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset);
@@ -3442,7 +3453,7 @@ static Expr *substExpr(
Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
Expr ifNullRow;
assert( pSubst->pEList!=0 && pExpr->iColumn<pSubst->pEList->nExpr );
assert( pExpr->pRight==0 );
assert( pExpr->eX!=EX_Right );
if( sqlite3ExprIsVector(pCopy) ){
sqlite3VectorErrorMsg(pSubst->pParse, pCopy);
}else{
@@ -3471,11 +3482,20 @@ static Expr *substExpr(
pExpr->iTable = pSubst->iNewTable;
}
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;
}
case EX_Right: {
pExpr->x.pRight = substExpr(pSubst, pExpr->x.pRight);
if( pExpr->x.pRight==0 ) pExpr->eX = EX_None;
break;
}
}
}
return pExpr;
@@ -3715,7 +3735,9 @@ static int flattenSubquery(
** became arbitrary expressions, we were forced to add restrictions (13)
** and (14). */
if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */
if( pSub->pLimit && pSub->pLimit->pRight ) return 0; /* Restriction (14) */
if( pSub->pLimit && pSub->pLimit->eX==EX_Right ){
return 0; /* Restriction (14) */
}
if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){
return 0; /* Restriction (15) */
}
@@ -4110,26 +4132,28 @@ static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
if( pExpr==0 ) return;
if( ExprHasProperty(pExpr, EP_FromJoin) ) return;
if( pExpr->op==TK_AND ){
findConstInWhere(pConst, pExpr->pRight);
assert( pExpr->eX==EX_Right );
findConstInWhere(pConst, pExpr->x.pRight);
findConstInWhere(pConst, pExpr->pLeft);
return;
}
if( pExpr->op!=TK_EQ ) return;
pRight = pExpr->pRight;
assert( pExpr->eX==EX_Right );
pRight = pExpr->x.pRight;
pLeft = pExpr->pLeft;
assert( pRight!=0 );
assert( pLeft!=0 );
if( pRight->op==TK_COLUMN
&& !ExprHasProperty(pRight, EP_FixedCol)
&& sqlite3ExprIsConstant(pLeft)
&& sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
&& sqlite3IsBinary(sqlite3ComparisonCollSeq(pConst->pParse,pLeft,pRight))
){
constInsert(pConst, pRight, pLeft);
}else
if( pLeft->op==TK_COLUMN
&& !ExprHasProperty(pLeft, EP_FixedCol)
&& sqlite3ExprIsConstant(pRight)
&& sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
&& sqlite3IsBinary(sqlite3ComparisonCollSeq(pConst->pParse,pLeft,pRight))
){
constInsert(pConst, pLeft, pRight);
}
@@ -4316,7 +4340,8 @@ static int pushDownWhereTerms(
return 0; /* restriction (3) */
}
while( pWhere->op==TK_AND ){
nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight,
assert( pWhere->eX==EX_Right );
nChng += pushDownWhereTerms(pParse, pSubq, pWhere->x.pRight,
iCursor, isLeftJoin);
pWhere = pWhere->pLeft;
}
@@ -4902,9 +4927,9 @@ static int selectExpander(Walker *pWalker, Select *p){
for(k=0; k<pEList->nExpr; k++){
pE = pEList->a[k].pExpr;
if( pE->op==TK_ASTERISK ) break;
assert( pE->op!=TK_DOT || pE->pRight!=0 );
assert( pE->op!=TK_DOT || pE->eX==EX_Right );
assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
if( pE->op==TK_DOT && pE->pRight->op==TK_ASTERISK ) break;
if( pE->op==TK_DOT && pE->x.pRight->op==TK_ASTERISK ) break;
elistFlags |= pE->flags;
}
if( k<pEList->nExpr ){
@@ -4922,7 +4947,7 @@ static int selectExpander(Walker *pWalker, Select *p){
for(k=0; k<pEList->nExpr; k++){
pE = a[k].pExpr;
elistFlags |= pE->flags;
pRight = pE->pRight;
pRight = pE->eX==EX_Right ? pE->x.pRight : 0;
assert( pE->op!=TK_DOT || pRight!=0 );
if( pE->op!=TK_ASTERISK
&& (pE->op!=TK_DOT || pRight->op!=TK_ASTERISK)
@@ -5242,8 +5267,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 +5291,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 +5322,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 +6212,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;
+25 -5
View 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 */
@@ -2431,10 +2433,12 @@ struct Expr {
*********************************************************************/
Expr *pLeft; /* Left subnode */
Expr *pRight; /* Right subnode */
union {
Expr *pRight; /* Right subnode */
ExprList *pList; /* op = IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */
Select *pSelect; /* EP_xIsSelect and op = IN, EXISTS, SELECT */
Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL
** for a column of an index on an expression */
} x;
/* If the EP_Reduced flag is set in the Expr.flags mask, then no
@@ -2459,13 +2463,25 @@ struct Expr {
** TK_COLUMN: the value of p5 for OP_Column
** TK_AGG_FUNCTION: nesting depth */
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL
** for a column of an index on an expression */
#ifndef SQLITE_OMIT_WINDOWFUNC
Window *pWin; /* Window definition for window functions */
#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,10 +3810,13 @@ 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*);
void sqlite3ExprAddTab(sqlite3*, Expr*, Table*);
Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
void sqlite3ExprDelete(sqlite3*, Expr*);
void sqlite3ExprClearXUnion(sqlite3*,Expr*);
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
void sqlite3ExprListSetSortOrder(ExprList*,int);
@@ -4385,7 +4404,8 @@ int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
void sqlite3ParserReset(Parse*);
int sqlite3Reprepare(Vdbe*);
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
CollSeq *sqlite3ComparisonCollSeq(Parse*,Expr*,Expr*);
CollSeq *sqlite3ComparisonExprCollSeq(Parse*,Expr*);
int sqlite3TempInMemory(const sqlite3*);
const char *sqlite3JournalModename(int);
#ifndef SQLITE_OMIT_WAL
+19 -12
View File
@@ -238,10 +238,10 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
}
if( p->pLimit ){
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
if( p->pLimit->pRight ){
sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->eX==EX_Right);
if( p->pLimit->eX==EX_Right ){
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
sqlite3TreeViewExpr(pView, p->pLimit->x.pRight, 0);
sqlite3TreeViewPop(pView);
}
sqlite3TreeViewPop(pView);
@@ -468,9 +468,9 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
"IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE"
};
assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT );
assert( pExpr->pRight );
assert( pExpr->pRight->op==TK_TRUEFALSE );
x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);
assert( pExpr->eX==EX_Right );
assert( pExpr->x.pRight->op==TK_TRUEFALSE );
x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->x.pRight);
zUniOp = azOp[x];
break;
}
@@ -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;
}
@@ -596,7 +601,8 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
case TK_MATCH: {
sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s",
pExpr->iTable, pExpr->iColumn, zFlgs);
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
assert( pExpr->eX==EX_Right );
sqlite3TreeViewExpr(pView, pExpr->x.pRight, 0);
break;
}
case TK_VECTOR: {
@@ -621,7 +627,8 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
if( zBinOp ){
sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
assert( pExpr->eX==EX_Right );
sqlite3TreeViewExpr(pView, pExpr->x.pRight, 0);
}else if( zUniOp ){
sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
+2 -2
View File
@@ -1375,9 +1375,9 @@ static void displayP4Expr(StrAccum *p, Expr *pExpr){
if( zOp ){
sqlite3_str_appendf(p, "%s(", zOp);
displayP4Expr(p, pExpr->pLeft);
if( pExpr->pRight ){
if( pExpr->eX==EX_Right ){
sqlite3_str_append(p, ",", 1);
displayP4Expr(p, pExpr->pRight);
displayP4Expr(p, pExpr->x.pRight);
}
sqlite3_str_append(p, ")", 1);
}
+1 -2
View File
@@ -1053,8 +1053,7 @@ FuncDef *sqlite3VtabOverloadFunction(
/* Check to see the left operand is a column in a virtual table */
if( NEVER(pExpr==0) ) return pDef;
if( pExpr->op!=TK_COLUMN ) return pDef;
pTab = pExpr->pTab;
if( pTab==0 ) return pDef;
if( pExpr->eX!=EX_Tab || (pTab = pExpr->x.pTab)==0 ) return pDef;
if( !IsVirtual(pTab) ) return pDef;
pVtab = sqlite3GetVTable(db, pTab)->pVtab;
assert( pVtab!=0 );
+13 -8
View File
@@ -45,14 +45,19 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
if( rc ) return rc & WRC_Abort;
if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
assert( pExpr->x.pList==0 || pExpr->pRight==0 );
if( pExpr->pRight ){
pExpr = pExpr->pRight;
continue;
}else 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;
switch( pExpr->eX ){
case EX_Right: {
pExpr = pExpr->x.pRight;
continue;
}
case EX_Select: {
if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
break;
}
case EX_List: {
if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
break;
}
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( !ExprHasProperty(pExpr, EP_Reduced) && pExpr->pWin ){
+60 -38
View File
@@ -253,7 +253,9 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
){
if( (pTerm->eOperator & WO_EQUIV)!=0
&& pScan->nEquiv<ArraySize(pScan->aiCur)
&& (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN
&& ALWAYS(pTerm->pExpr->eX==EX_Right)
&& (pX = sqlite3ExprSkipCollate(pTerm->pExpr->x.pRight))->op
==TK_COLUMN
){
int j;
for(j=0; j<pScan->nEquiv; j++){
@@ -278,15 +280,15 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
continue;
}
assert(pX->pLeft);
pColl = sqlite3BinaryCompareCollSeq(pParse,
pX->pLeft, pX->pRight);
pColl = sqlite3ComparisonExprCollSeq(pParse, pX);
if( pColl==0 ) pColl = pParse->db->pDfltColl;
if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
continue;
}
}
if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0
&& (pX = pTerm->pExpr->pRight)->op==TK_COLUMN
&& ALWAYS(pTerm->pExpr->eX==EX_Right)
&& (pX = pTerm->pExpr->x.pRight)->op==TK_COLUMN
&& pX->iTable==pScan->aiCur[0]
&& pX->iColumn==pScan->aiColumn[0]
){
@@ -789,7 +791,7 @@ static void constructAutomaticIndex(
Expr *pX = pTerm->pExpr;
idxCols |= cMask;
pIdx->aiColumn[n] = pTerm->u.leftColumn;
pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
pColl = sqlite3ComparisonExprCollSeq(pParse, pX);
pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
n++;
}
@@ -1006,7 +1008,8 @@ static sqlite3_index_info *allocateIndexInfo(
assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
&& sqlite3ExprIsVector(pTerm->pExpr->pRight)
&& ALWAYS(pTerm->pExpr->eX==EX_Right)
&& sqlite3ExprIsVector(pTerm->pExpr->x.pRight)
){
if( i<16 ) mNoOmit |= (1 << i);
if( op==WO_LT ) pIdxCons[j].op = WO_LE;
@@ -1366,11 +1369,13 @@ static int whereRangeSkipScanEst(
pColl = sqlite3LocateCollSeq(pParse, p->azColl[nEq]);
if( pLower ){
rc = sqlite3Stat4ValueFromExpr(pParse, pLower->pExpr->pRight, aff, &p1);
assert( pLower->pExpr->eX==EX_Right );
rc = sqlite3Stat4ValueFromExpr(pParse, pLower->pExpr->x.pRight, aff, &p1);
nLower = 0;
}
if( pUpper && rc==SQLITE_OK ){
rc = sqlite3Stat4ValueFromExpr(pParse, pUpper->pExpr->pRight, aff, &p2);
assert( pUpper->pExpr->eX==EX_Right );
rc = sqlite3Stat4ValueFromExpr(pParse, pUpper->pExpr->x.pRight, aff, &p2);
nUpper = p2 ? 0 : p->nSample;
}
@@ -1532,7 +1537,9 @@ static int whereRangeScanEst(
/* If possible, improve on the iLower estimate using ($P:$L). */
if( pLower ){
int n; /* Values extracted from pExpr */
Expr *pExpr = pLower->pExpr->pRight;
Expr *pExpr;
assert( pLower->pExpr->eX==EX_Right );
pExpr = pLower->pExpr->x.pRight;
rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nBtm, nEq, &n);
if( rc==SQLITE_OK && n ){
tRowcnt iNew;
@@ -1549,7 +1556,9 @@ static int whereRangeScanEst(
/* If possible, improve on the iUpper estimate using ($P:$U). */
if( pUpper ){
int n; /* Values extracted from pExpr */
Expr *pExpr = pUpper->pExpr->pRight;
Expr *pExpr;
assert( pUpper->pExpr->eX==EX_Right );
pExpr = pUpper->pExpr->x.pRight;
rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nTop, nEq, &n);
if( rc==SQLITE_OK && n ){
tRowcnt iNew;
@@ -2279,7 +2288,9 @@ static void whereLoopOutputAdjust(
** guess a reasonable truth probability. */
pLoop->nOut--;
if( pTerm->eOperator&(WO_EQ|WO_IS) ){
Expr *pRight = pTerm->pExpr->pRight;
Expr *pRight;
assert( pTerm->pExpr->eX==EX_Right );
pRight = pTerm->pExpr->x.pRight;
testcase( pTerm->pExpr->op==TK_IS );
if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){
k = 10;
@@ -2328,9 +2339,13 @@ 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;
Expr *pRhs;
pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr;
assert( pTerm->pExpr->eX==EX_Right );
pRhs = pTerm->pExpr->x.pRight;
assert( pRhs->eX==EX_Select || pRhs->eX==EX_List );
if( pRhs->eX==EX_Select ){
pRhs = pRhs->x.pSelect->pEList->a[i].pExpr;
}else{
pRhs = pRhs->x.pList->a[i].pExpr;
@@ -2353,7 +2368,7 @@ static int whereRangeVectorLen(
idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn);
if( aff!=idxaff ) break;
pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
pColl = sqlite3ComparisonCollSeq(pParse, pLhs, pRhs);
if( pColl==0 ) break;
if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break;
}
@@ -2488,24 +2503,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,16 +2640,17 @@ 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;
if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){
if( (eOp & (WO_EQ|WO_IS))!=0 ){
testcase( eOp & WO_EQ );
testcase( eOp & WO_IS );
testcase( eOp & WO_ISNULL );
rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut);
}else{
assert( pExpr->eX==EX_Right );
rc = whereEqualScanEst(pParse, pBuilder, pExpr->x.pRight, &nOut);
}else if( pExpr->eX==EX_List ){
rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
}
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
@@ -2783,7 +2804,8 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
Parse *pParse = pWC->pWInfo->pParse;
while( pWhere->op==TK_AND ){
if( !whereUsablePartialIndex(iTab,pWC,pWhere->pLeft) ) return 0;
pWhere = pWhere->pRight;
assert( pWhere->eX==EX_Right );
pWhere = pWhere->x.pRight;
}
if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
@@ -3238,7 +3260,7 @@ const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int iCons){
int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset;
Expr *pX = pHidden->pWC->a[iTerm].pExpr;
if( pX->pLeft ){
pC = sqlite3BinaryCompareCollSeq(pHidden->pParse, pX->pLeft, pX->pRight);
pC = sqlite3ComparisonExprCollSeq(pHidden->pParse,pX);
}
zRet = (pC ? pC->zName : sqlite3StrBINARY);
}
+32 -17
View 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
@@ -502,7 +504,8 @@ static int codeEqualityTerm(
assert( pLevel->pWLoop->aLTerm[iEq]==pTerm );
assert( iTarget>0 );
if( pX->op==TK_EQ || pX->op==TK_IS ){
iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
assert( pX->eX==EX_Right );
iReg = sqlite3ExprCodeTarget(pParse, pX->x.pRight, iTarget);
}else if( pX->op==TK_ISNULL ){
iReg = iTarget;
sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
@@ -538,7 +541,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 +737,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
@@ -742,7 +745,9 @@ static int codeAllEqualityTerms(
if( zAff ) zAff[j] = SQLITE_AFF_BLOB;
}
}else if( (pTerm->eOperator & WO_ISNULL)==0 ){
Expr *pRight = pTerm->pExpr->pRight;
Expr *pRight;
assert( pTerm->pExpr->eX==EX_Right );
pRight = pTerm->pExpr->x.pRight;
if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
VdbeCoverage(v);
@@ -1074,7 +1079,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);
@@ -1117,7 +1122,7 @@ static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
pExpr->op = TK_COLUMN;
pExpr->iTable = pX->iIdxCur;
pExpr->iColumn = pX->iIdxCol;
pExpr->pTab = 0;
/* pExpr->pTab = 0; */
return WRC_Prune;
}else{
return WRC_Continue;
@@ -1262,7 +1267,8 @@ Bitmask sqlite3WhereCodeOneLoopStart(
codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
addrNotFound = pLevel->addrNxt;
}else{
Expr *pRight = pTerm->pExpr->pRight;
Expr *pExpr = pTerm->pExpr;
Expr *pRight = pExpr->eX==EX_Right ? pExpr->x.pRight : 0;
codeExprOrVector(pParse, pRight, iTarget, 1);
}
}
@@ -1307,8 +1313,11 @@ Bitmask sqlite3WhereCodeOneLoopStart(
assert( pCompare!=0 || db->mallocFailed );
if( pCompare ){
pCompare->pLeft = pTerm->pExpr->pLeft;
pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0);
assert( pCompare->eX==EX_None );
pRight = sqlite3Expr(db, TK_REGISTER, 0);
if( pRight ){
pCompare->x.pRight = pRight;
pCompare->eX = EX_Right;
pRight->iTable = iReg+j+2;
sqlite3ExprIfFalse(pParse, pCompare, pLevel->addrCont, 0);
}
@@ -1393,9 +1402,10 @@ Bitmask sqlite3WhereCodeOneLoopStart(
pX = pStart->pExpr;
assert( pX!=0 );
testcase( pStart->leftCursor!=iCur ); /* transitive constraints */
if( sqlite3ExprIsVector(pX->pRight) ){
assert( pX->eX==EX_Right );
if( sqlite3ExprIsVector(pX->x.pRight) ){
r1 = rTemp = sqlite3GetTempReg(pParse);
codeExprOrVector(pParse, pX->pRight, r1, 1);
codeExprOrVector(pParse, pX->x.pRight, r1, 1);
testcase( pX->op==TK_GT );
testcase( pX->op==TK_GE );
testcase( pX->op==TK_LT );
@@ -1406,7 +1416,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
assert( pX->op!=TK_LT || op==OP_SeekLE );
assert( pX->op!=TK_LE || op==OP_SeekLE );
}else{
r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp);
r1 = sqlite3ExprCodeTemp(pParse, pX->x.pRight, &rTemp);
disableTerm(pLevel, pStart);
op = aMoveOp[(pX->op - TK_GT)];
}
@@ -1426,19 +1436,20 @@ Bitmask sqlite3WhereCodeOneLoopStart(
Expr *pX;
pX = pEnd->pExpr;
assert( pX!=0 );
assert( pX->eX==EX_Right );
assert( (pEnd->wtFlags & TERM_VNULL)==0 );
testcase( pEnd->leftCursor!=iCur ); /* Transitive constraints */
testcase( pEnd->wtFlags & TERM_VIRTUAL );
memEndValue = ++pParse->nMem;
codeExprOrVector(pParse, pX->pRight, memEndValue, 1);
if( 0==sqlite3ExprIsVector(pX->pRight)
codeExprOrVector(pParse, pX->x.pRight, memEndValue, 1);
if( 0==sqlite3ExprIsVector(pX->x.pRight)
&& (pX->op==TK_LT || pX->op==TK_GT)
){
testOp = bRev ? OP_Le : OP_Ge;
}else{
testOp = bRev ? OP_Lt : OP_Gt;
}
if( 0==sqlite3ExprIsVector(pX->pRight) ){
if( 0==sqlite3ExprIsVector(pX->x.pRight) ){
disableTerm(pLevel, pEnd);
}
}
@@ -1622,7 +1633,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
/* Seek the index cursor to the start of the range. */
nConstraint = nEq;
if( pRangeStart ){
Expr *pRight = pRangeStart->pExpr->pRight;
Expr *pRight;
assert( pRangeStart->pExpr->eX==EX_Right );
pRight = pRangeStart->pExpr->x.pRight;
codeExprOrVector(pParse, pRight, regBase+nEq, nBtm);
whereLikeOptimizationStringFixup(v, pLevel, pRangeStart);
if( (pRangeStart->wtFlags & TERM_VNULL)==0
@@ -1674,7 +1687,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
*/
nConstraint = nEq;
if( pRangeEnd ){
Expr *pRight = pRangeEnd->pExpr->pRight;
Expr *pRight;
assert( pRangeEnd->pExpr->eX==EX_Right );
pRight = pRangeEnd->pExpr->x.pRight;
codeExprOrVector(pParse, pRight, regBase+nEq, nTop);
whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd);
if( (pRangeEnd->wtFlags & TERM_VNULL)==0
@@ -2194,7 +2209,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;
+87 -51
View File
@@ -119,15 +119,17 @@ static int allowedOp(int op){
** is not commuted.
*/
static void exprCommute(Parse *pParse, Expr *pExpr){
u16 expRight = (pExpr->pRight->flags & EP_Collate);
u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
u16 expRight, expLeft;
assert( pExpr->eX==EX_Right );
expRight = (pExpr->x.pRight->flags & EP_Collate);
expLeft = (pExpr->pLeft->flags & EP_Collate);
assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
if( expRight==expLeft ){
/* Either X and Y both have COLLATE operator or neither do */
if( expRight ){
/* Both X and Y have COLLATE operators. Make sure X is always
** used by clearing the EP_Collate flag from Y. */
pExpr->pRight->flags &= ~EP_Collate;
pExpr->x.pRight->flags &= ~EP_Collate;
}else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
/* Neither X nor Y have COLLATE operators, but X has a non-default
** collating sequence. So add the EP_Collate marker on X to cause
@@ -135,7 +137,7 @@ static void exprCommute(Parse *pParse, Expr *pExpr){
pExpr->pLeft->flags |= EP_Collate;
}
}
SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
SWAP(Expr*,pExpr->x.pRight,pExpr->pLeft);
if( pExpr->op>=TK_GT ){
assert( TK_LT==TK_GT+2 );
assert( TK_GE==TK_LE+2 );
@@ -280,8 +282,9 @@ static int isLikeOrGlob(
|| (zNew[0]+1=='0' && iTo==1)
){
if( pLeft->op!=TK_COLUMN
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
|| IsVirtual(pLeft->pTab) /* Value might be numeric */
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
|| NEVER(pLeft->eX!=EX_Tab)
|| IsVirtual(pLeft->x.pTab) /* Value might be numeric */
){
sqlite3ExprDelete(db, pPrefix);
sqlite3ValueFree(pVal);
@@ -382,7 +385,7 @@ static int isAuxiliaryVtabOperator(
** MATCH(expression,vtab_column)
*/
pCol = pList->a[1].pExpr;
if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){
if( pCol->op==TK_COLUMN && pCol->eX==EX_Tab && IsVirtual(pCol->x.pTab) ){
for(i=0; i<ArraySize(aOp); i++){
if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
*peOp2 = aOp[i].eOp2;
@@ -404,12 +407,12 @@ static int isAuxiliaryVtabOperator(
** with function names in an arbitrary case.
*/
pCol = pList->a[0].pExpr;
if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){
if( pCol->op==TK_COLUMN && pCol->eX==EX_Tab && IsVirtual(pCol->x.pTab) ){
sqlite3_vtab *pVtab;
sqlite3_module *pMod;
void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**);
void *pNotUsed;
pVtab = sqlite3GetVTable(db, pCol->pTab)->pVtab;
pVtab = sqlite3GetVTable(db, pCol->x.pTab)->pVtab;
assert( pVtab!=0 );
assert( pVtab->pModule!=0 );
pMod = (sqlite3_module *)pVtab->pModule;
@@ -426,11 +429,12 @@ static int isAuxiliaryVtabOperator(
}else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
int res = 0;
Expr *pLeft = pExpr->pLeft;
Expr *pRight = pExpr->pRight;
if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){
Expr *pRight = 0;
if( pLeft->op==TK_COLUMN && pLeft->eX==EX_Tab && IsVirtual(pLeft->x.pTab) ){
res++;
}
if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->pTab) ){
if( pExpr->eX==EX_Right && (pRight = pExpr->x.pRight)->op==TK_COLUMN
&& pRight->eX==EX_Tab && IsVirtual(pRight->x.pTab) ){
res++;
SWAP(Expr*, pLeft, pRight);
}
@@ -516,10 +520,14 @@ static void whereCombineDisjuncts(
if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
&& (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return;
assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 );
assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 );
if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return;
if( sqlite3ExprCompare(0,pOne->pExpr->pRight, pTwo->pExpr->pRight,-1) )return;
assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->eX==EX_Right );
assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->eX==EX_Right );
if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ){
return;
}
if( sqlite3ExprCompare(0,pOne->pExpr->x.pRight, pTwo->pExpr->x.pRight,-1) ){
return;
}
/* If we reach this point, it means the two subterms can be combined */
if( (eOp & (eOp-1))!=0 ){
if( eOp & (WO_LT|WO_LE) ){
@@ -827,7 +835,8 @@ static void exprAnalyzeOrTerm(
** of both right and left sides must be such that no type
** conversions are required on the right. (Ticket #2249)
*/
affRight = sqlite3ExprAffinity(pOrTerm->pExpr->pRight);
assert( pOrTerm->pExpr->eX==EX_Right );
affRight = sqlite3ExprAffinity(pOrTerm->pExpr->x.pRight);
affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft);
if( affRight!=0 && affRight!=affLeft ){
okToChngToIN = 0;
@@ -853,25 +862,28 @@ static void exprAnalyzeOrTerm(
assert( pOrTerm->eOperator & WO_EQ );
assert( pOrTerm->leftCursor==iCursor );
assert( pOrTerm->u.leftColumn==iColumn );
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
assert( pOrTerm->pExpr->eX==EX_Right );
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->x.pRight, 0);
pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
pLeft = pOrTerm->pExpr->pLeft;
}
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);
}
}
}
@@ -900,15 +912,16 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr){
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0;
aff1 = sqlite3ExprAffinity(pExpr->pLeft);
aff2 = sqlite3ExprAffinity(pExpr->pRight);
assert( pExpr->eX==EX_Right );
aff2 = sqlite3ExprAffinity(pExpr->x.pRight);
if( aff1!=aff2
&& (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2))
){
return 0;
}
pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
pColl = sqlite3ComparisonExprCollSeq(pParse, pExpr);
if( sqlite3IsBinary(pColl) ) return 1;
return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->x.pRight);
}
/*
@@ -1053,17 +1066,25 @@ static void exprAnalyze(
prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft);
op = pExpr->op;
if( op==TK_IN ){
assert( pExpr->pRight==0 );
assert( pExpr->eX!=EX_Right );
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
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;
}else{
pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight);
assert( op!=TK_ISNULL || pExpr->eX!=EX_Right );
if( pExpr->eX==EX_Right ){
pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->x.pRight);
}else{
pTerm->prereqRight = 0;
}
}
pMaskSet->bVarSelect = 0;
prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr);
@@ -1084,10 +1105,16 @@ static void exprAnalyze(
pTerm->eOperator = 0;
if( allowedOp(op) ){
int aiCurCol[2];
Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
Expr *pLeft, *pRight;
u16 opMask;
pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
if( pExpr->eX==EX_Right ){
pRight = sqlite3ExprSkipCollate(pExpr->x.pRight);
}else{
pRight = 0;
}
opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
if( pTerm->iField>0 ){
assert( op==TK_IN );
assert( pLeft->op==TK_VECTOR );
@@ -1328,17 +1355,18 @@ static void exprAnalyze(
if( pWC->op==TK_AND
&& (pExpr->op==TK_EQ || pExpr->op==TK_IS)
&& (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
&& sqlite3ExprVectorSize(pExpr->pRight)==nLeft
&& ( (pExpr->pLeft->flags & EP_xIsSelect)==0
|| (pExpr->pRight->flags & EP_xIsSelect)==0)
&& ALWAYS(pExpr->eX==EX_Right)
&& sqlite3ExprVectorSize(pExpr->x.pRight)==nLeft
&& ( pExpr->pLeft->eX!=EX_Select || pExpr->x.pRight->eX!=EX_Select )
){
int i;
for(i=0; i<nLeft; i++){
int idxNew;
Expr *pNew;
Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
Expr *pNew, *pLeft, *pRight;
pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
assert( pExpr->eX==EX_Right );
pRight = sqlite3ExprForVectorField(pParse, pExpr->x.pRight, i);
pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
transferJoinMarkings(pNew, pExpr);
idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
@@ -1446,8 +1474,9 @@ void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
if( pE2->op!=op ){
whereClauseInsert(pWC, pExpr, 0);
}else{
assert( pE2->eX==EX_Right );
sqlite3WhereSplit(pWC, pE2->pLeft, op);
sqlite3WhereSplit(pWC, pE2->pRight, op);
sqlite3WhereSplit(pWC, pE2->x.pRight, op);
}
}
@@ -1506,14 +1535,20 @@ Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
}
mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0;
if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft);
if( p->pRight ){
mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pRight);
assert( p->x.pList==0 );
}else 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);
switch( p->eX ){
case EX_Right: {
mask |= sqlite3WhereExprUsageNN(pMaskSet, p->x.pRight);
break;
}
case EX_Select: {
if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
break;
}
case EX_List: {
mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
break;
}
}
return mask;
}
@@ -1583,7 +1618,8 @@ void sqlite3WhereTabFuncArgs(
if( pColRef==0 ) return;
pColRef->iTable = pItem->iCursor;
pColRef->iColumn = k++;
pColRef->pTab = pTab;
pColRef->x.pTab = pTab;
pColRef->eX = EX_Tab;
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef,
sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0));
whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
+1 -2
View File
@@ -14,7 +14,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix bestindex4
set testprefix bestindex5
ifcapable !vtab {
finish_test
@@ -247,4 +247,3 @@ do_execsql_test 3.5 { SELECT rowid, * FROM t4 WHERE rowid!=1 OR x!='245'; } {}
finish_test