diff options
-rw-r--r-- | manifest | 20 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/expr.c | 95 | ||||
-rw-r--r-- | src/sqliteInt.h | 9 | ||||
-rw-r--r-- | src/vdbemem.c | 2 | ||||
-rw-r--r-- | src/wherecode.c | 35 | ||||
-rw-r--r-- | src/whereexpr.c | 32 |
7 files changed, 106 insertions, 89 deletions
@@ -1,5 +1,5 @@ -C Replace\sthe\smagic\snumber\s(-2)\swith\sits\ssymbol\sXN_EXPR\sin\sthe\nexprMightBeIndexed()\sroutine.\s\sNo\slogic\schanges. -D 2016-08-19T19:58:06.626 +C Change\sthe\sway\sTK_SELECT_COLUMN\sis\shandled\sso\sthat\sthe\ssubquery\sis\sonly\ngenerated\sonce\seven\sif\spart\sof\sthe\svector\scomparison\sis\sused\sfor\sindexing\nand\sthe\sother\spart\sis\snow.\s\sThis\schange\salso\sis\sa\spathway\sto\svector\sassignment\nin\sUPDATE\sstatements. +D 2016-08-20T00:07:01.602 F Makefile.in cfd8fb987cd7a6af046daa87daa146d5aad0e088 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc d66d0395c38571aab3804f8db0fa20707ae4609a @@ -338,7 +338,7 @@ F src/ctime.c e77f3dc297b4b65c96da78b4ae4272fdfae863d7 F src/date.c 95c9a8d00767e7221a8e9a31f4e913fc8029bf6b F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d F src/delete.c 76c084f0265f4a3cd1ecf17eee112a94f1ccbc05 -F src/expr.c e139851835a8532e3974ca4bc8f6b0e5aef0e06f +F src/expr.c ff73eb6cae76c2423928d46ceff6f2fdc379a568 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c e2be0968c1adc679c87e467aa5b4f167588f38a8 F src/func.c 29cc9acb170ec1387b9f63eb52cd85f8de96c771 @@ -389,7 +389,7 @@ F src/shell.c 79dda477be6c96eba6e952a934957ad36f87acc7 F src/sqlite.h.in 0f7580280d1b009b507d8beec1ff0f197ba0cc99 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae -F src/sqliteInt.h 02b7f4bd9f945fbc46b05f7914b9c43d89517c59 +F src/sqliteInt.h 84f32ad3a5bfaf698b82bf5a9c6939f3e3d79ee0 F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247 F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1 F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -456,7 +456,7 @@ F src/vdbeInt.h c59381049af5c7751a83456c39b80d1a6fde1f9d F src/vdbeapi.c a32d61b7dd05e6890d8fd44d2805f55e2f5ba9f3 F src/vdbeaux.c a32d79aeaa88dc2b97c261172d952d395254a055 F src/vdbeblob.c 3e82a797b60c3b9fed7b8de8c539ca7607874937 -F src/vdbemem.c 77d6505956bf4e45c328ab3ebef6b461334cab5d +F src/vdbemem.c e67dc6d8177fd1830efb5d15e17793408251a187 F src/vdbesort.c 91fda3909326860382b0ca8aa251e609c6a9d62c F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834 F src/vtab.c 5ca4fa8b028f9e2ed4793ee1670911a83cfcefd8 @@ -466,8 +466,8 @@ F src/wal.h 6dd221ed384afdc204bc61e25c23ef7fd5a511f2 F src/walker.c 2d2cc7fb0f320f7f415215d7247f3c584141ac09 F src/where.c c7cdfd54f383090bb801cdd50d36de1a24684bb2 F src/whereInt.h 14dd243e13b81cbb0a66063d38b70f93a7d6e613 -F src/wherecode.c f3fd16b9b4cef1345330d22cf3f1628f87a56456 -F src/whereexpr.c bb22074cc2712c5013ecacdf7d652e7568a47bc3 +F src/wherecode.c 0c790c422ea5ecb6c83d6a78f2c4ebc036eea90e +F src/whereexpr.c 021469f11930cc705a26f7f31ec37640588df1d4 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1518,7 +1518,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 acea4ee136def4815d22eec240c5903a72bde9bd -R 223c403e8b392fa16a54efbf6c58e1ba +P d4a5af69cc3bde6f8c02075c07b4d47a0252392d +R 8a9288690d2190168e2ddd79f5078350 U drh -Z b5c0cabb5688d369770dffa65d09a7da +Z 663c48e63b0d59d8fc6b403d2678eeeb diff --git a/manifest.uuid b/manifest.uuid index 95b5affc2..a8cf8cf3b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d4a5af69cc3bde6f8c02075c07b4d47a0252392d
\ No newline at end of file +d8feea7dcde83179bff303072426561cfe825e58
\ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 1949be50a..de2c7a6a2 100644 --- a/src/expr.c +++ b/src/expr.c @@ -334,13 +334,21 @@ int sqlite3ExprVectorSize(Expr *pExpr){ #ifndef SQLITE_OMIT_SUBQUERY /* -** If the expression passed as the first argument is a TK_VECTOR, return -** a pointer to the i'th field of the vector. Or, if the first argument -** points to a sub-select that returns more than one column, return a -** pointer to the i'th returned column value. Otherwise, return a copy -** of the first argument. +** Interpret the pVector input as a vector expression. If pVector is +** an ordinary scalar expression, treat it as a vector of size 1. +** +** Return a pointer to a subexpression of pVector that is the i-th +** column of the vector (numbered starting with 0). The caller must +** ensure that i is within range. +** +** pVector retains ownership of the returned subexpression. +** +** If the vector is a (SELECT ...) then the expression returned is +** just the expression for the i-th term of the result set, and is +** necessarily ready to be evaluated because the table cursor might +** not have been positioned yet. */ -Expr *sqlite3ExprVectorField(Expr *pVector, int i){ +Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){ assert( i<sqlite3ExprVectorSize(pVector) ); if( sqlite3ExprIsVector(pVector) ){ if( pVector->op==TK_SELECT ){ @@ -351,7 +359,57 @@ Expr *sqlite3ExprVectorField(Expr *pVector, int i){ } return pVector; } -#endif +#endif /* !defined(SQLITE_OMIT_SUBQUERY) */ + +#ifndef SQLITE_OMIT_SUBQUERY +/* +** Compute and return a new Expr object which when passed to +** sqlite3ExprCode() will generate all necessary code to compute +** the iField-th column of the vector expression pVector. +** +** The caller owns the returned Expr object and is responsible for +** ensuring that the returned value eventually gets freed. +** +** Ownership of pVector is controlled by the takeOwnership parameter. If +** takeOwnership is true, this routine takes responsibility for freeing +** pVector, and may do so before returning, hence the caller must not reference +** pVector again. If takeOwnership is false, then the caller takes +** responsibility for freeing pVector and must ensure the pVector remains +** valid as long as the returned value remains in use. +*/ +Expr *sqlite3ExprForVectorField( + Parse *pParse, /* Parsing context */ + Expr *pVector, /* The vector. List of expressions or a sub-SELECT */ + int iField, /* Which column of the vector to return */ + int takeOwnership /* True to take ownership of pVector before returning */ +){ + Expr *pRet; + assert( sqlite3ExprIsVector(pVector) ); + /* FIXME: Add support for takeOwnership!=0 */ assert( takeOwnership==0 ); + if( pVector->flags & EP_xIsSelect ){ + /* The TK_SELECT_COLUMN Expr node: + ** + ** pLeft: pVector containing TK_SELECT + ** pRight: pVector if ownership taken + ** iColumn: Index of a column in pVector + ** pLeft->iTable: First in an array of register holding result, or 0 + ** if the result is not yet computed. + ** + ** sqlite3ExprDelete() specifically skips the recursive delete of + ** pLeft on TK_SELECT_COLUMN nodes. But pRight is followed, so pVector + ** is included on pRight if ownership is taken. Typically there will + ** be multiple TK_SELECT_COLUMN nodes with the same pLeft pointer to + ** the pVector, but only one of them will own the pVector. + */ + pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, pVector, 0, 0); + if( pRet ) pRet->iColumn = iField; + assert( pRet==0 || pRet->iTable==0 ); + }else{ + pRet = sqlite3ExprDup(pParse->db, pVector->x.pList->a[iField].pExpr, 0); + } + return pRet; +} +#endif /* !define(SQLITE_OMIT_SUBQUERY) */ /* ** If expression pExpr is of type TK_SELECT, generate code to evaluate @@ -2025,7 +2083,7 @@ int sqlite3FindInIndex( ** comparison is the same as the affinity of each column. If ** it not, it is not possible to use any index. */ for(i=0; i<nExpr && affinity_ok; i++){ - Expr *pLhs = sqlite3ExprVectorField(pX->pLeft, i); + Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i); int iCol = pEList->a[i].pExpr->iColumn; char idxaff = pTab->aCol[iCol].affinity; char cmpaff = sqlite3CompareAffinity(pLhs, idxaff); @@ -2051,7 +2109,7 @@ int sqlite3FindInIndex( } for(i=0; i<nExpr; i++){ - Expr *pLhs = sqlite3ExprVectorField(pX->pLeft, i); + Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i); Expr *pRhs = pEList->a[i].pExpr; CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); int j; @@ -2159,7 +2217,7 @@ static char *exprINAffinity(Parse *pParse, Expr *pExpr){ if( zRet ){ int i; for(i=0; i<nVal; i++){ - Expr *pA = sqlite3ExprVectorField(pLeft, i); + Expr *pA = sqlite3VectorFieldSubexpr(pLeft, i); char a = sqlite3ExprAffinity(pA); if( pSelect ){ zRet[i] = sqlite3CompareAffinity(pSelect->pEList->a[i].pExpr, a); @@ -2313,7 +2371,7 @@ int sqlite3CodeSubselect( assert( pEList->nExpr>0 ); assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); for(i=0; i<nVal; i++){ - Expr *p = (nVal>1) ? sqlite3ExprVectorField(pLeft, i) : pLeft; + Expr *p = (nVal>1) ? sqlite3VectorFieldSubexpr(pLeft, i) : pLeft; pKeyInfo->aColl[i] = sqlite3BinaryCompareCollSeq( pParse, p, pEList->a[i].pExpr ); @@ -2553,7 +2611,7 @@ static void sqlite3ExprCodeIN( } }else{ for(i=0; i<nVector; i++){ - Expr *pLhs = sqlite3ExprVectorField(pLeft, i); + Expr *pLhs = sqlite3VectorFieldSubexpr(pLeft, i); sqlite3ExprCode(pParse, pLhs, r1+aiMap[i]); } } @@ -2612,7 +2670,7 @@ static void sqlite3ExprCodeIN( ** completely empty, or NULL otherwise. */ if( destIfNull==destIfFalse ){ for(i=0; i<nVector; i++){ - Expr *p = sqlite3ExprVectorField(pExpr->pLeft, i); + Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i); if( sqlite3ExprCanBeNull(p) ){ sqlite3VdbeAddOp2(v, OP_IsNull, r1+aiMap[i], destIfNull); VdbeCoverage(v); @@ -2654,7 +2712,7 @@ static void sqlite3ExprCodeIN( Expr *p; CollSeq *pColl; int r2 = sqlite3GetTempReg(pParse); - p = sqlite3ExprVectorField(pLeft, i); + p = sqlite3VectorFieldSubexpr(pLeft, i); pColl = sqlite3ExprCollSeq(pParse, p); sqlite3VdbeAddOp3(v, OP_Column, iIdx, i, r2); @@ -2674,7 +2732,7 @@ static void sqlite3ExprCodeIN( ** result is 1. */ sqlite3VdbeJumpHere(v, addr); for(i=0; i<nVector; i++){ - Expr *p = sqlite3ExprVectorField(pExpr->pLeft, i); + Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i); if( sqlite3ExprCanBeNull(p) ){ sqlite3VdbeAddOp2(v, OP_IsNull, r1+aiMap[i], destIfNull); VdbeCoverage(v); @@ -3510,6 +3568,13 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ } break; } + case TK_SELECT_COLUMN: { + if( pExpr->pLeft->iTable==0 ){ + pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0); + } + inReg = pExpr->pLeft->iTable + pExpr->iColumn; + break; + } case TK_IN: { int destIfFalse = sqlite3VdbeMakeLabel(v); int destIfNull = sqlite3VdbeMakeLabel(v); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 7b37b030c..7651ff69e 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2298,9 +2298,11 @@ struct Expr { int iTable; /* TK_COLUMN: cursor number of table holding column ** TK_REGISTER: register number ** TK_TRIGGER: 1 -> new, 0 -> old - ** EP_Unlikely: 134217728 times likelihood */ + ** EP_Unlikely: 134217728 times likelihood + ** TK_SELECT: 1st register of result vector */ ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid. - ** TK_VARIABLE: variable number (always >= 1). */ + ** TK_VARIABLE: variable number (always >= 1). + ** TK_SELECT_COLUMN: column of the result vector */ i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */ u8 op2; /* TK_REGISTER: original value of Expr.op @@ -4273,6 +4275,7 @@ int sqlite3DbstatRegister(sqlite3*); int sqlite3ExprVectorSize(Expr *pExpr); int sqlite3ExprIsVector(Expr *pExpr); -Expr *sqlite3ExprVectorField(Expr*, int); +Expr *sqlite3VectorFieldSubexpr(Expr*, int); +Expr *sqlite3ExprForVectorField(Parse*,Expr*,int,int); #endif /* SQLITEINT_H */ diff --git a/src/vdbemem.c b/src/vdbemem.c index 070952763..bc0804200 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -1571,7 +1571,7 @@ int sqlite3Stat4ProbeSetValue( for(i=0; i<nElem; i++){ sqlite3_value *pVal = 0; - Expr *pElem = (pExpr ? sqlite3ExprVectorField(pExpr, i) : 0); + Expr *pElem = (pExpr ? sqlite3VectorFieldSubexpr(pExpr, i) : 0); u8 aff = sqlite3IndexColumnAffinity(pParse->db, pIdx, iVal+i); alloc.iVal = iVal+i; rc = stat4ValueFromExpr(pParse, pElem, aff, &alloc, &pVal); diff --git a/src/wherecode.c b/src/wherecode.c index dd15b5893..2ef9a46b5 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -377,34 +377,7 @@ static int codeEqualityTerm( assert( pLevel->pWLoop->aLTerm[iEq]==pTerm ); assert( iTarget>0 ); if( pX->op==TK_EQ || pX->op==TK_IS ){ - Expr *pRight = pX->pRight; -#ifndef SQLITE_OMIT_SUBQUERY - if( pRight->op==TK_SELECT_COLUMN ){ - /* This case occurs for expressions like "(a, b) == (SELECT ...)". */ - WhereLoop *pLoop = pLevel->pWLoop; - int i; - Expr *pSub = pRight->pLeft; - assert( pSub->op==TK_SELECT ); - for(i=pLoop->nSkip; i<iEq; i++){ - Expr *pExpr = pLoop->aLTerm[i]->pExpr->pRight; - if( pExpr && pExpr->op==TK_SELECT_COLUMN && pExpr->pLeft==pSub ) break; - } - - if( i==iEq ){ - iReg = sqlite3CodeSubselect(pParse, pSub, 0, 0); - for(/*no-op*/; i<pLoop->nLTerm; i++){ - Expr *pExpr = pLoop->aLTerm[i]->pExpr->pRight; - if( pExpr && pExpr->op==TK_SELECT_COLUMN && pExpr->pLeft==pSub ){ - sqlite3VdbeAddOp2(v, OP_Copy, iReg+pExpr->iColumn, iTarget-iEq+i); - } - } - } - iReg = iTarget; - }else -#endif - { - iReg = sqlite3ExprCodeTarget(pParse, pRight, iTarget); - } + iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget); }else if( pX->op==TK_ISNULL ){ iReg = iTarget; sqlite3VdbeAddOp2(v, OP_Null, 0, iReg); @@ -1101,11 +1074,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( addrNotFound = pLevel->addrNxt; }else{ Expr *pRight = pTerm->pExpr->pRight; - if( pRight->op==TK_SELECT_COLUMN ){ - codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); - }else{ - codeExprOrVector(pParse, pRight, iTarget, 1); - } + codeExprOrVector(pParse, pRight, iTarget, 1); } } sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg); diff --git a/src/whereexpr.c b/src/whereexpr.c index 2fc903ce6..55a4cf568 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -874,29 +874,6 @@ static int exprMightBeIndexed( } /* -** The expression passed as the second argument is a vector (either a -** TK_VECTOR node or a TK_SELECT that returns more than one column). This -** function returns a pointer to a new expression object representing -** field iField of the vector. -** -** If pVector is of type TK_VECTOR, the returned object is just a copy of -** the iField'th element of the vector. Or, if pVector is of type TK_SELECT, -** the return value points to a new expression object of type -** TK_SELECT_COLUMN. -*/ -static Expr *exprExtractVectorField(Parse *pParse, Expr *pVector, int iField){ - Expr *pRet; - assert( sqlite3ExprIsVector(pVector) ); - if( pVector->flags & EP_xIsSelect ){ - pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, pVector, 0, 0); - if( pRet ) pRet->iColumn = iField; - }else{ - pRet = sqlite3ExprDup(pParse->db, pVector->x.pList->a[iField].pExpr, 0); - } - return pRet; -} - -/* ** The input to this routine is an WhereTerm structure with only the ** "pExpr" field filled in. The job of this routine is to analyze the ** subexpression and populate all the other fields of the WhereTerm @@ -1211,14 +1188,17 @@ static void exprAnalyze( for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){ int idxNew; Expr *pNew; - Expr *pLeft = exprExtractVectorField(pParse, pExpr->pLeft, i); - Expr *pRight = exprExtractVectorField(pParse, pExpr->pRight, i); + Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i, 0); + Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i, 0); pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0); - idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); + idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); exprAnalyze(pSrc, pWC, idxNew); markTermAsChild(pWC, idxNew, idxTerm); } + pTerm = &pWC->a[idxTerm]; + pTerm->wtFlags = TERM_CODED; + pTerm->eOperator = 0; } } |