-C Make\ssure\stemporary\sExpr\sobjects\sare\sfully\sinitialized\sprior\sto\ssending\sthem\ninto\ssqlite3ExprCodeTemp().
-D 2018-09-19T11:59:15.245
+C Reduce\sthe\ssize\sof\sExpr\sfrom\s80\sto\s72\sbytes\smoving\sthe\spRight\sfield\sinside\sthe\n"x"\sunion.\s\sThis\sis\san\sincremental\scheck-in\sthat\sstill\shas\sissues.
+D 2018-09-19T14:54:38.166
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 2269dd2f37ba963fde4c51e9e83542f126c86a8e10357c17f48137c6bee5299b
F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9
-F src/attach.c 8b8e52590fca04bed868461aadc5d38de7542f005310ced863e032c83e1b1b6a
+F src/attach.c d06bf7ab9efceb7c679ba8beaeeb3082ce3defde482f54de50ac175469f7c4ca
F src/auth.c 32a5bbe3b755169ab6c66311c5225a3cd4f75a46c041f7fb117e0cbb68055114
F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3
F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91
F src/delete.c 07a7ecf18a64478be7241cbb332bc26321586384c750e47fb566f678c5aee512
-F src/expr.c d48bca738efa75f4a8731c55db8425d275e6367163ca0149bed9b6117eab5e32
+F src/expr.c cc72d25fe9c2f3d6e8bdf9d519ab20135a45a8ade37c7712155af5d88693092e
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c f59253c0be4b1e9dfcb073b6d6d6ab83090ae50c08b5c113b76013c4b157cd6a
F src/func.c 82aeef69505b67197a476836d44cc16c1a434ee53481f23cffb70a75a1bcbc7a
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c a0d8f686ef64549ad5b356fd30429bd9ee7a06dd42b4d6faa096352ff26b1c5b
F src/pager.h ecc554a55bc55d1c4ba5e17137b72e238e00bd81e72ff2662d8b9c8c10ae3963
-F src/parse.y 15eeb0ead639555727ed81fc61bd8e28968e9379bc074ae9cb48b95c79b50f0d
+F src/parse.y cea885dd89f7c2963aee930b93c8ba14a7a9eb2bb31ba146777a7bbbc5b8a121
F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
F src/prepare.c f8e260d940a0e08494c0f30744521b2f832d7263eca9d02b050cea0ba144b097
F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
-F src/resolve.c 301eadb8bf5afcd0b673d4db3c85c179334e19970af276187932e5b0a97b90ec
+F src/resolve.c 1f8444d1155b4711cbe2fc1fcd40ecace3f71faa1cf593472581e17b9b39e6af
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
-F src/select.c af9efbeea79c7eaa21f51c2640f9f8e21d1c9dbcea236d5af68bb8f0313d9b1e
+F src/select.c f3070ba3c6a591799c62eed45cce83ec458e77f39567debf92e90b022bd2f05a
F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1f
F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 305adca1b5da4a33ce2db5bd236935768e951d5651bfe5560ed55cfcdbce6a63
-F src/sqliteInt.h 0aed6451d241a43814ac54d93f7d2b8645826ffa9e35e7289240dd38e967b813
+F src/sqliteInt.h b8a598f500ce81be682730b30b5d0dbdc4c1ec70a8ef640b7893d0edcadb5bdd
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 9f55961518f77793edd56eee860ecf035d4370ebbb0726ad2f6cada6637fd16b
-F src/treeview.c b6f459831c544d697e4b38471b98b972d9dd3b4611d0e8c6338632c7ad926d12
+F src/treeview.c 1bc9fc4ebd661bea19b4f39dd32f34b609faf2250112d83d7ffa40ab1c3b386b
F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd
F src/update.c 682f112c49247d2fe5950c9fe2226046c6bc497cf114f74d58766926914216ff
F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
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/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f
F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
-F src/walker.c b2d62136868f1f939a7778bdce8b372bb4e314862cd2b33bd1ec9614eef0b44c
-F src/where.c c90c392c7c8c8ea3e36592dba9800cee35eeadd36c512ab904da8245c334b148
+F src/walker.c 4ba292cadd145b8b77e8b2128a363beff0bd87c7f9abfe090c0948eb0330d727
+F src/where.c 33a546a918b0439e3e174351ca00c9158f26d73c5a8bb54c6c3cf5bae20b7499
F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4
-F src/wherecode.c 75a3b20d28a5c9f88e6c6dd9037ffeacdd786feaba8013245f7d8576a093dcf4
-F src/whereexpr.c c08b5afce2e7b9046c65f5edc3302888d79e8c541907a97df089c135895b25f0
+F src/wherecode.c 4c3ec236bfeaf2229e5d862e3ff9a2ac22d7cc3ce69c56892d3d25582bece577
+F src/whereexpr.c ba56a077649e8b0f4453eabfe57f3077c85bc6c9b7b3884bf2223c04f57fbca5
F src/window.c 4b503da928dace3e845b891381a4d98eeb8c5744313ae3643df8d8d21fdcca65
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 8849a463d67d79ec60c74a08835c176c08da651a82731558a1dceac2781cd75d
-R db879ad69540fd8a785f584d64935c70
+P de02a1d97a860f780d9b75cddf008a8b1824cf0483f7891e6ed55b83e2d32d91
+R 48c3dc53a777e2b3895af501d46c8ac1
U drh
-Z 1294c1f2dad466247d6550207298ec20
+Z 0905558528608b1236ee1840013b25d6
-de02a1d97a860f780d9b75cddf008a8b1824cf0483f7891e6ed55b83e2d32d91
\ No newline at end of file
+147c61a6d4b2a17d6c1da3584e3f29f2bc441e81fbea9d19110a9169c38fbd5f
\ No newline at end of file
if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
break;
}
- }
- if( sqlite3FixExpr(pFix, pExpr->pRight) ){
- return 1;
+ case EX_Right: {
+ if( sqlite3FixExpr(pFix, pExpr->x.pRight) ) return 1;
+ break;
+ }
}
pExpr = pExpr->pLeft;
}
if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){
p = p->pLeft;
}else{
- Expr *pNext = p->pRight;
+ Expr *pNext = 0;
/* p->flags holds EP_Collate and p->pLeft->flags does not. And
** p->x.pSelect cannot. So if p->x.pLeft exists, it must hold at
** least one EP_Collate. Thus the following two ALWAYS. */
break;
}
}
+ }else if( p->eX==EX_Right ){
+ pNext = p->x.pRight;
}
p = pNext;
}
pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT );
assert( pExpr->pLeft );
aff = sqlite3ExprAffinity(pExpr->pLeft);
- if( pExpr->pRight ){
- aff = sqlite3CompareAffinity(pExpr->pRight, aff);
+ if( pExpr->eX==EX_Right ){
+ aff = sqlite3CompareAffinity(pExpr->x.pRight, aff);
}else if( pExpr->eX==EX_Select ){
aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
}else if( aff==0 ){
**
** 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
}
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.
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);
){
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;
static void exprSetHeight(Expr *p){
int nHeight = 0;
heightOfExpr(p->pLeft, &nHeight);
- heightOfExpr(p->pRight, &nHeight);
- if( p->eX==EX_Select ){
- heightOfSelect(p->x.pSelect, &nHeight);
- }else if( p->eX==EX_List ){
- heightOfExprList(p->x.pList, &nHeight);
- p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
+ switch( p->eX ){
+ case EX_Select: {
+ heightOfSelect(p->x.pSelect, &nHeight);
+ break;
+ }
+ case EX_List: {
+ heightOfExprList(p->x.pList, &nHeight);
+ p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
+ break;
+ }
+ case EX_Right: {
+ heightOfExpr(p->x.pRight, &nHeight);
+ break;
+ }
}
p->nHeight = nHeight + 1;
}
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 ){
#ifdef SQLITE_DEBUG
if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){
assert( p->pLeft==0 );
- assert( p->pRight==0 );
assert( p->eX==EX_None );
}
if( !ExprHasProperty(p, EP_TokenOnly) ){
assert( p->op!=TK_FUNCTION || p->pLeft==0 );
- assert( p->pRight==0 || p->x.pSelect==0 );
}
if( !ExprHasProperty(p, (EP_TokenOnly|EP_Reduced)) ){
assert( p->pWin==0 || p->pLeft==0 );
assert( p->pWin==0 || p->pTab==0 );
assert( p->pWin==0 || p->op==TK_FUNCTION );
- assert( p->pTab==0 || (p->pRight==0 && p->eX==EX_None) );
+ assert( p->pTab==0 || p->eX==EX_None );
}
#endif
if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){
- /* The Expr.x union is never used at the same time as Expr.pRight */
- assert( p->x.pList==0 || p->pRight==0 );
if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
- if( p->pRight ){
- sqlite3ExprDeleteNN(db, p->pRight);
- }else{
- switch( p->eX ){
- case EX_Select: {
- sqlite3SelectDelete(db, p->x.pSelect);
- break;
- }
- case EX_List: {
- sqlite3ExprListDelete(db, p->x.pList);
- break;
- }
+ switch( p->eX ){
+ case EX_Select: {
+ sqlite3SelectDelete(db, p->x.pSelect);
+ break;
+ }
+ case EX_List: {
+ sqlite3ExprListDelete(db, p->x.pList);
+ break;
+ }
+ case EX_Right: {
+ sqlite3ExprDelete(db, p->x.pRight);
+ break;
}
}
if( !ExprHasProperty(p, EP_Reduced) ){
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;
}
}
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;
** 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.
*/
}
}
- /* 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;
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);
+ }
}
}
}
){
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 );
/* 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
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 );
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
);
}
codeVectorCompare(pParse, pExpr, target, op, p5);
}else{
r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
- codeCompare(pParse, pLeft, pExpr->pRight, op,
+ assert( pExpr->eX==EX_Right );
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, ®Free2);
+ 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);
assert( TK_RSHIFT==OP_ShiftRight ); testcase( op==TK_RSHIFT );
assert( TK_CONCAT==OP_Concat ); testcase( op==TK_CONCAT );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
+ assert( pExpr->eX==EX_Right );
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, ®Free2);
sqlite3VdbeAddOp3(v, op, r2, r1, target);
testcase( regFree1==0 );
testcase( regFree2==0 );
int bNormal; /* IS TRUE or IS FALSE */
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
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);
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;
}
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, ®Free1));
if( xJump ){
xJump(pParse, &exprAnd, dest, 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: {
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 ){
if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
testcase( jumpIfNull==0 );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
- codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
+ assert( pExpr->eX==EX_Right );
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, ®Free2);
+ 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);
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;
}
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 ){
if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
testcase( jumpIfNull==0 );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
- codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
+ assert( pExpr->eX==EX_Right );
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->x.pRight, ®Free2);
+ 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);
if( pA->eX==EX_Select || pA->eX!=pB->eX ) return 2;
if( (combinedFlags & EP_FixedCol)==0
&& sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
- if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2;
+ if( pA->eX==EX_Right ){
+ if( sqlite3ExprCompare(pParse,pA->x.pRight,pB->x.pRight,iTab) ) return 2;
+ }
if( pA->eX==EX_List ){
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
}
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;
}
testcase( pExpr->op==TK_LE );
testcase( pExpr->op==TK_GT );
testcase( pExpr->op==TK_GE );
+ assert( pExpr->eX==EX_Right );
if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab))
- || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab))
+ || (pExpr->x.pRight->op==TK_COLUMN && IsVirtual(pExpr->x.pRight->pTab))
){
return WRC_Prune;
}
p->eX = EX_None;
p->flags = EP_Leaf;
p->iAgg = -1;
- p->pLeft = p->pRight = 0;
+ p->pLeft = 0;
p->pAggInfo = 0;
p->pTab = 0;
p->op2 = 0;
** 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;
}
}
}
** 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
char *zAs = pEList->a[j].zName;
if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
Expr *pOrig;
- assert( pExpr->pLeft==0 && pExpr->pRight==0 );
+ assert( pExpr->pLeft==0 );
assert( pExpr->eX==EX_None );
pOrig = pEList->a[j].pExpr;
if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){
*/
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:
}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;
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 ){
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 );
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;
}
}
&& (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;
}
}
}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 );
/*
** 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
** 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.
**
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);
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{
pExpr->iTable = pSubst->iNewTable;
}
pExpr->pLeft = substExpr(pSubst, pExpr->pLeft);
- pExpr->pRight = substExpr(pSubst, pExpr->pRight);
switch( pExpr->eX ){
case EX_Select: {
substSelect(pSubst, pExpr->x.pSelect, 1);
substExprList(pSubst, pExpr->x.pList);
break;
}
+ case EX_Right: {
+ pExpr->x.pRight = substExpr(pSubst, pExpr->x.pRight);
+ break;
+ }
}
}
return pExpr;
** 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) */
}
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);
}
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;
}
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 ){
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)
*********************************************************************/
Expr *pLeft; /* Left subnode */
- Expr *pRight; /* Right subnode */
union {
+ Expr *pRight; /* Right subnode */
ExprList *pList; /* op = IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */
Select *pSelect; /* EP_xIsSelect and op = IN, EXISTS, SELECT */
} x;
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
}
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);
"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;
}
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: {
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);
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);
}
if( rc ) return rc & WRC_Abort;
if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
- assert( pExpr->x.pList==0 || pExpr->pRight==0 );
- if( pExpr->pRight ){
- pExpr = pExpr->pRight;
- continue;
- }else{
- switch( pExpr->eX ){
- case EX_Select: {
- if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
- break;
- }
- case EX_List: {
- if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
- break;
- }
+ switch( pExpr->eX ){
+ case EX_Right: {
+ pExpr = pExpr->x.pRight;
+ continue;
+ }
+ case EX_Select: {
+ if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
+ break;
+ }
+ case EX_List: {
+ if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
+ break;
}
}
#ifndef SQLITE_OMIT_WINDOWFUNC
){
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++){
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]
){
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++;
}
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;
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;
}
/* 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;
/* 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;
** 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;
char aff; /* Comparison affinity */
char idxaff = 0; /* Indexed columns affinity */
CollSeq *pColl; /* Comparison collation sequence */
- Expr *pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr;
- Expr *pRhs = pTerm->pExpr->pRight;
+ Expr *pLhs;
+ Expr *pRhs;
+ pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr;
+ assert( pTerm->pExpr->eX==EX_Right );
+ pRhs = pTerm->pExpr->x.pRight;
assert( pRhs->eX==EX_Select || pRhs->eX==EX_List );
if( pRhs->eX==EX_Select ){
pRhs = pRhs->x.pSelect->pEList->a[i].pExpr;
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;
}
&& 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;
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++){
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);
}
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);
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);
if( pTerm->eOperator & WO_IN ){
codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
addrNotFound = pLevel->addrNxt;
- }else{
- Expr *pRight = pTerm->pExpr->pRight;
+ }else if( pTerm->pExpr->eX==EX_Right ){
+ Expr *pRight;
+ pRight = pTerm->pExpr->x.pRight;
codeExprOrVector(pParse, pRight, iTarget, 1);
}
}
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);
}
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 );
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)];
}
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);
}
}
/* 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
*/
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
** 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
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 );
}else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
int res = 0;
Expr *pLeft = pExpr->pLeft;
- Expr *pRight = pExpr->pRight;
+ Expr *pRight = pExpr->x.pRight;
if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){
res++;
}
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) ){
** 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;
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;
}
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);
}
/*
prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft);
op = pExpr->op;
if( op==TK_IN ){
- assert( pExpr->pRight==0 );
+ assert( pExpr->eX!=EX_Right );
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
switch( pExpr->eX ){
case EX_Select: {
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);
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 );
if( pWC->op==TK_AND
&& (pExpr->op==TK_EQ || pExpr->op==TK_IS)
&& (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
- && sqlite3ExprVectorSize(pExpr->pRight)==nLeft
- && ( pExpr->pLeft->eX!=EX_Select || pExpr->pRight->eX!=EX_Select )
+ && ALWAYS(pExpr->eX==EX_Right)
+ && sqlite3ExprVectorSize(pExpr->x.pRight)==nLeft
+ && ( pExpr->pLeft->eX!=EX_Select || pExpr->x.pRight->eX!=EX_Select )
){
int i;
for(i=0; i<nLeft; i++){
int idxNew;
- Expr *pNew;
- Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
- Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
+ Expr *pNew, *pLeft, *pRight;
+ pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
+ assert( pExpr->eX==EX_Right );
+ pRight = sqlite3ExprForVectorField(pParse, pExpr->x.pRight, i);
pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
transferJoinMarkings(pNew, pExpr);
idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
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);
}
}
}
mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0;
if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft);
- if( p->pRight ){
- mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pRight);
- assert( p->x.pList==0 );
- }else{
- switch( p->eX ){
- case EX_Select: {
- if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
- mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
- break;
- }
- case EX_List: {
- mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
- break;
- }
+ switch( p->eX ){
+ case EX_Right: {
+ mask |= sqlite3WhereExprUsageNN(pMaskSet, p->x.pRight);
+ break;
+ }
+ case EX_Select: {
+ if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
+ mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
+ break;
+ }
+ case EX_List: {
+ mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
+ break;
}
}
return mask;