-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
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
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
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
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
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
-d4a5af69cc3bde6f8c02075c07b4d47a0252392d
\ No newline at end of file
+d8feea7dcde83179bff303072426561cfe825e58
\ No newline at end of file
#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 ){
}
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
** 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);
}
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;
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);
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
);
}
}else{
for(i=0; i<nVector; i++){
- Expr *pLhs = sqlite3ExprVectorField(pLeft, i);
+ Expr *pLhs = sqlite3VectorFieldSubexpr(pLeft, i);
sqlite3ExprCode(pParse, pLhs, r1+aiMap[i]);
}
}
** 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);
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);
** 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);
}
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);
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
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 */
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);
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);
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);
return 0;
}
-/*
-** 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
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;
}
}