mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
Reuse the same materialization of a view when that view appears in a query
more than once, such as in a self-join. FossilOrigin-Name: 9e35c89dbe744312f612e507b51ff9a5bb656def75392d25bc19fc638548cd1e
This commit is contained in:
39
src/select.c
39
src/select.c
@@ -4950,6 +4950,32 @@ static void havingToWhere(
|
||||
sqlite3WalkExpr(&sWalker, pHaving);
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if the pThis entry of pTabList is a self-join of a prior view.
|
||||
** If it is, then return the SrcList_item for the prior view. If it is not,
|
||||
** then return 0.
|
||||
*/
|
||||
static struct SrcList_item *isSelfJoinView(
|
||||
SrcList *pTabList, /* Search for self-joins in this FROM clause */
|
||||
struct SrcList_item *pThis /* Search for prior reference to this subquery */
|
||||
){
|
||||
struct SrcList_item *pItem;
|
||||
for(pItem = pTabList->a; pItem<pThis; pItem++){
|
||||
if( pItem->pSelect==0 ) continue;
|
||||
if( pItem->fg.viaCoroutine ) continue;
|
||||
if( pItem->zName==0 ) continue;
|
||||
if( sqlite3_stricmp(pItem->zDatabase, pThis->zDatabase)!=0 ) continue;
|
||||
if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue;
|
||||
if( sqlite3ExprCompare(pThis->pSelect->pWhere, pItem->pSelect->pWhere, -1) ){
|
||||
/* The view was modified by some other optimization such as
|
||||
** pushDownWhereTerms() */
|
||||
continue;
|
||||
}
|
||||
return pItem;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code for the SELECT statement given in the p argument.
|
||||
**
|
||||
@@ -5184,6 +5210,8 @@ int sqlite3Select(
|
||||
int topAddr;
|
||||
int onceAddr = 0;
|
||||
int retAddr;
|
||||
struct SrcList_item *pPrior;
|
||||
|
||||
assert( pItem->addrFillSub==0 );
|
||||
pItem->regReturn = ++pParse->nMem;
|
||||
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
|
||||
@@ -5197,9 +5225,14 @@ int sqlite3Select(
|
||||
}else{
|
||||
VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
||||
}
|
||||
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
|
||||
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
|
||||
sqlite3Select(pParse, pSub, &dest);
|
||||
pPrior = isSelfJoinView(pTabList, pItem);
|
||||
if( pPrior ){
|
||||
sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
|
||||
}else{
|
||||
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
|
||||
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
|
||||
sqlite3Select(pParse, pSub, &dest);
|
||||
}
|
||||
pItem->pTab->nRowLogEst = pSub->nSelectRow;
|
||||
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
|
||||
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
|
||||
|
||||
Reference in New Issue
Block a user