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

Avoid storing redundant fields in sorter records when the sort-key and data have

fields in common (as in "SELECT a FROM t1 ORDER BY 1").

FossilOrigin-Name: 0af62fdbd8e2aab14718ff8bcb5934f05463c176
This commit is contained in:
dan
2016-11-10 20:14:06 +00:00
parent 58282f68d8
commit 257c13fa00
5 changed files with 54 additions and 21 deletions

View File

@@ -533,11 +533,11 @@ 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_REF);
SQLITE_ECEL_DUP);
if( bSeq ){
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
}
if( nPrefixReg==0 ){
if( nPrefixReg==0 && nData>0 ){
sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord);
@@ -666,7 +666,7 @@ static void codeDistinct(
** If srcTab is negative, then the pEList expressions
** are evaluated in order to get the data for this row. If srcTab is
** zero or more, then data is pulled from srcTab and pEList is used only
** to get number columns and the datatype for each column.
** to get the number of columns and the collation sequence for each column.
*/
static void selectInnerLoop(
Parse *pParse, /* The parser context */
@@ -734,7 +734,25 @@ static void selectInnerLoop(
}else{
ecelFlags = 0;
}
sqlite3ExprCodeExprList(pParse, pEList, regResult, 0, ecelFlags);
if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab && eDest!=SRT_Table ){
/* 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
** expression within the sort-key that pushOntoSorter() will generate.
** This allows the pEList field to be omitted from the sorted record,
** saving space and CPU cycles. */
ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF);
for(i=pSort->nOBSat; i<pSort->pOrderBy->nExpr; i++){
int j;
if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){
pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat;
}
}
assert( eDest==SRT_Set || eDest==SRT_Mem
|| eDest==SRT_Coroutine || eDest==SRT_Output );
}
nResultCol = sqlite3ExprCodeExprList(pParse,pEList,regResult,0,ecelFlags);
}
/* If the DISTINCT keyword was present on the SELECT statement
@@ -900,11 +918,12 @@ static void selectInnerLoop(
** memory cells and break out of the scan loop.
*/
case SRT_Mem: {
assert( nResultCol==pDest->nSdst );
if( pSort ){
assert( nResultCol<=pDest->nSdst );
pushOntoSorter(
pParse, pSort, p, regResult, regResult, nResultCol, nPrefixReg);
}else{
assert( nResultCol==pDest->nSdst );
assert( regResult==iParm );
/* The LIMIT clause will jump out of the loop for us */
}
@@ -1202,14 +1221,13 @@ static void generateSortTail(
int iParm = pDest->iSDParm;
int regRow;
int regRowid;
int iCol;
int nKey;
int iSortTab; /* Sorter cursor to read from */
int nSortData; /* Trailing values to read from sorter */
int i;
int bSeq; /* True if sorter record includes seq. no. */
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
struct ExprList_item *aOutEx = p->pEList->a;
#endif
assert( addrBreak<0 );
if( pSort->labelBkOut ){
@@ -1247,8 +1265,14 @@ static void generateSortTail(
iSortTab = iTab;
bSeq = 1;
}
for(i=0; i<nSortData; i++){
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq+i, regRow+i);
for(i=0, iCol=nKey+bSeq; i<nSortData; i++){
int iRead;
if( aOutEx[i].u.x.iOrderByCol ){
iRead = aOutEx[i].u.x.iOrderByCol-1;
}else{
iRead = iCol++;
}
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i);
VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
}
switch( eDest ){