/* ** Initialize iterator pIter to scan through the PMA stored in file pFile ** starting at offset iStart and ending at offset iEof-1. This function ** leaves the iterator pointing to the first key in the PMA (or EOF if the ** PMA is empty). */ static int vdbeSorterIterInit( sqlite3 *db, /* Database handle */ VdbeSorter *pSorter, /* Sorter object */ i64 iStart, /* Start offset in pFile */ VdbeSorterIter *pIter, /* Iterator to populate */ i64 *pnByte /* IN/OUT: Increment this value by PMA size */ ){ int rc; assert( pSorter->iWriteOff>iStart ); assert( pIter->aAlloc==0 ); pIter->pFile = pSorter->pTemp1; pIter->iReadOff = iStart; pIter->nAlloc = 128; pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc); if( !pIter->aAlloc ){ rc = SQLITE_NOMEM; }else{ i64 nByte; /* Total size of PMA in bytes */ rc = vdbeSorterReadVarint(pSorter->pTemp1, &pIter->iReadOff, &nByte); *pnByte += nByte; pIter->iEof = pIter->iReadOff + nByte; } if( rc==SQLITE_OK ){ rc = vdbeSorterIterNext(db, pIter); } return rc; }
/* ** Initialize iterator pIter to scan through the PMA stored in file pFile ** starting at offset iStart and ending at offset iEof-1. This function ** leaves the iterator pointing to the first key in the PMA (or EOF if the ** 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 */ i64 *pnByte /* IN/OUT: Increment this value by PMA size */ ){ int rc = SQLITE_OK; int nBuf; nBuf = sqlite3BtreeGetPageSize(db->aDb[0].pBt); assert( pSorter->iWriteOff>iStart ); assert( pIter->aAlloc==0 ); assert( pIter->aBuffer==0 ); pIter->pFile = pSorter->pTemp1; pIter->iReadOff = iStart; pIter->nAlloc = 128; pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc); pIter->nBuffer = nBuf; pIter->aBuffer = (u8 *)sqlite3DbMallocRaw(db, nBuf); if( !pIter->aBuffer ){ rc = SQLITE_NOMEM; }else{ int iBuf; iBuf = iStart % nBuf; if( iBuf ){ int nRead = nBuf - iBuf; if( (iStart + nRead) > pSorter->iWriteOff ){ nRead = (int)(pSorter->iWriteOff - iStart); } rc = sqlite3OsRead( pSorter->pTemp1, &pIter->aBuffer[iBuf], nRead, iStart ); assert( rc!=SQLITE_IOERR_SHORT_READ ); } if( rc==SQLITE_OK ){ u64 nByte; /* Size of PMA in bytes */ pIter->iEof = pSorter->iWriteOff; rc = vdbeSorterIterVarint(db, pIter, &nByte); pIter->iEof = pIter->iReadOff + nByte; *pnByte += nByte; } } if( rc==SQLITE_OK ){ rc = vdbeSorterIterNext(db, pIter); } return rc; }
/* ** Advance to the next element in the sorter. */ int sqlite3VdbeSorterNext(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){ VdbeSorter *pSorter = pCsr->pSorter; 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]); for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){ rc = vdbeSorterDoCompare(pCsr, i); } *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0); }else{ SorterRecord *pFree = pSorter->pRecord; pSorter->pRecord = pFree->pNext; pFree->pNext = 0; vdbeSorterRecordFree(db, pFree); *pbEof = !pSorter->pRecord; rc = SQLITE_OK; } return rc; }