mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-18 10:21:03 +03:00
Merge in all the 3.9.0 updates from trunk.
FossilOrigin-Name: 29444149342fc6b1ea8cd34c2c8e1fcb06eaa7ed
This commit is contained in:
74
src/where.c
74
src/where.c
@@ -87,6 +87,13 @@ int sqlite3WhereBreakLabel(WhereInfo *pWInfo){
|
||||
*/
|
||||
int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){
|
||||
memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2);
|
||||
#ifdef WHERETRACE_ENABLED
|
||||
if( sqlite3WhereTrace && pWInfo->eOnePass!=ONEPASS_OFF ){
|
||||
sqlite3DebugPrintf("%s cursors: %d %d\n",
|
||||
pWInfo->eOnePass==ONEPASS_SINGLE ? "ONEPASS_SINGLE" : "ONEPASS_MULTI",
|
||||
aiCur[0], aiCur[1]);
|
||||
}
|
||||
#endif
|
||||
return pWInfo->eOnePass;
|
||||
}
|
||||
|
||||
@@ -182,13 +189,13 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
|
||||
while( pScan->iEquiv<=pScan->nEquiv ){
|
||||
iCur = pScan->aiCur[pScan->iEquiv-1];
|
||||
iColumn = pScan->aiColumn[pScan->iEquiv-1];
|
||||
if( iColumn==(-2) && pScan->pIdxExpr==0 ) return 0;
|
||||
if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0;
|
||||
while( (pWC = pScan->pWC)!=0 ){
|
||||
for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
|
||||
if( pTerm->leftCursor==iCur
|
||||
&& pTerm->u.leftColumn==iColumn
|
||||
&& (iColumn!=(-2)
|
||||
|| sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0)
|
||||
&& (iColumn!=XN_EXPR
|
||||
|| sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0)
|
||||
&& (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin))
|
||||
){
|
||||
if( (pTerm->eOperator & WO_EQUIV)!=0
|
||||
@@ -281,7 +288,7 @@ static WhereTerm *whereScanInit(
|
||||
if( pIdx ){
|
||||
j = iColumn;
|
||||
iColumn = pIdx->aiColumn[j];
|
||||
if( iColumn==(-2) ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
|
||||
if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
|
||||
}
|
||||
if( pIdx && iColumn>=0 ){
|
||||
pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
|
||||
@@ -720,7 +727,7 @@ static void constructAutomaticIndex(
|
||||
}
|
||||
}
|
||||
assert( n==nKeyCol );
|
||||
pIdx->aiColumn[n] = -1;
|
||||
pIdx->aiColumn[n] = XN_ROWID;
|
||||
pIdx->azColl[n] = "BINARY";
|
||||
|
||||
/* Create the automatic index */
|
||||
@@ -1159,6 +1166,7 @@ static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){
|
||||
** Return the affinity for a single column of an index.
|
||||
*/
|
||||
static char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){
|
||||
assert( iCol>=0 && iCol<pIdx->nColumn );
|
||||
if( !pIdx->zColAff ){
|
||||
if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB;
|
||||
}
|
||||
@@ -1216,8 +1224,7 @@ static int whereRangeSkipScanEst(
|
||||
int nLower = -1;
|
||||
int nUpper = p->nSample+1;
|
||||
int rc = SQLITE_OK;
|
||||
int iCol = p->aiColumn[nEq];
|
||||
u8 aff = sqlite3IndexColumnAffinity(db, p, iCol);
|
||||
u8 aff = sqlite3IndexColumnAffinity(db, p, nEq);
|
||||
CollSeq *pColl;
|
||||
|
||||
sqlite3_value *p1 = 0; /* Value extracted from pLower */
|
||||
@@ -2235,7 +2242,9 @@ static int whereLoopAddBtreeIndex(
|
||||
int iCol = pProbe->aiColumn[saved_nEq];
|
||||
pNew->wsFlags |= WHERE_COLUMN_EQ;
|
||||
assert( saved_nEq==pNew->u.btree.nEq );
|
||||
if( iCol==(-1) || (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) ){
|
||||
if( iCol==XN_ROWID
|
||||
|| (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
|
||||
){
|
||||
if( iCol>=0 && pProbe->uniqNotNull==0 ){
|
||||
pNew->wsFlags |= WHERE_UNQ_WANTED;
|
||||
}else{
|
||||
@@ -2421,18 +2430,25 @@ static int indexMightHelpWithOrderBy(
|
||||
int iCursor
|
||||
){
|
||||
ExprList *pOB;
|
||||
ExprList *aColExpr;
|
||||
int ii, jj;
|
||||
|
||||
if( pIndex->bUnordered ) return 0;
|
||||
if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0;
|
||||
for(ii=0; ii<pOB->nExpr; ii++){
|
||||
Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr);
|
||||
if( pExpr->op!=TK_COLUMN ) return 0;
|
||||
if( pExpr->iTable==iCursor ){
|
||||
if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){
|
||||
if( pExpr->iColumn<0 ) return 1;
|
||||
for(jj=0; jj<pIndex->nKeyCol; jj++){
|
||||
if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1;
|
||||
}
|
||||
}else if( (aColExpr = pIndex->aColExpr)!=0 ){
|
||||
for(jj=0; jj<pIndex->nKeyCol; jj++){
|
||||
if( pIndex->aiColumn[jj]!=XN_EXPR ) continue;
|
||||
if( sqlite3ExprCompare(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -2580,7 +2596,7 @@ static int whereLoopAddBtree(
|
||||
&& (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
|
||||
&& pSrc->pIBIndex==0 /* Has no INDEXED BY clause */
|
||||
&& !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */
|
||||
&& HasRowid(pTab) /* Is not a WITHOUT ROWID table. (FIXME: Why not?) */
|
||||
&& HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */
|
||||
&& !pSrc->fg.isCorrelated /* Not a correlated subquery */
|
||||
&& !pSrc->fg.isRecursive /* Not a recursive common table expression. */
|
||||
){
|
||||
@@ -2825,6 +2841,7 @@ static int whereLoopAddVirtual(
|
||||
pIdxInfo->orderByConsumed = 0;
|
||||
pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
|
||||
pIdxInfo->estimatedRows = 25;
|
||||
pIdxInfo->idxFlags = 0;
|
||||
rc = vtabBestIndex(pParse, pTab, pIdxInfo);
|
||||
if( rc ) goto whereLoopAddVtab_exit;
|
||||
pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
|
||||
@@ -2870,6 +2887,7 @@ static int whereLoopAddVirtual(
|
||||
** (2) Multiple outputs from a single IN value will not merge
|
||||
** together. */
|
||||
pIdxInfo->orderByConsumed = 0;
|
||||
pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2885,6 +2903,14 @@ static int whereLoopAddVirtual(
|
||||
pNew->rSetup = 0;
|
||||
pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
|
||||
pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows);
|
||||
|
||||
/* Set the WHERE_ONEROW flag if the xBestIndex() method indicated
|
||||
** that the scan will visit at most one row. Clear it otherwise. */
|
||||
if( pIdxInfo->idxFlags & SQLITE_INDEX_SCAN_UNIQUE ){
|
||||
pNew->wsFlags |= WHERE_ONEROW;
|
||||
}else{
|
||||
pNew->wsFlags &= ~WHERE_ONEROW;
|
||||
}
|
||||
whereLoopInsert(pBuilder, pNew);
|
||||
if( pNew->u.vtab.needFree ){
|
||||
sqlite3_free(pNew->u.vtab.idxStr);
|
||||
@@ -3206,7 +3232,8 @@ static i8 wherePathSatisfiesOrderBy(
|
||||
nKeyCol = pIndex->nKeyCol;
|
||||
nColumn = pIndex->nColumn;
|
||||
assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
|
||||
assert( pIndex->aiColumn[nColumn-1]==(-1) || !HasRowid(pIndex->pTable));
|
||||
assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
|
||||
|| !HasRowid(pIndex->pTable));
|
||||
isOrderDistinct = IsUniqueIndex(pIndex);
|
||||
}
|
||||
|
||||
@@ -3238,7 +3265,7 @@ static i8 wherePathSatisfiesOrderBy(
|
||||
revIdx = pIndex->aSortOrder[j];
|
||||
if( iColumn==pIndex->pTable->iPKey ) iColumn = -1;
|
||||
}else{
|
||||
iColumn = -1;
|
||||
iColumn = XN_ROWID;
|
||||
revIdx = 0;
|
||||
}
|
||||
|
||||
@@ -3264,9 +3291,15 @@ static i8 wherePathSatisfiesOrderBy(
|
||||
testcase( wctrlFlags & WHERE_GROUPBY );
|
||||
testcase( wctrlFlags & WHERE_DISTINCTBY );
|
||||
if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
|
||||
if( pOBExpr->op!=TK_COLUMN ) continue;
|
||||
if( pOBExpr->iTable!=iCur ) continue;
|
||||
if( pOBExpr->iColumn!=iColumn ) continue;
|
||||
if( iColumn>=(-1) ){
|
||||
if( pOBExpr->op!=TK_COLUMN ) continue;
|
||||
if( pOBExpr->iTable!=iCur ) continue;
|
||||
if( pOBExpr->iColumn!=iColumn ) continue;
|
||||
}else{
|
||||
if( sqlite3ExprCompare(pOBExpr,pIndex->aColExpr->a[j].pExpr,iCur) ){
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( iColumn>=0 ){
|
||||
pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
|
||||
if( !pColl ) pColl = db->pDfltColl;
|
||||
@@ -4097,7 +4130,8 @@ WhereInfo *sqlite3WhereBegin(
|
||||
}
|
||||
|
||||
/* Construct the WhereLoop objects */
|
||||
WHERETRACE(0xffff,("*** Optimizer Start ***\n"));
|
||||
WHERETRACE(0xffff,("*** Optimizer Start *** (wctrlFlags: 0x%x)\n",
|
||||
wctrlFlags));
|
||||
#if defined(WHERETRACE_ENABLED)
|
||||
if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */
|
||||
int i;
|
||||
@@ -4519,7 +4553,10 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
}else if( pLoop->wsFlags & WHERE_MULTI_OR ){
|
||||
pIdx = pLevel->u.pCovidx;
|
||||
}
|
||||
if( pIdx && !db->mallocFailed ){
|
||||
if( pIdx
|
||||
&& (pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable))
|
||||
&& !db->mallocFailed
|
||||
){
|
||||
last = sqlite3VdbeCurrentAddr(v);
|
||||
k = pLevel->addrBody;
|
||||
pOp = sqlite3VdbeGetOp(v, k);
|
||||
@@ -4531,6 +4568,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
if( !HasRowid(pTab) ){
|
||||
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
x = pPk->aiColumn[x];
|
||||
assert( x>=0 );
|
||||
}
|
||||
x = sqlite3ColumnOfIndex(pIdx, x);
|
||||
if( x>=0 ){
|
||||
|
||||
Reference in New Issue
Block a user