]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Much faster sorting when there are a large number of columns in the
authordrh <drh@noemail.net>
Fri, 17 Mar 2006 00:04:03 +0000 (00:04 +0000)
committerdrh <drh@noemail.net>
Fri, 17 Mar 2006 00:04:03 +0000 (00:04 +0000)
result set. (CVS 3141)

FossilOrigin-Name: 6b3717aeb4ac45a433f2a30bdd0264ed728676e1

manifest
manifest.uuid
src/select.c
src/sqliteInt.h
src/vdbe.c

index 4cc5bc6a972412ee998a9b0b08c4874e1a9cfe3a..1212a6771217241b4b19f2ac1ecd738fd0deba79 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\ssome\scompiler\swarnings.\s(CVS\s3140)
-D 2006-03-16T16:19:56
+C Much\sfaster\ssorting\swhen\sthere\sare\sa\slarge\snumber\sof\scolumns\sin\sthe\nresult\sset.\s(CVS\s3141)
+D 2006-03-17T00:04:03
 F Makefile.in 5d8dff443383918b700e495de42ec65bc1c8865b
 F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -66,11 +66,11 @@ F src/pragma.c 27d5e395c5d950931c7ac4fe610e7c2993e2fa55
 F src/prepare.c 6afd730cc8851c0920b5f9050294646b1c2ab28c
 F src/printf.c 341e488b549b1a41f83b05a69ce1d7a8258b624c
 F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261
-F src/select.c 38203fd2851e2accac1ece7a8f1ce68f1c6d86be
+F src/select.c c95d5cd4331f68d8de947586edb06dc710167317
 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c 7a4b16f85d8f6f25d917cdc3d0f7e18f84867adf
 F src/sqlite.h.in 0bf6f03f9a14dde5f3a4f87471840803acaa4497
-F src/sqliteInt.h 8c5788a32da5c0b8fdfddc1497b5b38ee3a2c17d
+F src/sqliteInt.h dba7385fa5a03148ffcf44536d65e263e07bb2e3
 F src/table.c f64ec4fbfe333f8df925bc6ba494f55e05b0e75e
 F src/tclsqlite.c d20bdf1822c47e367f5acd37823ffe67df40301c
 F src/test1.c d1f210f3a295670e5d82d620bea46fabc73bb0ea
@@ -89,7 +89,7 @@ F src/update.c 34add66fcd3301b33b6e4c4c813f4e408f7ee4a0
 F src/utf.c 1d51225bce1ea8d1978e8ab28e862a0c12c7a8e8
 F src/util.c 59389ed717f0fa9d8023b3f482ba09dcf41343a8
 F src/vacuum.c 5b37d0f436f8e1ffacd17934e44720b38d2247f9
-F src/vdbe.c 2c687d8cf6b75380ef26a8c9db047ce0e3fa7424
+F src/vdbe.c 0d19124eeb6c38bbc960f2676048652bb9134e99
 F src/vdbe.h 80ba1c391ec28180dd07a630577f50b22c2062da
 F src/vdbeInt.h 85cd5f81d38edb1b8f4786f407c77a7a3ba636fb
 F src/vdbeapi.c 7dc662e7c905ce666bb506dced932e0307115cbf
@@ -355,7 +355,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P 5048fae04227857c064c0ba48eb11bedeb467df0
-R 7208193fddae26aaa731b3eae4156afb
+P 6c5175bc0f98e4ce715b099394f3fdc878ed82e8
+R 33078041ea680509db177f2f08180f2d
 U drh
-Z 6d1979f8c99cc176c714b0360fc60414
+Z d6f3682faa4b50ddafbdf0b8d9e74c43
index 0a1b1094553f7c2edd5e6d926800e046cd66ca3c..213b57f2344d61c2ddfeb3965dd9a004dfd57633 100644 (file)
@@ -1 +1 @@
-6c5175bc0f98e4ce715b099394f3fdc878ed82e8
\ No newline at end of file
+6b3717aeb4ac45a433f2a30bdd0264ed728676e1
\ No newline at end of file
index b8bd5f538f3578672dbe1b1981d41499df7d1dd7..d1b6df2f73bae7ab89b1cb783683db3adf3aa8d1 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle SELECT statements in SQLite.
 **
-** $Id: select.c,v 1.307 2006/03/09 17:28:12 drh Exp $
+** $Id: select.c,v 1.308 2006/03/17 00:04:03 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -680,6 +680,7 @@ static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){
 ** routine generates the code needed to do that.
 */
 static void generateSortTail(
+  Parse *pParse,   /* Parsing context */
   Select *p,       /* The SELECT statement */
   Vdbe *v,         /* Generate code into this VDBE */
   int nColumn,     /* Number of columns of data */
@@ -690,11 +691,20 @@ static void generateSortTail(
   int cont = sqlite3VdbeMakeLabel(v);
   int addr;
   int iTab;
+  int pseudoTab;
   ExprList *pOrderBy = p->pOrderBy;
 
   iTab = pOrderBy->iECursor;
+  if( eDest==SRT_Callback || eDest==SRT_Subroutine ){
+    pseudoTab = pParse->nTab++;
+    sqlite3VdbeAddOp(v, OP_OpenPseudo, pseudoTab, 0);
+    sqlite3VdbeAddOp(v, OP_SetNumColumns, pseudoTab, nColumn);
+  }
   addr = 1 + sqlite3VdbeAddOp(v, OP_Sort, iTab, brk);
   codeOffset(v, p, cont, 0);
+  if( eDest==SRT_Callback || eDest==SRT_Subroutine ){
+    sqlite3VdbeAddOp(v, OP_Integer, 1, 0);
+  }
   sqlite3VdbeAddOp(v, OP_Column, iTab, pOrderBy->nExpr + 1);
   switch( eDest ){
     case SRT_Table:
@@ -724,17 +734,15 @@ static void generateSortTail(
     case SRT_Callback:
     case SRT_Subroutine: {
       int i;
-      sqlite3VdbeAddOp(v, OP_Integer, p->pEList->nExpr, 0);
-      sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
+      sqlite3VdbeAddOp(v, OP_Insert, pseudoTab, 0);
       for(i=0; i<nColumn; i++){
-        sqlite3VdbeAddOp(v, OP_Column, -1-i, i);
+        sqlite3VdbeAddOp(v, OP_Column, pseudoTab, i);
       }
       if( eDest==SRT_Callback ){
         sqlite3VdbeAddOp(v, OP_Callback, nColumn, 0);
       }else{
         sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm);
       }
-      sqlite3VdbeAddOp(v, OP_Pop, 2, 0);
       break;
     }
     default: {
@@ -755,6 +763,10 @@ static void generateSortTail(
   sqlite3VdbeResolveLabel(v, cont);
   sqlite3VdbeAddOp(v, OP_Next, iTab, addr);
   sqlite3VdbeResolveLabel(v, brk);
+  if( eDest==SRT_Callback || eDest==SRT_Subroutine ){
+    sqlite3VdbeAddOp(v, OP_Close, pseudoTab, 0);
+  }
+
 }
 
 /*
@@ -1964,7 +1976,7 @@ static int multiSelect(
       pKeyInfo->nField = nOrderByExpr;
       sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
       pKeyInfo = 0;
-      generateSortTail(p, v, p->pEList->nExpr, eDest, iParm);
+      generateSortTail(pParse, p, v, p->pEList->nExpr, eDest, iParm);
     }
 
     sqliteFree(pKeyInfo);
@@ -3253,7 +3265,7 @@ int sqlite3Select(
   ** and send them to the callback one by one.
   */
   if( pOrderBy ){
-    generateSortTail(p, v, pEList->nExpr, eDest, iParm);
+    generateSortTail(pParse, p, v, pEList->nExpr, eDest, iParm);
   }
 
 #ifndef SQLITE_OMIT_SUBQUERY
index dd637457992e1411d135525906fdfd784487efdd..93d7b9df1d67abcff2280b40202de769cdb9d349 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.489 2006/03/13 15:06:07 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.490 2006/03/17 00:04:04 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1639,7 +1639,7 @@ void sqlite3ChangeCookie(sqlite3*, Vdbe*, int);
 #else
 # define sqlite3TriggersExist(A,B,C,D,E,F) 0
 # define sqlite3DeleteTrigger(A)
-# define sqlite3DropTriggerPtr(A,B,C)
+# define sqlite3DropTriggerPtr(A,B)
 # define sqlite3UnlinkAndDeleteTrigger(A,B,C)
 # define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I) 0
 #endif
index 002c2df3c19c376db25220326db14a7828231f2a..c878de823634fa2b981a01bcefcd4953a9145ea9 100644 (file)
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.545 2006/03/13 14:28:05 drh Exp $
+** $Id: vdbe.c,v 1.546 2006/03/17 00:04:04 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -1921,6 +1921,7 @@ case OP_Column: {
   ** which is the number of records.
   */
   assert( p1<0 || p->apCsr[p1]!=0 );
+#if 0
   if( p1<0 ){
     /* Take the record off of the stack */
     Mem *pRec = &pTos[p1];
@@ -1933,7 +1934,9 @@ case OP_Column: {
     assert( pCnt->flags & MEM_Int );
     nField = pCnt->i;
     pCrsr = 0;
-  }else if( (pC = p->apCsr[p1])->pCursor!=0 ){
+  }else
+#endif
+  if( (pC = p->apCsr[p1])->pCursor!=0 ){
     /* The record is stored in a B-Tree */
     rc = sqlite3VdbeCursorMoveto(pC);
     if( rc ) goto abort_due_to_error;
@@ -1952,7 +1955,6 @@ case OP_Column: {
       sqlite3BtreeDataSize(pCrsr, &payloadSize);
     }
     nField = pC->nField;
-#ifndef SQLITE_OMIT_TRIGGER
   }else if( pC->pseudoTable ){
     /* The record is the sole entry of a pseudo-table */
     payloadSize = pC->nData;
@@ -1961,7 +1963,6 @@ case OP_Column: {
     assert( payloadSize==0 || zRec!=0 );
     nField = pC->nField;
     pCrsr = 0;
-#endif
   }else{
     zRec = 0;
     payloadSize = 0;
@@ -2111,7 +2112,7 @@ case OP_Column: {
 
   /* If we dynamically allocated space to hold the data (in the
   ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
-  ** dynamically allocated space over to the pTos structure rather.
+  ** dynamically allocated space over to the pTos structure.
   ** This prevents a memory copy.
   */
   if( (sMem.flags & MEM_Dyn)!=0 ){
@@ -2722,7 +2723,6 @@ case OP_OpenVirtual: {       /* no-push */
   break;
 }
 
-#ifndef SQLITE_OMIT_TRIGGER
 /* Opcode: OpenPseudo P1 * *
 **
 ** Open a new cursor that points to a fake table that contains a single
@@ -2731,7 +2731,9 @@ case OP_OpenVirtual: {       /* no-push */
 ** closed.
 **
 ** A pseudo-table created by this opcode is useful for holding the
-** NEW or OLD tables in a trigger.
+** NEW or OLD tables in a trigger.  Also used to hold the a single
+** row output from the sorter so that the row can be decomposed into
+** individual columns using the OP_Column opcode.
 */
 case OP_OpenPseudo: {       /* no-push */
   int i = pOp->p1;
@@ -2746,7 +2748,6 @@ case OP_OpenPseudo: {       /* no-push */
   pCx->isIndex = 0;
   break;
 }
-#endif
 
 /* Opcode: Close P1 * *
 **
@@ -3320,7 +3321,6 @@ case OP_Insert: {         /* no-push */
     }else{
       assert( pTos->flags & (MEM_Blob|MEM_Str) );
     }
-#ifndef SQLITE_OMIT_TRIGGER
     if( pC->pseudoTable ){
       sqliteFree(pC->pData);
       pC->iKey = iKey;
@@ -3337,11 +3337,8 @@ case OP_Insert: {         /* no-push */
       }
       pC->nullRow = 0;
     }else{
-#endif
       rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, pTos->z, pTos->n);
-#ifndef SQLITE_OMIT_TRIGGER
     }
-#endif
     
     pC->rowidIsValid = 0;
     pC->deferredMoveto = 0;
@@ -3498,12 +3495,10 @@ case OP_RowData: {
     }else{
       sqlite3BtreeData(pCrsr, 0, n, pTos->z);
     }
-#ifndef SQLITE_OMIT_TRIGGER
   }else if( pC->pseudoTable ){
     pTos->n = pC->nData;
     pTos->z = pC->pData;
     pTos->flags = MEM_Blob|MEM_Ephem;
-#endif
   }else{
     pTos->flags = MEM_Null;
   }