Do not let the multi-core sorter use lookaside memory, which is not
thread-safe.
FossilOrigin-Name: acdc7d1270b6aacf4612296a8d4dd596042b058c
diff --git a/manifest b/manifest
index 38f1409..8a00a3e 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_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/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 c3f2313..571cd82 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 33781a7..7cc9642 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -47,7 +47,6 @@
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 12e7325..8d512ed 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -4405,7 +4405,7 @@
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 @@
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 @@
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 1f5694a..88a2eef 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -422,19 +422,19 @@
#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 3ccf711..2551b9f 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -1575,7 +1575,7 @@
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 4b546e7..0fd17ab 100644
--- a/src/vdbesort.c
+++ b/src/vdbesort.c
@@ -107,6 +107,8 @@
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 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 @@
** 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 @@
if( p->nAlloc<nByte ){
int nNew = p->nAlloc*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 @@
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 @@
** 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 @@
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 @@
** 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 @@
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 @@
** 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 @@
){
int rc = SQLITE_OK;
int nBuf;
+ sqlite3 *db = pSorter->db;
nBuf = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
@@ -330,6 +332,7 @@
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 @@
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 @@
** 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 @@
** 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 @@
}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 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 @@
/*
** 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; i<pSorter->nTree; i++){
@@ -521,6 +539,7 @@
}
vdbeSorterRecordFree(db, pSorter->pRecord);
sqlite3DbFree(db, pSorter->pUnpacked);
+ sqlite3DbFree(db, pSorter->pKeyInfo);
sqlite3DbFree(db, pSorter);
pCsr->pSorter = 0;
}
@@ -545,7 +564,7 @@
** 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 @@
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 @@
** 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 @@
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 @@
}
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 @@
** 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 @@
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 @@
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 @@
** 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 @@
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 @@
** 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 @@
+ 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 @@
** 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 @@
/* Initialize the iterators. */
for(i=0; i<SORTER_MAX_MERGE_COUNT; i++){
VdbeSorterIter *pIter = &pSorter->aIter[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 @@
/* 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 @@
** 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 @@
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 @@
** 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 @@
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 @@
/*
** 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 @@
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;
}