Index: src/vdbesort.c ================================================================== --- src/vdbesort.c +++ src/vdbesort.c @@ -885,34 +885,28 @@ ** Free all resources owned by the object indicated by argument pTask. All ** fields of *pTask are zeroed before returning. */ static void vdbeSortSubtaskCleanup(sqlite3 *db, SortSubtask *pTask){ sqlite3DbFree(db, pTask->pUnpacked); - pTask->pUnpacked = 0; #if SQLITE_MAX_WORKER_THREADS>0 /* pTask->list.aMemory can only be non-zero if it was handed memory ** from the main thread. That only occurs SQLITE_MAX_WORKER_THREADS>0 */ if( pTask->list.aMemory ){ sqlite3_free(pTask->list.aMemory); - pTask->list.aMemory = 0; }else #endif { assert( pTask->list.aMemory==0 ); vdbeSorterRecordFree(0, pTask->list.pList); } - pTask->list.pList = 0; if( pTask->file.pFd ){ sqlite3OsCloseFree(pTask->file.pFd); - pTask->file.pFd = 0; - pTask->file.iEof = 0; } if( pTask->file2.pFd ){ sqlite3OsCloseFree(pTask->file2.pFd); - pTask->file2.pFd = 0; - pTask->file2.iEof = 0; } + memset(pTask, 0, sizeof(SortSubtask)); } #ifdef SQLITE_DEBUG_SORTER_THREADS static void vdbeSorterWorkDebug(SortSubtask *pTask, const char *zEvent){ i64 t; @@ -1088,10 +1082,11 @@ vdbeMergeEngineFree(pSorter->pMerger); pSorter->pMerger = 0; for(i=0; inTask; i++){ SortSubtask *pTask = &pSorter->aTask[i]; vdbeSortSubtaskCleanup(db, pTask); + pTask->pSorter = pSorter; } if( pSorter->list.aMemory==0 ){ vdbeSorterRecordFree(0, pSorter->list.pList); } pSorter->list.pList = 0; Index: test/orderby1.test ================================================================== --- test/orderby1.test +++ test/orderby1.test @@ -493,7 +493,36 @@ CREATE INDEX t7ab ON t7(a,b); EXPLAIN QUERY PLAN SELECT * FROM t7 WHERE a=?1 ORDER BY rowid; } {~/ORDER BY/} +#------------------------------------------------------------------------- +# Test a partial sort large enough to cause the sorter to spill data +# to disk. +# +reset_db +do_execsql_test 8.0 { + PRAGMA cache_size = 5; + CREATE TABLE t1(a, b); + CREATE INDEX i1 ON t1(a); +} + +do_eqp_test 8.1 { + SELECT * FROM t1 ORDER BY a, b; +} { + 0 0 0 {SCAN TABLE t1 USING INDEX i1} + 0 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY} +} + +do_execsql_test 8.2 { + WITH cnt(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM cnt WHERE i<10000 + ) + INSERT INTO t1 SELECT i%2, randomblob(500) FROM cnt; +} + +do_test 8.3 { + db eval { SELECT * FROM t1 ORDER BY a, b } { incr res $a } + set res +} 5000 finish_test