diff options
author | dan <dan@noemail.net> | 2016-11-10 20:14:06 +0000 |
---|---|---|
committer | dan <dan@noemail.net> | 2016-11-10 20:14:06 +0000 |
commit | 257c13fa008b2033960e60927d180f2ebbe1fdca (patch) | |
tree | e5c0f947ddb9c5633ffe88013f35aa249ad948d5 /src | |
parent | 58282f68d88e6c9ff907988a99ff67d8c473f137 (diff) | |
download | sqlite-257c13fa008b2033960e60927d180f2ebbe1fdca.tar.gz sqlite-257c13fa008b2033960e60927d180f2ebbe1fdca.zip |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 9 | ||||
-rw-r--r-- | src/select.c | 42 | ||||
-rw-r--r-- | src/sqliteInt.h | 1 |
3 files changed, 41 insertions, 11 deletions
diff --git a/src/expr.c b/src/expr.c index c2b9c8fe4..165bb30f7 100644 --- a/src/expr.c +++ b/src/expr.c @@ -4086,8 +4086,13 @@ int sqlite3ExprCodeExprList( if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR; for(pItem=pList->a, i=0; i<n; i++, pItem++){ Expr *pExpr = pItem->pExpr; - if( (flags & SQLITE_ECEL_REF)!=0 && (j = pList->a[i].u.x.iOrderByCol)>0 ){ - sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); + if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){ + if( flags & SQLITE_ECEL_OMITREF ){ + i--; + n--; + }else{ + sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); + } }else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){ sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0); }else{ diff --git a/src/select.c b/src/select.c index 199e13f11..003d42e72 100644 --- a/src/select.c +++ b/src/select.c @@ -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 ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index c0e5aa01b..88662958d 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3706,6 +3706,7 @@ int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8); #define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */ #define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */ #define SQLITE_ECEL_REF 0x04 /* Use ExprList.u.x.iOrderByCol */ +#define SQLITE_ECEL_OMITREF 0x08 /* Omit if ExprList.u.x.iOrderByCol */ void sqlite3ExprIfTrue(Parse*, Expr*, int, int); void sqlite3ExprIfFalse(Parse*, Expr*, int, int); void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int); |