DBD-SQLite-Amalgamation
view release on metacpan or search on metacpan
sqlite-amalgamation.c view on Meta::CPAN
dataBufferReplace(&pReader->term, pData+1+n, nTerm);
/* Position after the first term. */
assert( 1+n+nTerm<nData );
pReader->pData = pData+1+n+nTerm;
pReader->nData = nData-1-n-nTerm;
}
/* Step the reader forward to the next term. */
static void leafReaderStep(LeafReader *pReader){
int n, nData, nPrefix, nSuffix;
assert( !leafReaderAtEnd(pReader) );
/* Skip previous entry's data block. */
n = fts3GetVarint32(pReader->pData, &nData);
assert( n+nData<=pReader->nData );
pReader->pData += n+nData;
pReader->nData -= n+nData;
if( !leafReaderAtEnd(pReader) ){
/* Construct the new term using a prefix from the old term plus a
** suffix from the leaf data.
*/
n = fts3GetVarint32(pReader->pData, &nPrefix);
n += fts3GetVarint32(pReader->pData+n, &nSuffix);
assert( n+nSuffix<pReader->nData );
pReader->term.nData = nPrefix;
dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix);
pReader->pData += n+nSuffix;
pReader->nData -= n+nSuffix;
}
}
/* strcmp-style comparison of pReader's current term against pTerm.
** If isPrefix, equality means equal through nTerm bytes.
*/
static int leafReaderTermCmp(LeafReader *pReader,
const char *pTerm, int nTerm, int isPrefix){
int c, n = pReader->term.nData<nTerm ? pReader->term.nData : nTerm;
if( n==0 ){
if( pReader->term.nData>0 ) return -1;
if(nTerm>0 ) return 1;
return 0;
}
c = memcmp(pReader->term.pData, pTerm, n);
if( c!=0 ) return c;
if( isPrefix && n==nTerm ) return 0;
return pReader->term.nData - nTerm;
}
/****************************************************************/
/* LeavesReader wraps LeafReader to allow iterating over the entire
** leaf layer of the tree.
*/
typedef struct LeavesReader {
int idx; /* Index within the segment. */
sqlite3_stmt *pStmt; /* Statement we're streaming leaves from. */
int eof; /* we've seen SQLITE_DONE from pStmt. */
LeafReader leafReader; /* reader for the current leaf. */
DataBuffer rootData; /* root data for inline. */
} LeavesReader;
/* Access the current term. */
static int leavesReaderTermBytes(LeavesReader *pReader){
assert( !pReader->eof );
return leafReaderTermBytes(&pReader->leafReader);
}
static const char *leavesReaderTerm(LeavesReader *pReader){
assert( !pReader->eof );
return leafReaderTerm(&pReader->leafReader);
}
/* Access the doclist data for the current term. */
static int leavesReaderDataBytes(LeavesReader *pReader){
assert( !pReader->eof );
return leafReaderDataBytes(&pReader->leafReader);
}
static const char *leavesReaderData(LeavesReader *pReader){
assert( !pReader->eof );
return leafReaderData(&pReader->leafReader);
}
static int leavesReaderAtEnd(LeavesReader *pReader){
return pReader->eof;
}
/* loadSegmentLeaves() may not read all the way to SQLITE_DONE, thus
** leaving the statement handle open, which locks the table.
*/
/* TODO(shess) This "solution" is not satisfactory. Really, there
** should be check-in function for all statement handles which
** arranges to call sqlite3_reset(). This most likely will require
** modification to control flow all over the place, though, so for now
** just punt.
**
** Note the the current system assumes that segment merges will run to
** completion, which is why this particular probably hasn't arisen in
** this case. Probably a brittle assumption.
*/
static int leavesReaderReset(LeavesReader *pReader){
return sqlite3_reset(pReader->pStmt);
}
static void leavesReaderDestroy(LeavesReader *pReader){
/* If idx is -1, that means we're using a non-cached statement
** handle in the optimize() case, so we need to release it.
*/
if( pReader->pStmt!=NULL && pReader->idx==-1 ){
sqlite3_finalize(pReader->pStmt);
}
leafReaderDestroy(&pReader->leafReader);
dataBufferDestroy(&pReader->rootData);
SCRAMBLE(pReader);
}
/* Initialize pReader with the given root data (if iStartBlockid==0
( run in 0.698 second using v1.01-cache-2.11-cpan-140bd7fdf52 )