From: drh Date: Mon, 24 Mar 2014 18:08:15 +0000 (+0000) Subject: Avoid unnecessary moving of content between registers during an ORDER BY. X-Git-Tag: version-3.8.7~132^2~95^2~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fd0a2f9756745401f68fc0e76b868c682194d023;p=thirdparty%2Fsqlite.git Avoid unnecessary moving of content between registers during an ORDER BY. FossilOrigin-Name: 4f472accf072d9cb64f209923924b26f21b13d27 --- diff --git a/manifest b/manifest index feb6340a70..a1b753f05e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunnecessary\stemporary\sregister\sallocation. -D 2014-03-24T09:34:58.396 +C Avoid\sunnecessary\smoving\sof\scontent\sbetween\sregisters\sduring\san\sORDER\sBY. +D 2014-03-24T18:08:15.960 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -217,7 +217,7 @@ F src/printf.c e5a0005f8b3de21f85da6a709d2fbee76775bf4b F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 -F src/select.c a088183774c4efae4105076355ac4010c62390a8 +F src/select.c 7f4a1ef9c9e893ee6da160441cd773c951f3d44e F src/shell.c cee9f46f2688a261601b1fd3d7f4b3cddf9b5cdf F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e @@ -1157,7 +1157,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P e6c59d23316c83b318b1a94d9b28a5d321737fa5 -R ab9aa4f9f7d5ea8c370ac77061403538 -U dan -Z 631d6a70f4aeb5d6a455a81761c8aefd +P 5d506743f541b022cde04a9606baa4680cdfd70b +R edfc832bbac864fb9d0e2cb38ae7f098 +U drh +Z a04be0daeb9646c039a07b2f019c65a9 diff --git a/manifest.uuid b/manifest.uuid index 36b51c0a51..1c7384bd0a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5d506743f541b022cde04a9606baa4680cdfd70b \ No newline at end of file +4f472accf072d9cb64f209923924b26f21b13d27 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 641a54faa2..40fd59daab 100644 --- a/src/select.c +++ b/src/select.c @@ -463,19 +463,28 @@ static void pushOntoSorter( SortCtx *pSort, /* Information about the ORDER BY clause */ Select *pSelect, /* The whole SELECT statement */ int regData, /* First register holding data to be sorted */ - int nData /* Number of elements in the data array */ + int nData, /* Number of elements in the data array */ + int nPrefixReg /* No. of reg prior to regData available for use */ ){ Vdbe *v = pParse->pVdbe; /* Stmt under construction */ int nExpr = pSort->pOrderBy->nExpr; /* No. of ORDER BY terms */ int nBase = nExpr + 1 + nData; /* Fields in sorter record */ - int regBase = sqlite3GetTempRange(pParse, nBase); /* Regs for sorter record */ + int regBase; /* Regs for sorter record */ int regRecord = sqlite3GetTempReg(pParse); /* Assemblied sorter record */ int nOBSat = pSort->nOBSat; /* No. ORDER BY terms to skip */ int op; /* Opcode to add sorter record to sorter */ + if( nPrefixReg ){ + assert( nPrefixReg==nExpr+1 ); + regBase = regData - nExpr - 1; + }else{ + regBase = sqlite3GetTempRange(pParse, nBase); + } sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, SQLITE_ECEL_DUP); sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr); - sqlite3VdbeAddOp3(v, OP_Move, regData, regBase+nExpr+1, nData); + if( nPrefixReg==0 ){ + sqlite3VdbeAddOp3(v, OP_Move, regData, regBase+nExpr+1, nData); + } sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord); if( nOBSat>0 ){ int regPrevKey; /* The first nOBSat columns of the previous row */ @@ -515,7 +524,9 @@ static void pushOntoSorter( sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord); if( nOBSat==0 ){ sqlite3ReleaseTempReg(pParse, regRecord); - sqlite3ReleaseTempRange(pParse, regBase, nBase); + if( nPrefixReg==0 ){ + sqlite3ReleaseTempRange(pParse, regBase, nBase); + } } if( pSelect->iLimit ){ int addr1, addr2; @@ -631,6 +642,7 @@ static void selectInnerLoop( 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 */ assert( v ); assert( pEList!=0 ); @@ -646,6 +658,10 @@ static void selectInnerLoop( nResultCol = pEList->nExpr; if( pDest->iSdst==0 ){ + if( pSort ){ + nPrefixReg = pSort->pOrderBy->nExpr + 1; + pParse->nMem += nPrefixReg; + } pDest->iSdst = pParse->nMem+1; pParse->nMem += nResultCol; }else if( pDest->iSdst+nResultCol > pParse->nMem ){ @@ -762,10 +778,10 @@ static void selectInnerLoop( case SRT_DistFifo: case SRT_Table: case SRT_EphemTab: { - int r1 = sqlite3GetTempReg(pParse); + int r1 = sqlite3GetTempRange(pParse, nPrefixReg+1); testcase( eDest==SRT_Table ); testcase( eDest==SRT_EphemTab ); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg); #ifndef SQLITE_OMIT_CTE if( eDest==SRT_DistFifo ){ /* If the destination is DistFifo, then cursor (iParm+1) is open @@ -780,7 +796,7 @@ static void selectInnerLoop( } #endif if( pSort ){ - pushOntoSorter(pParse, pSort, p, r1, 1); + pushOntoSorter(pParse, pSort, p, r1+nPrefixReg, 1, nPrefixReg); }else{ int r2 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); @@ -788,7 +804,7 @@ static void selectInnerLoop( sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3ReleaseTempReg(pParse, r2); } - sqlite3ReleaseTempReg(pParse, r1); + sqlite3ReleaseTempRange(pParse, r1, nPrefixReg+1); break; } @@ -806,7 +822,7 @@ static void selectInnerLoop( ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ - pushOntoSorter(pParse, pSort, p, regResult, 1); + pushOntoSorter(pParse, pSort, p, regResult, 1, nPrefixReg); }else{ int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1); @@ -832,7 +848,7 @@ static void selectInnerLoop( case SRT_Mem: { assert( nResultCol==1 ); if( pSort ){ - pushOntoSorter(pParse, pSort, p, regResult, 1); + pushOntoSorter(pParse, pSort, p, regResult, 1, nPrefixReg); }else{ sqlite3ExprCodeMove(pParse, regResult, iParm, 1); /* The LIMIT clause will jump out of the loop for us */ @@ -846,7 +862,7 @@ static void selectInnerLoop( testcase( eDest==SRT_Coroutine ); testcase( eDest==SRT_Output ); if( pSort ){ - pushOntoSorter(pParse, pSort, p, regResult, nResultCol); + pushOntoSorter(pParse, pSort, p, regResult, nResultCol, nPrefixReg); }else if( eDest==SRT_Coroutine ){ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); }else{