]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Avoid unnecessary moving of content between registers during an ORDER BY.
authordrh <drh@noemail.net>
Mon, 24 Mar 2014 18:08:15 +0000 (18:08 +0000)
committerdrh <drh@noemail.net>
Mon, 24 Mar 2014 18:08:15 +0000 (18:08 +0000)
FossilOrigin-Name: 4f472accf072d9cb64f209923924b26f21b13d27

manifest
manifest.uuid
src/select.c

index feb6340a70aadbe892217f8426a75acf45b14f05..a1b753f05eab973f9e35f823897af426a9325214 100644 (file)
--- 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
index 36b51c0a51c8509eec6f8e177066e79c26132400..1c7384bd0a7ceb36f0892b4465737e006026a814 100644 (file)
@@ -1 +1 @@
-5d506743f541b022cde04a9606baa4680cdfd70b
\ No newline at end of file
+4f472accf072d9cb64f209923924b26f21b13d27
\ No newline at end of file
index 641a54faa2130fd8bd06e0f926eafeaf5b3b7d00..40fd59daabb3bdb50c9a2da04734d9a24a43ff23 100644 (file)
@@ -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{