1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-12 13:01:09 +03:00

Reenable the SQLITE_EXPR_REF optimization for "SELECT DISTINCT ... ORDER BY"

queries.

FossilOrigin-Name: 6e2e9d383f5fc4a0cbf05fe83ec7425812c0f556
This commit is contained in:
dan
2016-11-11 18:08:59 +00:00
parent 257c13fa00
commit 9af90b7231
3 changed files with 25 additions and 20 deletions

View File

@@ -521,7 +521,7 @@ static void pushOntoSorter(
int iLimit; /* LIMIT counter */
assert( bSeq==0 || bSeq==1 );
assert( nData==1 || regData==regOrigData );
assert( nData==1 || regData==regOrigData || regOrigData==0 );
if( nPrefixReg ){
assert( nPrefixReg==nExpr+bSeq );
regBase = regData - nExpr - bSeq;
@@ -533,7 +533,7 @@ static void pushOntoSorter(
iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit;
pSort->labelDone = sqlite3VdbeMakeLabel(v);
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData,
SQLITE_ECEL_DUP);
SQLITE_ECEL_DUP | (regOrigData? SQLITE_ECEL_REF : 0));
if( bSeq ){
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
}
@@ -681,13 +681,20 @@ static void selectInnerLoop(
){
Vdbe *v = pParse->pVdbe;
int i;
int hasDistinct; /* True if the DISTINCT keyword is present */
int regResult; /* Start of memory holding result set */
int hasDistinct; /* True if the DISTINCT keyword is present */
int eDest = pDest->eDest; /* How to dispose of results */
int iParm = pDest->iSDParm; /* First argument to disposal method */
int nResultCol; /* Number of result columns */
int nPrefixReg = 0; /* Number of extra registers before regResult */
/* Usually, regResult is the first cell in an array of memory cells
** containing the current result row. In this case regOrig is set to the
** same value. However, if the results are being sent to the sorter, the
** values for any expressions that are also part of the sort-key are omitted
** from this array. In this case regOrig is set to zero. */
int regResult; /* Start of memory holding current results */
int regOrig; /* Start of memory holding full result (or 0) */
assert( v );
assert( pEList!=0 );
hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP;
@@ -718,7 +725,7 @@ static void selectInnerLoop(
pParse->nMem += nResultCol;
}
pDest->nSdst = nResultCol;
regResult = pDest->iSdst;
regOrig = regResult = pDest->iSdst;
if( srcTab>=0 ){
for(i=0; i<nResultCol; i++){
sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
@@ -734,7 +741,8 @@ static void selectInnerLoop(
}else{
ecelFlags = 0;
}
if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab && eDest!=SRT_Table ){
assert( eDest!=SRT_Table || pSort==0 );
if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab ){
/* For each expression in pEList that is a copy of an expression in
** the ORDER BY clause (pSort->pOrderBy), set the associated
** iOrderByCol value to one more than the index of the ORDER BY
@@ -748,7 +756,7 @@ static void selectInnerLoop(
pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat;
}
}
regOrig = 0;
assert( eDest==SRT_Set || eDest==SRT_Mem
|| eDest==SRT_Coroutine || eDest==SRT_Output );
}
@@ -892,7 +900,7 @@ static void selectInnerLoop(
** does not matter. But there might be a LIMIT clause, in which
** case the order does matter */
pushOntoSorter(
pParse, pSort, p, regResult, regResult, nResultCol, nPrefixReg);
pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
}else{
int r1 = sqlite3GetTempReg(pParse);
assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
@@ -921,7 +929,7 @@ static void selectInnerLoop(
if( pSort ){
assert( nResultCol<=pDest->nSdst );
pushOntoSorter(
pParse, pSort, p, regResult, regResult, nResultCol, nPrefixReg);
pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
}else{
assert( nResultCol==pDest->nSdst );
assert( regResult==iParm );
@@ -936,7 +944,7 @@ static void selectInnerLoop(
testcase( eDest==SRT_Coroutine );
testcase( eDest==SRT_Output );
if( pSort ){
pushOntoSorter(pParse, pSort, p, regResult, regResult, nResultCol,
pushOntoSorter(pParse, pSort, p, regResult, regOrig, nResultCol,
nPrefixReg);
}else if( eDest==SRT_Coroutine ){
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);