-C Add\sthe\sSQLITE_OMIT_MERGE_SORT\spre-processor\sdirective.\sTo\somit\sthe\scode\sin\svdbesort.c.
-D 2011-08-12T15:02:00.509
+C Remove\san\sunused\sparameter\sfrom\sa\sfunction\sin\svdbesort.c.\sFix\ssome\scomments\sand\sother\sdetails\sin\sthe\ssame\sfile.
+D 2011-08-12T16:11:43.093
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in c1d7a7f4fd8da6b1815032efca950e3d5125407e
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/utf.c c53eb7404b3eb5c1cbb5655c6a7a0e0ce6bd50f0
F src/util.c 0f33bbbdfcc4a2d8cf20c3b2a16ffc3b57c58a70
F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e
-F src/vdbe.c eed17aa60343d7d19dc5110e0d4855695b7be9bb
+F src/vdbe.c 1f5bb8b8a0f24bd93e66958eaebd060ccee272a2
F src/vdbe.h 5cf09e7ee8a3f7d93bc51f196a96550786afe7a1
-F src/vdbeInt.h 603b4ccc81ffd7e57f15e4bdecee6d593856eec7
+F src/vdbeInt.h f9250326f264ca5f100acc19e9c07096bb889096
F src/vdbeapi.c 11dc47987abacb76ad016dcf5abc0dc422482a98
F src/vdbeaux.c 8fb978eb73a97b34d352dd3ef3bff35b1b3fa7e9
F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
-F src/vdbesort.c b475ceede1837731f603f32ad28c3d59f07ec04e
+F src/vdbesort.c a756d20db3ff596dd3dd10f6a13fd832f5715540
F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114
F src/vtab.c 901791a47318c0562cd0c676a2c6ff1bc530e582
F src/wal.c 0c70ad7b1cac6005fa5e2cbefd23ee05e391c290
F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings.sh 2ebae31e1eb352696f3c2f7706a34c084b28c262
-P 87a15917d7d88285054e2a319506dd4a0cac9722
-R 8547f4d65e2fdae700fb2b829b9d1918
+P 4ced2394b10d0a4f86422ff893bcdf3cf32591e3
+R ced8374c50fa0d83b7bc754994eec7c3
U dan
-Z 981ae6d6ebf67ae66ca60cea9244ff02
+Z 2a841cd45d02eb2ca25a3f8996849530
typedef struct VdbeSorterIter VdbeSorterIter;
/*
+** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES:
+**
** As keys are added to the sorter, they are written to disk in a series
** of sorted packed-memory-arrays (PMAs). The size of each PMA is roughly
** the same as the cache-size allowed for temporary databases. In order
};
/* Minimum allowable value for the VdbeSorter.nWorking variable */
-#define SORTER_MIN_SEGMENT_SIZE 10
+#define SORTER_MIN_WORKING 10
/* Maximum number of segments to merge in a single pass. */
#define SORTER_MAX_MERGE_COUNT 16
}
/*
-** Advance iterator pIter to the next key in its PMA.
+** Advance iterator pIter to the next key in its PMA. Return SQLITE_OK if
+** 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;
- int nRead;
- int nRec;
- int iOff;
+ int rc; /* Return Code */
+ int nRead; /* Number of bytes read */
+ int nRec; /* Size of record in bytes */
+ int iOff; /* Size of serialized size varint in bytes */
nRead = pIter->iEof - pIter->iReadOff;
if( nRead>5 ) nRead = 5;
if( nRead<=0 ){
+ /* This is an EOF condition */
vdbeSorterIterZero(db, pIter);
return SQLITE_OK;
}
iOff = getVarint32(pIter->aAlloc, nRec);
if( rc==SQLITE_OK && (iOff+nRec)>nRead ){
- int nRead2;
+ int nRead2; /* Number of extra bytes to read */
if( (iOff+nRec)>pIter->nAlloc ){
int nNew = pIter->nAlloc*2;
while( (iOff+nRec)>nNew ) nNew = nNew*2;
}
assert( nRec>0 || rc!=SQLITE_OK );
-
pIter->iReadOff += iOff+nRec;
pIter->nKey = nRec;
pIter->aKey = &pIter->aAlloc[iOff];
** incremented by the number of bytes written.
*/
static int vdbeSorterWriteVarint(
- sqlite3_file *pFile,
- i64 iVal,
- i64 *piOffset
+ sqlite3_file *pFile, /* File to write to */
+ i64 iVal, /* Value to write as a varint */
+ i64 *piOffset /* IN/OUT: Write offset in file pFile */
){
u8 aVarint[9]; /* Buffer large enough for a varint */
int nVarint; /* Number of used bytes in varint */
** both *piOffset and *piVal are undefined.
*/
static int vdbeSorterReadVarint(
- sqlite3_file *pFile,
+ sqlite3_file *pFile, /* File to read from */
i64 iEof, /* Total number of bytes in file */
- i64 *piOffset, /* IN/OUT: Read offset */
+ i64 *piOffset, /* IN/OUT: Read offset in pFile */
i64 *piVal /* OUT: Value read from file */
){
u8 aVarint[9]; /* Buffer large enough for a varint */
i64 *pnByte /* IN/OUT: Increment this value by PMA size */
){
int rc;
- i64 iEof = pSorter->iWriteOff;
- assert( iEof>iStart );
+ assert( pSorter->iWriteOff>iStart );
assert( pIter->aAlloc==0 );
pIter->pFile = pSorter->pTemp1;
pIter->iReadOff = iStart;
if( !pIter->aAlloc ){
rc = SQLITE_NOMEM;
}else{
- i64 nByte;
+ i64 iEof = pSorter->iWriteOff; /* EOF of file pSorter->pTemp1 */
+ i64 nByte; /* Total size of PMA in bytes */
rc = vdbeSorterReadVarint(pSorter->pTemp1, iEof, &pIter->iReadOff, &nByte);
*pnByte += nByte;
pIter->iEof = pIter->iReadOff + nByte;
** Initialize the temporary index cursor just opened as a sorter cursor.
*/
int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){
- VdbeSorter *pSorter; /* Allocated sorter object */
-
- /* Cursor must be a temp cursor and not open on an intkey table */
assert( pCsr->pKeyInfo && pCsr->pBt );
-
- pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter));
- if( !pSorter ) return SQLITE_NOMEM;
- pCsr->pSorter = pSorter;
- return SQLITE_OK;
+ pCsr->pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter));
+ return (pCsr->pSorter ? SQLITE_NOMEM : SQLITE_OK);
}
/*
/*
** Write the current contents of the b-tree to a PMA. Return SQLITE_OK
** if successful, or an SQLite error code otherwise.
+**
+** The format of a PMA is:
+**
+** * A varint. This varint contains the total number of bytes of content
+** in the PMA (not including the varint itself).
+**
+** * One or more records packed end-to-end in order of ascending keys.
+** 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 vdbeSorterBtreeToPMA(sqlite3 *db, VdbeCursor *pCsr){
int rc = SQLITE_OK; /* Return code */
VdbeSorter *pSorter = pCsr->pSorter;
- i64 iWriteOff = pSorter->iWriteOff;
int res = 0;
- void *aMalloc = 0;
- int nMalloc = 0;
rc = sqlite3BtreeFirst(pCsr->pCursor, &res);
if( rc!=SQLITE_OK || res ) return rc;
+ assert( pSorter->nBtree>0 );
/* If the first temporary PMA file has not been opened, open it now. */
if( pSorter->pTemp1==0 ){
}
if( rc==SQLITE_OK ){
+ i64 iWriteOff = pSorter->iWriteOff;
+ void *aMalloc = 0; /* Array used to hold a single record */
+ int nMalloc = 0; /* Allocated size of aMalloc[] in bytes */
pSorter->nPMA++;
-
- /* Write a varint containg the size of the PMA in bytes into the file. */
- assert( pSorter->nBtree>0 );
-
for(
rc = vdbeSorterWriteVarint(pSorter->pTemp1, pSorter->nBtree, &iWriteOff);
rc==SQLITE_OK && res==0;
if( rc!=SQLITE_OK ) break;
}
+ /* This assert verifies that unless an error has occurred, the size of
+ ** the PMA on disk is the same as the expected size stored in
+ ** pSorter->nBtree. */
assert( rc!=SQLITE_OK || pSorter->nBtree==(
iWriteOff-pSorter->iWriteOff-sqlite3VarintLen(pSorter->nBtree)
));
+
pSorter->iWriteOff = iWriteOff;
sqlite3DbFree(db, aMalloc);
}
}
/*
-** This function is called on a sorter cursor before each row is inserted.
-** If the current b-tree being constructed is already considered "full",
-** a new tree is started.
+** This function is called on a sorter cursor by the VDBE before each row
+** is inserted into VdbeCursor.pCsr. Argument nKey is the size of the key, in
+** bytes, about to be inserted.
+**
+** If it is determined that the temporary b-tree accessed via VdbeCursor.pCsr
+** is large enough, its contents are written to a sorted PMA on disk and the
+** tree emptied. This prevents the b-tree (which must be small enough to
+** fit entirely in the cache in order to support efficient inserts) from
+** growing too large.
+**
+** An SQLite error code is returned if an error occurs. Otherwise, SQLITE_OK.
*/
int sqlite3VdbeSorterWrite(sqlite3 *db, VdbeCursor *pCsr, int nKey){
int rc = SQLITE_OK; /* Return code */
Pager *pPager = sqlite3BtreePager(pCsr->pBt);
int nPage; /* Current size of temporary file in pages */
+ /* Determine how many pages the temporary b-tree has grown to */
sqlite3PagerPagecount(pPager, &nPage);
/* If pSorter->nWorking is still zero, but the temporary file has been
** file in pages. */
if( pSorter->nWorking==0 && sqlite3PagerFile(pPager)->pMethods ){
pSorter->nWorking = nPage-5;
- if( pSorter->nWorking<SORTER_MIN_SEGMENT_SIZE ){
- pSorter->nWorking = SORTER_MIN_SEGMENT_SIZE;
+ if( pSorter->nWorking<SORTER_MIN_WORKING ){
+ pSorter->nWorking = SORTER_MIN_WORKING;
}
}
/*
** Copy the current sorter key into the memory cell pOut.
*/
-int sqlite3VdbeSorterRowkey(sqlite3 *db, VdbeCursor *pCsr, Mem *pOut){
+int sqlite3VdbeSorterRowkey(VdbeCursor *pCsr, Mem *pOut){
VdbeSorter *pSorter = pCsr->pSorter;
VdbeSorterIter *pIter;