diff --git a/manifest b/manifest index 43f53685aa..c71b40dd0d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\scomment\stypo\sfixes\sfrom\strunk. -D 2016-07-10T19:35:45.597 +C Modifications\stowards\sbetter\svector\sIN(...)\ssupport\son\sthis\sbranch.\sNot\sactivated\syet. +D 2016-07-13T19:48:13.115 F Makefile.in 6c20d44f72d4564f11652b26291a214c8367e5db F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc d66d0395c38571aab3804f8db0fa20707ae4609a @@ -337,7 +337,7 @@ F src/ctime.c 61949e83c4c36e37195a8398ebc752780b534d95 F src/date.c 1cc9fb516ec9932c6fd4d2a0d2f8bc4480145c39 F src/dbstat.c 4f6f7f52b49beb9636ffbd517cfe44a402ba4ad0 F src/delete.c 4aba4214a377ce8ddde2d2e609777bcc8235200f -F src/expr.c 330854fe9fdea1d244abaef6d680f6b91df07cb4 +F src/expr.c 939362d26f5e99a4802ae94ae6e47d4def72b8f3 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c bc4145347595b7770f9a598cff1c848302cf5413 F src/func.c 61a4114cf7004f10c542cfabbab9f2bcb9033045 @@ -1507,7 +1507,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 b2204215b231202aef7a218411cc2ddaecf28f35 77c692a6704cd877ba35d0afb774ab9b46364d59 -R 1a7620cc6269220b48a9fcbcbb9b68d1 -U mistachkin -Z cf1dd7dc395b0586dda9fa40ccf71a27 +P 728c5aa436a5f55c86b019c415a2b71d1b0a8fd6 +R 6c0b20cb1573f5c43e78ae5a07a06597 +U dan +Z 35590bc4128842477cd3208768d4edc0 diff --git a/manifest.uuid b/manifest.uuid index b148ca6043..722c9bb7cc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -728c5aa436a5f55c86b019c415a2b71d1b0a8fd6 \ No newline at end of file +34e35c71b25b0aa2d8931040feb260a78cc48c49 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 7941c228fd..c43c6c04de 100644 --- a/src/expr.c +++ b/src/expr.c @@ -309,6 +309,12 @@ static int codeCompare( return addr; } +/* +** If the expression passed as the only argument is of type TK_VECTOR +** return the number of expressions in the vector. Or, if the expression +** is a sub-select, return the number of columns in the sub-select. For +** any other type of expression, return 1. +*/ int sqlite3ExprVectorSize(Expr *pExpr){ if( (pExpr->flags & EP_Vector)==0 ) return 1; if( pExpr->flags & EP_xIsSelect ){ @@ -318,7 +324,10 @@ int sqlite3ExprVectorSize(Expr *pExpr){ } static Expr *exprVectorField(Expr *pVector, int i){ - if( pVector->flags & EP_xIsSelect ){ + if( (pVector->flags & EP_Vector)==0 ){ + assert( i==0 ); + return pVector; + }else if( pVector->flags & EP_xIsSelect ){ return pVector->x.pSelect->pEList->a[i].pExpr; } return pVector->x.pList->a[i].pExpr; @@ -1703,12 +1712,12 @@ int sqlite3IsRowid(const char *z){ ** table, then return NULL. */ #ifndef SQLITE_OMIT_SUBQUERY -static Select *isCandidateForInOpt(Expr *pX){ +static Select *isCandidateForInOpt(Expr *pX, int bNullSensitive){ Select *p; SrcList *pSrc; ExprList *pEList; - Expr *pRes; Table *pTab; + int i; if( !ExprHasProperty(pX, EP_xIsSelect) ) return 0; /* Not a subquery */ if( ExprHasProperty(pX, EP_VarSelect) ) return 0; /* Correlated subq */ p = pX->x.pSelect; @@ -1731,10 +1740,18 @@ static Select *isCandidateForInOpt(Expr *pX){ assert( pTab->pSelect==0 ); /* FROM clause is not a view */ if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */ pEList = p->pEList; - if( pEList->nExpr!=1 ) return 0; /* One column in the result set */ - pRes = pEList->a[0].pExpr; - if( pRes->op!=TK_COLUMN ) return 0; /* Result is a column */ - assert( pRes->iTable==pSrc->a[0].iCursor ); /* Not a correlated subquery */ + + /* All SELECT results must be columns. If the SELECT returns more than + ** one column and the bNullSensitive flag is set, all returned columns + ** must be declared NOT NULL. */ + for(i=0; inExpr; i++){ + Expr *pRes = pEList->a[i].pExpr; + if( pRes->op!=TK_COLUMN ) return 0; + assert( pRes->iTable==pSrc->a[0].iCursor ); /* Not a correlated subquery */ + if( pEList->nExpr>1 && bNullSensitive ){ + if( pTab->aCol[pRes->iColumn].notNull==0 ) return 0; + } + } return p; } #endif /* SQLITE_OMIT_SUBQUERY */ @@ -1867,20 +1884,18 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){ ** satisfy the query. This is preferable to generating a new ** ephemeral table. */ - if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){ + if( pParse->nErr==0 && (p = isCandidateForInOpt(pX, prRhsHasNull!=0))!=0 ){ sqlite3 *db = pParse->db; /* Database connection */ Table *pTab; /* Table . */ - Expr *pExpr; /* Expression */ - i16 iCol; /* Index of column */ + ExprList *pEList = p->pEList; + int nExpr = pEList->nExpr; i16 iDb; /* Database idx for pTab */ assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */ pTab = p->pSrc->a[0].pTab; - pExpr = p->pEList->a[0].pExpr; - iCol = (i16)pExpr->iColumn; - + /* Code an OP_Transaction and OP_TableLock for
. */ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); sqlite3CodeVerifySchema(pParse, iDb); @@ -1891,7 +1906,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){ ** successful here. */ assert(v); - if( iCol<0 ){ + if( nExpr==1 && pEList->a[0].pExpr->iColumn<0 ){ int iAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v); @@ -1901,23 +1916,54 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){ sqlite3VdbeJumpHere(v, iAddr); }else{ Index *pIdx; /* Iterator variable */ + int affinity_ok = 1; + int i; + + /* Check that the affinity that will be used to perform each + ** comparison is the same as the affinity of each column. If + ** it not, it is not possible to use any index. */ + for(i=0; ipLeft, i); + int iCol = pEList->a[i].pExpr->iColumn; + char idxaff = pTab->aCol[iCol].affinity; + char cmpaff = sqlite3CompareAffinity(pLhs, idxaff); + switch( cmpaff ){ + case SQLITE_AFF_BLOB: + break; + case SQLITE_AFF_TEXT: + affinity_ok = (idxaff==SQLITE_AFF_TEXT); + break; + default: + affinity_ok = sqlite3IsNumericAffinity(idxaff); + } + } /* The collation sequence used by the comparison. If an index is to ** be used in place of a temp-table, it must be ordered according ** to this collation sequence. */ - CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pExpr); - - /* Check that the affinity that will be used to perform the - ** comparison is the same as the affinity of the column. If - ** it is not, it is not possible to use any index. - */ - int affinity_ok = sqlite3IndexAffinityOk(pX, pTab->aCol[iCol].affinity); for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){ - if( (pIdx->aiColumn[0]==iCol) - && sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq - && (!mustBeUnique || (pIdx->nKeyCol==1 && IsUniqueIndex(pIdx))) - ){ + if( pIdx->nKeyColnKeyCol!=nExpr || !IsUniqueIndex(pIdx)) ){ + continue; + } + + for(i=0; ipLeft, i); + Expr *pRhs = pEList->a[i].pExpr; + CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); + int j; + + for(j=0; jaiColumn[j]!=pRhs->iColumn ) continue; + assert( pIdx->azColl[j] ); + if( sqlite3StrICmp(pReq->zName, pIdx->azColl[j])!=0 ) continue; + break; + } + if( j==nExpr ) break; + } + + if( i==nExpr ){ int iAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); @@ -1925,11 +1971,13 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){ assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; - if( prRhsHasNull && !pTab->aCol[iCol].notNull ){ + if( prRhsHasNull && nExpr==1 + && !pTab->aCol[pEList->a[0].pExpr->iColumn].notNull + ){ #ifdef SQLITE_ENABLE_COLUMN_USED_MASK - const i64 sOne = 1; + i64 mask = (1<nMem; sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull); @@ -1954,7 +2002,6 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){ ){ eType = IN_INDEX_NOOP; } - if( eType==0 ){ /* Could not find an existing table or index to use as the RHS b-tree.