mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-11 01:42:22 +03:00
Aggregates with GROUP BY now make use of expressions on indexes. This code
works and gets the correct answer for the test case in the ticket. Lots more testing and documentation is needed, however. FossilOrigin-Name: 8dcf9f2031c16f296d187fe876d4204c71fc96fec120984ff11b6d8b03d58a5f
This commit is contained in:
48
src/select.c
48
src/select.c
@@ -6222,7 +6222,7 @@ static void printAggInfo(AggInfo *pAggInfo){
|
||||
sqlite3TreeViewExpr(0, pAggInfo->aCol[ii].pCExpr, 0);
|
||||
}
|
||||
for(ii=0; ii<pAggInfo->nFunc; ii++){
|
||||
sqlite3DebugPrintf("agg-func[%d]: iMem=\n",
|
||||
sqlite3DebugPrintf("agg-func[%d]: iMem=%d\n",
|
||||
ii, AggInfoFuncReg(pAggInfo,ii));
|
||||
sqlite3TreeViewExpr(0, pAggInfo->aFunc[ii].pFExpr, 0);
|
||||
}
|
||||
@@ -6309,6 +6309,40 @@ static void optimizeAggregateUseOfIndexedExpr(
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Walker callback for aggregateConvertIndexedExprRefToColumn().
|
||||
*/
|
||||
static int aggregateIdxEprRefToColCallback(Walker *pWalker, Expr *pExpr){
|
||||
AggInfo *pAggInfo;
|
||||
struct AggInfo_col *pCol;
|
||||
if( pExpr->pAggInfo==0 ) return WRC_Continue;
|
||||
if( pExpr->op==TK_AGG_COLUMN ) return WRC_Continue;
|
||||
if( pExpr->op==TK_AGG_FUNCTION ) return WRC_Continue;
|
||||
pAggInfo = pExpr->pAggInfo;
|
||||
assert( pExpr->iAgg>=0 && pExpr->iAgg<pAggInfo->nColumn );
|
||||
pCol = &pAggInfo->aCol[pExpr->iAgg];
|
||||
pExpr->op = TK_AGG_COLUMN;
|
||||
pExpr->iTable = pCol->iTable;
|
||||
pExpr->iColumn = pCol->iColumn;
|
||||
return WRC_Prune;
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert every pAggInfo->aFunc[].pExpr such that any node within
|
||||
** those expressions that has pAppInfo set is changed into a TK_AGG_COLUMN
|
||||
** opcode.
|
||||
*/
|
||||
static void aggregateConvertIndexedExprRefToColumn(AggInfo *pAggInfo){
|
||||
int i;
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = aggregateIdxEprRefToColCallback;
|
||||
for(i=0; i<pAggInfo->nFunc; i++){
|
||||
sqlite3WalkExpr(&w, pAggInfo->aFunc[i].pFExpr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Allocate a block of registers so that there is one register for each
|
||||
** pAggInfo->aCol[] and pAggInfo->aFunc[] entry in pAggInfo. The first
|
||||
@@ -7669,6 +7703,18 @@ int sqlite3Select(
|
||||
pAggInfo->useSortingIdx = 1;
|
||||
}
|
||||
|
||||
if( pParse->pIdxEpr ){
|
||||
aggregateConvertIndexedExprRefToColumn(pAggInfo);
|
||||
#if TREETRACE_ENABLED
|
||||
if( sqlite3TreeTrace & 0x20 ){
|
||||
TREETRACE(0x20, pParse, p,
|
||||
("AggInfo function expressions converted to reference index\n"));
|
||||
sqlite3TreeViewSelect(0, p, 0);
|
||||
printAggInfo(pAggInfo);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If the index or temporary table used by the GROUP BY sort
|
||||
** will naturally deliver rows in the order required by the ORDER BY
|
||||
** clause, cancel the ephemeral table open coded earlier.
|
||||
|
||||
Reference in New Issue
Block a user