mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Ensure that queries like "SELECT indeterministic(a) FROM tbl GROUP BY 1" invoke the indeterministic function only once for each row of tbl.
FossilOrigin-Name: 4555d66547e28cb110e1012b145bcf3aafb5d4bde05e9d27bcb4ca33837b28f5
This commit is contained in:
@ -4243,7 +4243,7 @@ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
|
||||
** register iReg. The caller must ensure that iReg already contains
|
||||
** the correct value for the expression.
|
||||
*/
|
||||
static void exprToRegister(Expr *pExpr, int iReg){
|
||||
void sqlite3ExprToRegister(Expr *pExpr, int iReg){
|
||||
Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
|
||||
if( NEVER(p==0) ) return;
|
||||
p->op2 = p->op;
|
||||
@ -5252,7 +5252,7 @@ expr_code_doover:
|
||||
break;
|
||||
}
|
||||
testcase( pX->op==TK_COLUMN );
|
||||
exprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
|
||||
sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
|
||||
testcase( regFree1==0 );
|
||||
memset(&opCompare, 0, sizeof(opCompare));
|
||||
opCompare.op = TK_EQ;
|
||||
@ -5602,7 +5602,7 @@ static void exprCodeBetween(
|
||||
compRight.op = TK_LE;
|
||||
compRight.pLeft = pDel;
|
||||
compRight.pRight = pExpr->x.pList->a[1].pExpr;
|
||||
exprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
|
||||
sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
|
||||
if( xJump ){
|
||||
xJump(pParse, &exprAnd, dest, jumpIfNull);
|
||||
}else{
|
||||
|
14
src/select.c
14
src/select.c
@ -7847,12 +7847,18 @@ int sqlite3Select(
|
||||
*/
|
||||
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
|
||||
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
|
||||
&& OptimizationEnabled(db, SQLITE_GroupByOrder)
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
&& p->pWin==0
|
||||
#endif
|
||||
){
|
||||
p->selFlags &= ~SF_Distinct;
|
||||
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
|
||||
if( pGroupBy ){
|
||||
for(i=0; i<pGroupBy->nExpr; i++){
|
||||
pGroupBy->a[i].u.x.iOrderByCol = i+1;
|
||||
}
|
||||
}
|
||||
p->selFlags |= SF_Aggregate;
|
||||
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
|
||||
** the sDistinct.isTnct is still set. Hence, isTnct represents the
|
||||
@ -8315,12 +8321,18 @@ int sqlite3Select(
|
||||
sortOut, sortPTab);
|
||||
}
|
||||
for(j=0; j<pGroupBy->nExpr; j++){
|
||||
int iOrderByCol = pGroupBy->a[j].u.x.iOrderByCol;
|
||||
|
||||
if( groupBySort ){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
|
||||
}else{
|
||||
pAggInfo->directMode = 1;
|
||||
sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
|
||||
}
|
||||
|
||||
if( iOrderByCol ){
|
||||
sqlite3ExprToRegister(p->pEList->a[iOrderByCol-1].pExpr, iAMem+j);
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
|
||||
(char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
|
||||
@ -8336,9 +8348,9 @@ int sqlite3Select(
|
||||
** and resets the aggregate accumulator registers in preparation
|
||||
** for the next GROUP BY batch.
|
||||
*/
|
||||
sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
|
||||
VdbeComment((v, "output one row"));
|
||||
sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
|
||||
sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v);
|
||||
VdbeComment((v, "check abort flag"));
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
|
||||
|
@ -5025,6 +5025,7 @@ void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
|
||||
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
|
||||
void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
|
||||
void sqlite3ExprCodeMove(Parse*, int, int, int);
|
||||
void sqlite3ExprToRegister(Expr *pExpr, int iReg);
|
||||
void sqlite3ExprCode(Parse*, Expr*, int);
|
||||
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
||||
void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int);
|
||||
|
Reference in New Issue
Block a user