-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
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
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
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
-2869ed28299b1c9f355ecc24635830f7f1249126
\ No newline at end of file
+bab2e560f6cb989c83a96aad60f666960ede7abe
\ No newline at end of file
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 ){
}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: {
/* 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);
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.
*/
#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 */
/*
*/
case OP_OpenSorter:
case OP_OpenAutoindex:
+case OP_SorterOpen:
case OP_OpenEphemeral: {
VdbeCursor *pCx;
static const int vfsFlags =
}
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);
** 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;
/* Note that RowKey and RowData are really exactly the same instruction */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
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 );
** 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++;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
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);
** 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;
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);
** 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;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
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;
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 */
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 ){