From: drh Date: Thu, 1 Sep 2011 15:32:47 +0000 (+0000) Subject: Experimental code-generator changes to utilize new opcodes for sorting. X-Git-Tag: version-3.7.8~22^2~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c6aff30ca470f67c72c3a133ad3616989657fcec;p=thirdparty%2Fsqlite.git Experimental code-generator changes to utilize new opcodes for sorting. FossilOrigin-Name: bab2e560f6cb989c83a96aad60f666960ede7abe --- diff --git a/manifest b/manifest index cf95f75fde..b233b88396 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\susing\suninitialized\svariables\safter\sfailures\sin\sthe\smerge\ssort\scode. -D 2011-08-31T23:57:22.695 +C Experimental\scode-generator\schanges\sto\sutilize\snew\sopcodes\sfor\ssorting. +D 2011-09-01T15:32:47.873 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in d314143fa6be24828021d3f583ad37d9afdce505 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -179,11 +179,11 @@ F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 36368f44569208fa074e61f4dd0b6c4fb60ca2b4 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 -F src/select.c 14552e9ff4b27ec027a43fafb62ea5d049cd2809 +F src/select.c 20bef6860c5f69c6a90666b4968d4c5cb88056c0 F src/shell.c bbe7818ff5bc8614105ceb81ad67b8bdc0b671dd F src/sqlite.h.in 0a6c9c23337fd1352c5c75a613ff9533aa7d91cb F src/sqlite3ext.h 1a1a4f784aa9c3b00edd287940197de52487cd93 -F src/sqliteInt.h 86a4fdb3ba9ab31d98b266797606f30fefe5b8a9 +F src/sqliteInt.h f6debf9a9eb8463ab2ef8be4b2b740ea9af5afba F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -238,11 +238,11 @@ F src/update.c 74a6cfb34e9732c1e2a86278b229913b4b51eeec F src/utf.c c53eb7404b3eb5c1cbb5655c6a7a0e0ce6bd50f0 F src/util.c 06302ffd2b80408d4f6c7af71f7090e0cf8d8ff7 F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e -F src/vdbe.c 9165b35da939f4a66c7e68b0c6d3f017ca982cb1 +F src/vdbe.c 9260e5138855399bea2611a29da336688bfa1b79 F src/vdbe.h c1eeedacab6bcf1e7c2cf8203ba9763a616f9a86 -F src/vdbeInt.h 70767f6504aac4f0057ec2a55738470a890789ac +F src/vdbeInt.h 51a902e12c7d571e3b516e5407e30f996494aafe F src/vdbeapi.c 11dc47987abacb76ad016dcf5abc0dc422482a98 -F src/vdbeaux.c de1e4cab060a45df9ebee68dd63543d14559f0e7 +F src/vdbeaux.c e58acbc5ea3823922a0cd8fa21f94f39af51ee88 F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3 F src/vdbemem.c 5e6effb96dd53d233361cbfaa3f0a43b9af689e9 F src/vdbesort.c f3d043a1bab7409d4a23cd7a35287c3ac440a167 @@ -961,7 +961,10 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5 F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh b7fdb2cc525f5ef4fa43c80e771636dd3690f9d2 -P 70b5b309568ac55565558d5456aca1e431cfd26b -R 09e04eb9163c46e529a61f2438cff2a1 +P 2869ed28299b1c9f355ecc24635830f7f1249126 +R e08eee2093eee8a9fb40d6646a4c9c76 +T *branch * merge-sort +T *sym-merge-sort * +T -sym-trunk * U drh -Z bdb2832352809bf647849d42b7aa6060 +Z c5e8ef1774d371c2becb6d0057b76727 diff --git a/manifest.uuid b/manifest.uuid index 67e9d42efe..c35621c659 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2869ed28299b1c9f355ecc24635830f7f1249126 \ No newline at end of file +bab2e560f6cb989c83a96aad60f666960ede7abe \ No newline at end of file diff --git a/src/select.c b/src/select.c index 2e44522c6d..8825326594 100644 --- a/src/select.c +++ b/src/select.c @@ -419,12 +419,18 @@ static void pushOntoSorter( int nExpr = pOrderBy->nExpr; int regBase = sqlite3GetTempRange(pParse, nExpr+2); int regRecord = sqlite3GetTempReg(pParse); + int op; sqlite3ExprCacheClear(pParse); sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0); sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr); sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord); - sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord); + if( pSelect->selFlags & SF_UseSorter ){ + op = OP_SorterInsert; + }else{ + op = OP_IdxInsert; + } + sqlite3VdbeAddOp2(v, op, pOrderBy->iECursor, regRecord); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempRange(pParse, regBase, nExpr+2); if( pSelect->iLimit ){ @@ -893,9 +899,20 @@ static void generateSortTail( }else{ regRowid = sqlite3GetTempReg(pParse); } - addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); - codeOffset(v, p, addrContinue); - sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr + 1, regRow); + if( p->selFlags & SF_UseSorter ){ + int regSortOut = sqlite3GetTempReg(pParse); + int ptab2 = pParse->nTab++; + sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, pOrderBy->nExpr+2); + addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); + codeOffset(v, p, addrContinue); + sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut); + sqlite3VdbeAddOp3(v, OP_Column, ptab2, pOrderBy->nExpr+1, regRow); + sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE); + }else{ + addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); + codeOffset(v, p, addrContinue); + sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr+1, regRow); + } switch( eDest ){ case SRT_Table: case SRT_EphemTab: { @@ -948,7 +965,11 @@ static void generateSortTail( /* The bottom of the loop */ sqlite3VdbeResolveLabel(v, addrContinue); - sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); + if( p->selFlags & SF_UseSorter ){ + sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); + }else{ + sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); + } sqlite3VdbeResolveLabel(v, addrBreak); if( eDest==SRT_Output || eDest==SRT_Coroutine ){ sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0); @@ -3914,6 +3935,10 @@ int sqlite3Select( iEnd = sqlite3VdbeMakeLabel(v); p->nSelectRow = (double)LARGEST_INT64; computeLimitRegisters(pParse, p, iEnd); + if( p->iLimit==0 && addrSortIndex>=0 ){ + sqlite3VdbeGetOp(v, addrSortIndex)->opcode = OP_SorterOpen; + p->selFlags |= SF_UseSorter; + } /* Open a virtual index to use for the distinct set. */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5934c74316..18beb32e0f 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2082,6 +2082,7 @@ struct Select { #define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */ #define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */ #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ +#define SF_UseSorter 0x0040 /* Sort using a sorter */ /* diff --git a/src/vdbe.c b/src/vdbe.c index e7c7ed7fe2..f4ae4c44a6 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3170,6 +3170,7 @@ case OP_OpenWrite: { */ case OP_OpenSorter: case OP_OpenAutoindex: +case OP_SorterOpen: case OP_OpenEphemeral: { VdbeCursor *pCx; static const int vfsFlags = @@ -3214,6 +3215,7 @@ case OP_OpenEphemeral: { } pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); pCx->isIndex = !pCx->isTable; + pCx->isSorter = pOp->opcode==OP_SorterOpen; #ifndef SQLITE_OMIT_MERGE_SORT if( rc==SQLITE_OK && pOp->opcode==OP_OpenSorter ){ rc = sqlite3VdbeSorterInit(db, pCx); @@ -4090,6 +4092,7 @@ case OP_ResetCount: { ** If the P1 cursor must be pointing to a valid row (not a NULL row) ** of a real table, not a pseudo-table. */ +case OP_SorterData: case OP_RowKey: case OP_RowData: { VdbeCursor *pC; @@ -4103,11 +4106,12 @@ case OP_RowData: { /* Note that RowKey and RowData are really exactly the same instruction */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; - assert( pC->isTable || pOp->opcode==OP_RowKey ); + assert( pC->isTable || pOp->opcode!=OP_RowData ); assert( pC->isIndex || pOp->opcode==OP_RowData ); assert( pC!=0 ); assert( pC->nullRow==0 ); assert( pC->pseudoTableReg==0 ); + assert( pC->isSorter==(pOp->opcode==OP_SorterData) ); if( isSorter(pC) ){ assert( pOp->opcode==OP_RowKey ); @@ -4271,6 +4275,7 @@ case OP_Last: { /* jump */ ** regression tests can determine whether or not the optimizer is ** correctly optimizing out sorts. */ +case OP_SorterSort: /* jump */ case OP_Sort: { /* jump */ #ifdef SQLITE_TEST sqlite3_sort_count++; @@ -4295,6 +4300,7 @@ case OP_Rewind: { /* jump */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); + assert( pC->isSorter==(pOp->opcode==OP_SorterSort) ); res = 1; if( isSorter(pC) ){ rc = sqlite3VdbeSorterRewind(db, pC, &res); @@ -4347,6 +4353,7 @@ case OP_Rewind: { /* jump */ ** If P5 is positive and the jump is taken, then event counter ** number P5-1 in the prepared statement is incremented. */ +case OP_SorterNext: /* jump */ case OP_Prev: /* jump */ case OP_Next: { /* jump */ VdbeCursor *pC; @@ -4359,6 +4366,7 @@ case OP_Next: { /* jump */ if( pC==0 ){ break; /* See ticket #2273 */ } + assert( pC->isSorter==(pOp->opcode==OP_SorterNext) ); if( isSorter(pC) ){ assert( pOp->opcode==OP_Next ); rc = sqlite3VdbeSorterNext(db, pC, &res); @@ -4395,6 +4403,7 @@ case OP_Next: { /* jump */ ** This instruction only works for indices. The equivalent instruction ** for tables is OP_Insert. */ +case OP_SorterInsert: case OP_IdxInsert: { /* in2 */ VdbeCursor *pC; BtCursor *pCrsr; @@ -4404,6 +4413,7 @@ case OP_IdxInsert: { /* in2 */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); + assert( pC->isSorter==(pOp->opcode==OP_SorterInsert) ); pIn2 = &aMem[pOp->p2]; assert( pIn2->flags & MEM_Blob ); pCrsr = pC->pCursor; diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 846d807075..70d80c9d38 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -59,6 +59,7 @@ struct VdbeCursor { Bool isTable; /* True if a table requiring integer keys */ Bool isIndex; /* True if an index containing keys only - no data */ Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */ + Bool isSorter; /* True if a new-style sorter */ sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */ const sqlite3_module *pModule; /* Module for cursor pVtabCursor */ i64 seqCount; /* Sequence counter */ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 053d89f3b5..f622e8d09a 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -433,7 +433,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ n = pOp[-1].p1; if( n>nMaxArgs ) nMaxArgs = n; #endif - }else if( opcode==OP_Next ){ + }else if( opcode==OP_Next || opcode==OP_SorterNext ){ pOp->p4.xAdvance = sqlite3BtreeNext; pOp->p4type = P4_ADVANCE; }else if( opcode==OP_Prev ){