From 1d60598d4034a2678c4f78ca5a628c356b5cdc18 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 22 Aug 2012 15:16:36 +0000 Subject: [PATCH] Do not let the multi-core sorter use lookaside memory, which is not thread-safe. FossilOrigin-Name: acdc7d1270b6aacf4612296a8d4dd596042b058c --- manifest | 20 ++++---- manifest.uuid | 2 +- src/threads.c | 1 - src/vdbe.c | 6 +-- src/vdbeInt.h | 18 +++---- src/vdbeaux.c | 2 +- src/vdbesort.c | 127 ++++++++++++++++++++++++++++--------------------- 7 files changed, 96 insertions(+), 80 deletions(-) diff --git a/manifest b/manifest index 38f14093c3..8a00a3edc5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sin\sall\sthe\slatest\strunk\schanges. -D 2012-08-21T17:46:18.408 +C Do\snot\slet\sthe\smulti-core\ssorter\suse\slookaside\smemory,\swhich\sis\snot\nthread-safe. +D 2012-08-22T15:16:36.722 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in adec39f15a9c7000f634b87a535b95279b0cbd09 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -231,21 +231,21 @@ F src/test_vfs.c c6260ef238c1142c8f8bd402db02216afd182ae3 F src/test_vfstrace.c 6b28adb2a0e8ecd0f2e3581482e1f658b11b4067 F src/test_wholenumber.c 3d2b9ed1505c40ad5c5ca2ad16ae7a289d6cc251 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 -F src/threads.c 2b918d1f4f0b0831e8f41c49bcaa097f01490120 +F src/threads.c cde9d885fd562b5427f89a42a8829085f88b17df F src/tokenize.c 1e86210d3976717a19238ea7b047fac481fe8c12 F src/trigger.c ee7e178fb9188f44b532cebd449a7c1df90fb684 F src/update.c d3076782c887c10e882996550345da9c4c9f9dea F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84 F src/util.c 0af2e515dc0dabacec931bca39525f6c3f1c5455 F src/vacuum.c 587a52bb8833d7ac15af8916f25437e2575028bd -F src/vdbe.c 75da79cdcd58481825a06f045bc2f5ea3966eeae +F src/vdbe.c 1a451790e5abd4df1c0ad0c39d5d6398888b473f F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb -F src/vdbeInt.h 986b6b11a13c517337355009e5438703ba5b0a40 +F src/vdbeInt.h 3c238336fc5b186b193553dbac4e1979d91e0c0d F src/vdbeapi.c 88ea823bbcb4320f5a6607f39cd7c2d3cc4c26b1 -F src/vdbeaux.c dce80038c3c41f2680e5ab4dd0f7e0d8b7ff9071 +F src/vdbeaux.c 84bd15358329f4005a7bceefafc1e798592e987d F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb F src/vdbemem.c cb55e84b8e2c15704968ee05f0fae25883299b74 -F src/vdbesort.c 3945ae71fe43e52727ec52103a07492e9df1776f +F src/vdbesort.c acaefad52f6345a06fcfe2ec7da0c7d7d2569c39 F src/vdbetrace.c 8bd5da325fc90f28464335e4cc4ad1407fe30835 F src/vtab.c bb8ea3a26608bb1357538a5d2fc72beba6638998 F src/wal.c 9294df6f96aae5909ae1a9b733fd1e1b4736978b @@ -1012,7 +1012,7 @@ F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 67d8a99aceb56384a81b3f30d6c71743146d2cc9 -P 555fc07efd1a1bc597804dcacbbcd95e88e75e90 573770f5a66fa4d708931b30350149eb739da607 -R 6a248acc2b1ad3eddb9f82f26a87ebb7 +P 45cdc32f1e4d33959108dac94f551a4b8030424d +R fe69bbfbdf0f9035e48cc3502476a4c4 U drh -Z eefdd7d4c689b509af3b4731cefe3c98 +Z cf3f449e5e4dc5f0a36f059aada3751c diff --git a/manifest.uuid b/manifest.uuid index c3f2313a3a..571cd82139 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -45cdc32f1e4d33959108dac94f551a4b8030424d \ No newline at end of file +acdc7d1270b6aacf4612296a8d4dd596042b058c \ No newline at end of file diff --git a/src/threads.c b/src/threads.c index 33781a7aac..7cc964250d 100644 --- a/src/threads.c +++ b/src/threads.c @@ -47,7 +47,6 @@ int sqlite3ThreadCreate( void *pIn /* Argument passed into xTask() */ ){ SQLiteThread *p; - int rc; assert( ppThread!=0 ); assert( xTask!=0 ); diff --git a/src/vdbe.c b/src/vdbe.c index 12e7325143..8d512ed2f5 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4405,7 +4405,7 @@ case OP_Rewind: { /* jump */ assert( pC->isSorter==(pOp->opcode==OP_SorterSort) ); res = 1; if( isSorter(pC) ){ - rc = sqlite3VdbeSorterRewind(db, pC, &res); + rc = sqlite3VdbeSorterRewind(pC, &res); }else{ pCrsr = pC->pCursor; assert( pCrsr ); @@ -4474,7 +4474,7 @@ case OP_Next: { /* jump */ assert( pC->isSorter==(pOp->opcode==OP_SorterNext) ); if( isSorter(pC) ){ assert( pOp->opcode==OP_SorterNext ); - rc = sqlite3VdbeSorterNext(db, pC, &res); + rc = sqlite3VdbeSorterNext(pC, &res); }else{ res = 1; assert( pC->deferredMoveto==0 ); @@ -4530,7 +4530,7 @@ case OP_IdxInsert: { /* in2 */ rc = ExpandBlob(pIn2); if( rc==SQLITE_OK ){ if( isSorter(pC) ){ - rc = sqlite3VdbeSorterWrite(db, pC, pIn2); + rc = sqlite3VdbeSorterWrite(pC, pIn2); }else{ nKey = pIn2->n; zKey = pIn2->z; diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 1f5694a595..88a2eefd31 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -422,19 +422,19 @@ int sqlite3VdbeTransferError(Vdbe *p); #ifdef SQLITE_OMIT_MERGE_SORT # define sqlite3VdbeSorterInit(Y,Z) SQLITE_OK -# define sqlite3VdbeSorterWrite(X,Y,Z) SQLITE_OK -# define sqlite3VdbeSorterClose(Y,Z) +# define sqlite3VdbeSorterWrite(Y,Z) SQLITE_OK +# define sqlite3VdbeSorterClose(Z) # define sqlite3VdbeSorterRowkey(Y,Z) SQLITE_OK -# define sqlite3VdbeSorterRewind(X,Y,Z) SQLITE_OK -# define sqlite3VdbeSorterNext(X,Y,Z) SQLITE_OK -# define sqlite3VdbeSorterCompare(X,Y,Z) SQLITE_OK +# define sqlite3VdbeSorterRewind(Y,Z) SQLITE_OK +# define sqlite3VdbeSorterNext(Y,Z) SQLITE_OK +# define sqlite3VdbeSorterCompare(Y,Z) SQLITE_OK #else int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *); -void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *); +void sqlite3VdbeSorterClose(VdbeCursor *); int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *); -int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *); -int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *); -int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *); +int sqlite3VdbeSorterNext(const VdbeCursor *, int *); +int sqlite3VdbeSorterRewind(const VdbeCursor *, int *); +int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *); int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *); #endif diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 3ccf711619..2551b9fb79 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1575,7 +1575,7 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ if( pCx==0 ){ return; } - sqlite3VdbeSorterClose(p->db, pCx); + sqlite3VdbeSorterClose(pCx); if( pCx->pBt ){ sqlite3BtreeClose(pCx->pBt); /* The pCx->pCursor will be close automatically, if it exists, by diff --git a/src/vdbesort.c b/src/vdbesort.c index 4b546e7a90..0fd17ab40f 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -107,6 +107,8 @@ struct VdbeSorter { SorterRecord *pRecord; /* Head of in-memory record list */ int nRecord; /* Number of elements on the pRecord list */ UnpackedRecord *pUnpacked; /* Used to unpack keys */ + KeyInfo *pKeyInfo; /* Copy of cursor KeyInfo without db ptr */ + sqlite3 *db; /* Database connection */ }; /* @@ -116,6 +118,7 @@ struct VdbeSorter { struct VdbeSorterIter { i64 iReadOff; /* Current read offset */ i64 iEof; /* 1 byte past EOF for this iterator */ + sqlite3 *db; /* Corresponding database connection */ int nAlloc; /* Bytes of space at aAlloc */ int nKey; /* Number of bytes in key */ sqlite3_file *pFile; /* File iterator is reading from */ @@ -178,7 +181,6 @@ static void vdbeSorterIterZero(sqlite3 *db, VdbeSorterIter *pIter){ ** next call to this function. */ static int vdbeSorterIterRead( - sqlite3 *db, /* Database handle (for malloc) */ VdbeSorterIter *p, /* Iterator */ int nByte, /* Bytes of data to read */ u8 **ppOut /* OUT: Pointer to buffer containing data */ @@ -223,7 +225,7 @@ static int vdbeSorterIterRead( if( p->nAllocnAlloc*2; while( nByte>nNew ) nNew = nNew*2; - p->aAlloc = sqlite3DbReallocOrFree(db, p->aAlloc, nNew); + p->aAlloc = sqlite3DbReallocOrFree(p->db, p->aAlloc, nNew); if( !p->aAlloc ) return SQLITE_NOMEM; p->nAlloc = nNew; } @@ -243,7 +245,7 @@ static int vdbeSorterIterRead( nCopy = nRem; if( nRem>p->nBuffer ) nCopy = p->nBuffer; - rc = vdbeSorterIterRead(db, p, nCopy, &aNext); + rc = vdbeSorterIterRead(p, nCopy, &aNext); if( rc!=SQLITE_OK ) return rc; assert( aNext!=p->aAlloc ); memcpy(&p->aAlloc[nByte - nRem], aNext, nCopy); @@ -260,7 +262,7 @@ static int vdbeSorterIterRead( ** Read a varint from the stream of data accessed by p. Set *pnOut to ** the value read. */ -static int vdbeSorterIterVarint(sqlite3 *db, VdbeSorterIter *p, u64 *pnOut){ +static int vdbeSorterIterVarint(VdbeSorterIter *p, u64 *pnOut){ int iBuf; iBuf = p->iReadOff % p->nBuffer; @@ -270,7 +272,7 @@ static int vdbeSorterIterVarint(sqlite3 *db, VdbeSorterIter *p, u64 *pnOut){ u8 aVarint[16], *a; int i = 0, rc; do{ - rc = vdbeSorterIterRead(db, p, 1, &a); + rc = vdbeSorterIterRead(p, 1, &a); if( rc ) return rc; aVarint[(i++)&0xf] = a[0]; }while( (a[0]&0x80)!=0 ); @@ -286,11 +288,11 @@ static int vdbeSorterIterVarint(sqlite3 *db, VdbeSorterIter *p, u64 *pnOut){ ** no error occurs, or an SQLite error code if one does. */ static int vdbeSorterIterNext( - sqlite3 *db, /* Database handle (for sqlite3DbMalloc() ) */ VdbeSorterIter *pIter /* Iterator to advance */ ){ int rc; /* Return Code */ u64 nRec = 0; /* Size of record in bytes */ + sqlite3 *db = pIter->db; /* Database connection */ if( pIter->iReadOff>=pIter->iEof ){ /* This is an EOF condition */ @@ -298,10 +300,10 @@ static int vdbeSorterIterNext( return SQLITE_OK; } - rc = vdbeSorterIterVarint(db, pIter, &nRec); + rc = vdbeSorterIterVarint(pIter, &nRec); if( rc==SQLITE_OK ){ pIter->nKey = (int)nRec; - rc = vdbeSorterIterRead(db, pIter, (int)nRec, &pIter->aKey); + rc = vdbeSorterIterRead(pIter, (int)nRec, &pIter->aKey); } return rc; @@ -314,7 +316,6 @@ static int vdbeSorterIterNext( ** PMA is empty). */ static int vdbeSorterIterInit( - sqlite3 *db, /* Database handle */ const VdbeSorter *pSorter, /* Sorter object */ i64 iStart, /* Start offset in pFile */ VdbeSorterIter *pIter, /* Iterator to populate */ @@ -322,6 +323,7 @@ static int vdbeSorterIterInit( ){ int rc = SQLITE_OK; int nBuf; + sqlite3 *db = pSorter->db; nBuf = sqlite3BtreeGetPageSize(db->aDb[0].pBt); @@ -330,6 +332,7 @@ static int vdbeSorterIterInit( assert( pIter->aBuffer==0 ); pIter->pFile = pSorter->pTemp1; pIter->iReadOff = iStart; + pIter->db = db; pIter->nAlloc = 128; pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc); pIter->nBuffer = nBuf; @@ -355,14 +358,14 @@ static int vdbeSorterIterInit( if( rc==SQLITE_OK ){ u64 nByte; /* Size of PMA in bytes */ pIter->iEof = pSorter->iWriteOff; - rc = vdbeSorterIterVarint(db, pIter, &nByte); + rc = vdbeSorterIterVarint(pIter, &nByte); pIter->iEof = pIter->iReadOff + nByte; *pnByte += nByte; } } if( rc==SQLITE_OK ){ - rc = vdbeSorterIterNext(db, pIter); + rc = vdbeSorterIterNext(pIter); } return rc; } @@ -384,14 +387,14 @@ static int vdbeSorterIterInit( ** has been allocated and contains an unpacked record that is used as key2. */ static void vdbeSorterCompare( - const VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */ + VdbeSorter *pSorter, /* The sorter */ int bOmitRowid, /* Ignore rowid field at end of keys */ const void *pKey1, int nKey1, /* Left side of comparison */ const void *pKey2, int nKey2, /* Right side of comparison */ int *pRes, /* OUT: Result of comparison */ UnpackedRecord *r2 /* Space to hold the unpacked Key2 record */ ){ - KeyInfo *pKeyInfo = pCsr->pKeyInfo; + KeyInfo *pKeyInfo = pSorter->pKeyInfo; int i; if( pKey2 ){ @@ -419,8 +422,7 @@ static void vdbeSorterCompare( ** multiple b-tree segments. Parameter iOut is the index of the aTree[] ** value to recalculate. */ -static int vdbeSorterDoCompare(const VdbeCursor *pCsr, int iOut){ - VdbeSorter *pSorter = pCsr->pSorter; +static int vdbeSorterDoCompare(VdbeSorter *pSorter, int iOut){ int i1; int i2; int iRes; @@ -447,7 +449,7 @@ static int vdbeSorterDoCompare(const VdbeCursor *pCsr, int iOut){ }else{ int res; vdbeSorterCompare( - pCsr, 0, p1->aKey, p1->nKey, p2->aKey, p2->nKey, &res, + pSorter, 0, p1->aKey, p1->nKey, p2->aKey, p2->nKey, &res, pSorter->pUnpacked ); if( res<=0 ){ @@ -469,17 +471,32 @@ int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){ int mxCache; /* Cache size */ VdbeSorter *pSorter; /* The new sorter */ char *d; /* Dummy */ + int nByte; /* Bytes in pKeyInfo */ assert( pCsr->pKeyInfo && pCsr->pBt==0 ); pCsr->pSorter = pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter)); if( pSorter==0 ){ return SQLITE_NOMEM; } + pSorter->db = db; pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pCsr->pKeyInfo, 0, 0, &d); if( pSorter->pUnpacked==0 ) return SQLITE_NOMEM; assert( pSorter->pUnpacked==(UnpackedRecord *)d ); + /* pSorter->pKeyInfo is a copy of pCsr->pKeyInfo with the db field set to + ** zero. We use this modified pKeyInfo for sorting so that no lookaside + ** memory will be used, so that sorting can proceed in parallel in multiple + ** threads. + */ + nByte = sizeof(KeyInfo) + (pCsr->pKeyInfo->nField - 1)*sizeof(CollSeq*); + pSorter->pKeyInfo = sqlite3DbMallocRaw(db, nByte); + if( pSorter->pKeyInfo==0 ){ + return SQLITE_NOMEM; + } + memcpy(pSorter->pKeyInfo, pCsr->pKeyInfo, nByte); + pSorter->pKeyInfo->db = 0; + if( !sqlite3TempInMemory(db) ){ pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt); pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz; @@ -506,9 +523,10 @@ static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){ /* ** Free any cursor components allocated by sqlite3VdbeSorterXXX routines. */ -void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){ +void sqlite3VdbeSorterClose(VdbeCursor *pCsr){ VdbeSorter *pSorter = pCsr->pSorter; if( pSorter ){ + sqlite3 *db = pSorter->db; if( pSorter->aIter ){ int i; for(i=0; inTree; i++){ @@ -521,6 +539,7 @@ void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){ } vdbeSorterRecordFree(db, pSorter->pRecord); sqlite3DbFree(db, pSorter->pUnpacked); + sqlite3DbFree(db, pSorter->pKeyInfo); sqlite3DbFree(db, pSorter); pCsr->pSorter = 0; } @@ -545,7 +564,7 @@ static int vdbeSorterOpenTempFile(sqlite3 *db, sqlite3_file **ppFile){ ** Set *ppOut to the head of the new list. */ static void vdbeSorterMerge( - const VdbeCursor *pCsr, /* For pKeyInfo */ + VdbeSorter *pSorter, /* The sorter object */ SorterRecord *p1, /* First list to merge */ SorterRecord *p2, /* Second list to merge */ SorterRecord **ppOut, /* OUT: Head of merged list */ @@ -557,7 +576,7 @@ static void vdbeSorterMerge( while( p1 && p2 ){ int res; - vdbeSorterCompare(pCsr, 0, p1->pVal, p1->nVal, pVal2, p2->nVal, &res, + vdbeSorterCompare(pSorter, 0, p1->pVal, p1->nVal, pVal2, p2->nVal, &res, pUnpacked); if( res<=0 ){ *pp = p1; @@ -580,9 +599,9 @@ static void vdbeSorterMerge( ** Background sorting task */ typedef struct SortTask { - SorterRecord *pList; /* List of elements to be sorted */ - const VdbeCursor *pCsr; /* Cursor. Needed for pCur->pKeyInfo */ + VdbeSorter *pSorter; /* The sorter for which this task works */ UnpackedRecord *pUnpacked; /* Space to hold an unpacked key */ + SorterRecord *pList; /* List of elements to be sorted */ SorterRecord **apSlot; /* Temp memory for the merge sort */ } SortTask; @@ -599,7 +618,7 @@ void *vdbeSorterBackgroundSort(SortTask *pTask){ p->pNext = 0; for(i=0; a[i]; i++){ if( a[i]==0 ) break; - vdbeSorterMerge(pTask->pCsr, a[i], p, &p, pTask->pUnpacked); + vdbeSorterMerge(pTask->pSorter, a[i], p, &p, pTask->pUnpacked); a[i] = 0; } a[i] = p; @@ -607,7 +626,7 @@ void *vdbeSorterBackgroundSort(SortTask *pTask){ } p = 0; for(i=0; i<64; i++){ - vdbeSorterMerge(pTask->pCsr, a[i], p, &p, pTask->pUnpacked); + vdbeSorterMerge(pTask->pSorter, a[i], p, &p, pTask->pUnpacked); } pTask->pList = p; return p; @@ -644,10 +663,8 @@ static void vdbeSorterDivideList( ** if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if an error ** occurs. */ -static int vdbeSorterSort(const VdbeCursor *pCsr){ +static int vdbeSorterSort(VdbeSorter *pSorter){ int rc; - SorterRecord *p; - VdbeSorter *pSorter = pCsr->pSorter; char *pDummy = 0; int nByteA, nByteB; SortTask aTask[2]; @@ -655,19 +672,19 @@ static int vdbeSorterSort(const VdbeCursor *pCsr){ nByteA = 64*sizeof(SorterRecord*); nByteB = ROUND8(sizeof(UnpackedRecord)); - nByteB += sizeof(Mem)*(pCsr->pKeyInfo->nField+1); + nByteB += sizeof(Mem)*(pSorter->pKeyInfo->nField+1); aTask[0].apSlot = (SorterRecord **)sqlite3MallocZero(2*(nByteA + nByteB)); if( !aTask[0].apSlot ){ return SQLITE_NOMEM; } - aTask[0].pCsr = pCsr; - aTask[0].pUnpacked = sqlite3VdbeAllocUnpackedRecord(pCsr->pKeyInfo, + aTask[0].pSorter = pSorter; + aTask[0].pUnpacked = sqlite3VdbeAllocUnpackedRecord(pSorter->pKeyInfo, (char*)&aTask[0].apSlot[64], nByteB, &pDummy); assert( pDummy==0 ); - aTask[1].apSlot = (nByteA+nByteB)+(char*)aTask[0].apSlot; - aTask[1].pCsr = pCsr; - aTask[1].pUnpacked = sqlite3VdbeAllocUnpackedRecord(pCsr->pKeyInfo, + aTask[1].apSlot = (SorterRecord**)((nByteA+nByteB)+(char*)aTask[0].apSlot); + aTask[1].pSorter = pSorter; + aTask[1].pUnpacked = sqlite3VdbeAllocUnpackedRecord(pSorter->pKeyInfo, (char*)&aTask[1].apSlot[64], nByteB, &pDummy); assert( pDummy==0 ); @@ -678,10 +695,10 @@ static int vdbeSorterSort(const VdbeCursor *pCsr){ if( rc==SQLITE_NOMEM ){ vdbeSorterBackgroundSort(&aTask[0]); }else{ - rc = sqlite3ThreadJoin(pThread, &pDummy); + rc = sqlite3ThreadJoin(pThread, (void**)&pDummy); } - vdbeSorterMerge(pCsr, aTask[0].pList, aTask[1].pList, &pSorter->pRecord, - aTask[0].pUnpacked); + vdbeSorterMerge(pSorter, aTask[0].pList, aTask[1].pList, &pSorter->pRecord, + pSorter->pUnpacked); sqlite3_free(aTask[0].apSlot); return rc; } @@ -785,10 +802,10 @@ static void fileWriterWriteVarint(FileWriter *p, u64 iVal){ ** Each record consists of a varint followed by a blob of data (the ** key). The varint is the number of bytes in the blob of data. */ -static int vdbeSorterListToPMA(sqlite3 *db, const VdbeCursor *pCsr){ +static int vdbeSorterListToPMA(VdbeSorter *pSorter){ int rc = SQLITE_OK; /* Return code */ - VdbeSorter *pSorter = pCsr->pSorter; FileWriter writer; + sqlite3 *db = pSorter->db; memset(&writer, 0, sizeof(FileWriter)); @@ -798,7 +815,7 @@ static int vdbeSorterListToPMA(sqlite3 *db, const VdbeCursor *pCsr){ return rc; } - rc = vdbeSorterSort(pCsr); + rc = vdbeSorterSort(pSorter); /* If the first temporary PMA file has not been opened, open it now. */ if( rc==SQLITE_OK && pSorter->pTemp1==0 ){ @@ -833,11 +850,11 @@ static int vdbeSorterListToPMA(sqlite3 *db, const VdbeCursor *pCsr){ ** Add a record to the sorter. */ int sqlite3VdbeSorterWrite( - sqlite3 *db, /* Database handle */ - const VdbeCursor *pCsr, /* Sorter cursor */ + const VdbeCursor *pCsr, /* Sorter cursor */ Mem *pVal /* Memory cell containing record */ ){ VdbeSorter *pSorter = pCsr->pSorter; + sqlite3 *db = pSorter->db; int rc = SQLITE_OK; /* Return Code */ SorterRecord *pNew; /* New list element */ @@ -874,7 +891,7 @@ int sqlite3VdbeSorterWrite( + sqlite3VarintLen(pSorter->nInMemory) + pSorter->nInMemory; #endif - rc = vdbeSorterListToPMA(db, pCsr); + rc = vdbeSorterListToPMA(pSorter); pSorter->nInMemory = 0; assert( rc!=SQLITE_OK || (nExpect==pSorter->iWriteOff) ); } @@ -886,11 +903,9 @@ int sqlite3VdbeSorterWrite( ** Helper function for sqlite3VdbeSorterRewind(). */ static int vdbeSorterInitMerge( - sqlite3 *db, /* Database handle */ - const VdbeCursor *pCsr, /* Cursor handle for this sorter */ + VdbeSorter *pSorter, /* The sorter */ i64 *pnByte /* Sum of bytes in all opened PMAs */ ){ - VdbeSorter *pSorter = pCsr->pSorter; int rc = SQLITE_OK; /* Return code */ int i; /* Used to iterator through aIter[] */ i64 nByte = 0; /* Total bytes in all opened PMAs */ @@ -898,7 +913,7 @@ static int vdbeSorterInitMerge( /* Initialize the iterators. */ for(i=0; iaIter[i]; - rc = vdbeSorterIterInit(db, pSorter, pSorter->iReadOff, pIter, &nByte); + rc = vdbeSorterIterInit(pSorter, pSorter->iReadOff, pIter, &nByte); pSorter->iReadOff = pIter->iEof; assert( rc!=SQLITE_OK || pSorter->iReadOff<=pSorter->iWriteOff ); if( rc!=SQLITE_OK || pSorter->iReadOff>=pSorter->iWriteOff ) break; @@ -906,7 +921,7 @@ static int vdbeSorterInitMerge( /* Initialize the aTree[] array. */ for(i=pSorter->nTree-1; rc==SQLITE_OK && i>0; i--){ - rc = vdbeSorterDoCompare(pCsr, i); + rc = vdbeSorterDoCompare(pSorter, i); } *pnByte = nByte; @@ -917,8 +932,9 @@ static int vdbeSorterInitMerge( ** Once the sorter has been populated, this function is called to prepare ** for iterating through its contents in sorted order. */ -int sqlite3VdbeSorterRewind(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){ +int sqlite3VdbeSorterRewind(const VdbeCursor *pCsr, int *pbEof){ VdbeSorter *pSorter = pCsr->pSorter; + sqlite3 *db = pSorter->db; int rc; /* Return code */ sqlite3_file *pTemp2 = 0; /* Second temp file to use */ i64 iWrite2 = 0; /* Write offset for pTemp2 */ @@ -934,11 +950,11 @@ int sqlite3VdbeSorterRewind(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){ if( pSorter->nPMA==0 ){ *pbEof = !pSorter->pRecord; assert( pSorter->aTree==0 ); - return vdbeSorterSort(pCsr); + return vdbeSorterSort(pSorter); } /* Write the current in-memory list to a PMA. */ - rc = vdbeSorterListToPMA(db, pCsr); + rc = vdbeSorterListToPMA(pSorter); if( rc!=SQLITE_OK ) return rc; /* Allocate space for aIter[] and aTree[]. */ @@ -974,7 +990,7 @@ int sqlite3VdbeSorterRewind(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){ ** initialize interators for SORTER_MAX_MERGE_COUNT of them. These PMAs ** are merged into a single PMA that is written to file pTemp2. */ - rc = vdbeSorterInitMerge(db, pCsr, &nWrite); + rc = vdbeSorterInitMerge(pSorter, &nWrite); assert( rc!=SQLITE_OK || pSorter->aIter[ pSorter->aTree[1] ].pFile ); if( rc!=SQLITE_OK || pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){ break; @@ -996,7 +1012,7 @@ int sqlite3VdbeSorterRewind(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){ fileWriterWriteVarint(&writer, pIter->nKey); fileWriterWrite(&writer, pIter->aKey, pIter->nKey); - rc = sqlite3VdbeSorterNext(db, pCsr, &bEof); + rc = sqlite3VdbeSorterNext(pCsr, &bEof); } rc2 = fileWriterFinish(db, &writer, &iWrite2); if( rc==SQLITE_OK ) rc = rc2; @@ -1026,17 +1042,18 @@ int sqlite3VdbeSorterRewind(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){ /* ** Advance to the next element in the sorter. */ -int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){ +int sqlite3VdbeSorterNext(const VdbeCursor *pCsr, int *pbEof){ VdbeSorter *pSorter = pCsr->pSorter; + sqlite3 *db = pSorter->db; int rc; /* Return code */ if( pSorter->aTree ){ int iPrev = pSorter->aTree[1];/* Index of iterator to advance */ int i; /* Index of aTree[] to recalculate */ - rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]); + rc = vdbeSorterIterNext(&pSorter->aIter[iPrev]); for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){ - rc = vdbeSorterDoCompare(pCsr, i); + rc = vdbeSorterDoCompare(pSorter, i); } *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0); @@ -1110,7 +1127,7 @@ int sqlite3VdbeSorterCompare( void *pKey; int nKey; /* Sorter key to compare pVal with */ pKey = vdbeSorterRowkey(pSorter, &nKey); - vdbeSorterCompare(pCsr, 1, pVal->z, pVal->n, pKey, nKey, pRes, + vdbeSorterCompare(pSorter, 1, pVal->z, pVal->n, pKey, nKey, pRes, pSorter->pUnpacked); return SQLITE_OK; } -- 2.39.5