return ((u16)aIn[0] << 8) + aIn[1];
}
+/*
+** This is a copy of the sqlite3GetVarint32() routine from the SQLite core.
+** Except, this version does handle the single byte case that the core
+** version depends on being handled before its function is called.
+*/
+int sqlite3Fts5GetVarint32(const unsigned char *p, u32 *v){
+ u32 a,b;
+
+ /* The 1-byte case. Overwhelmingly the most common. */
+ a = *p;
+ /* a: p0 (unmasked) */
+ if (!(a&0x80))
+ {
+ /* Values between 0 and 127 */
+ *v = a;
+ return 1;
+ }
+
+ /* The 2-byte case */
+ p++;
+ b = *p;
+ /* b: p1 (unmasked) */
+ if (!(b&0x80))
+ {
+ /* Values between 128 and 16383 */
+ a &= 0x7f;
+ a = a<<7;
+ *v = a | b;
+ return 2;
+ }
+
+ /* The 3-byte case */
+ p++;
+ a = a<<14;
+ a |= *p;
+ /* a: p0<<14 | p2 (unmasked) */
+ if (!(a&0x80))
+ {
+ /* Values between 16384 and 2097151 */
+ a &= (0x7f<<14)|(0x7f);
+ b &= 0x7f;
+ b = b<<7;
+ *v = a | b;
+ return 3;
+ }
+
+ /* A 32-bit varint is used to store size information in btrees.
+ ** Objects are rarely larger than 2MiB limit of a 3-byte varint.
+ ** A 3-byte varint is sufficient, for example, to record the size
+ ** of a 1048569-byte BLOB or string.
+ **
+ ** We only unroll the first 1-, 2-, and 3- byte cases. The very
+ ** rare larger cases can be handled by the slower 64-bit varint
+ ** routine.
+ */
+ {
+ u64 v64;
+ u8 n;
+ p -= 2;
+ n = sqlite3GetVarint(p, &v64);
+ *v = (u32)v64;
+ assert( n>3 && n<=9 );
+ return n;
+ }
+}
+
/*
** Allocate and return a buffer at least nByte bytes in size.
**
/* Read the total number of levels and segments from the start of the
** structure record. */
- i += getVarint32(&pData[i], nLevel);
- i += getVarint32(&pData[i], nSegment);
+ i += fts5GetVarint32(&pData[i], nLevel);
+ i += fts5GetVarint32(&pData[i], nSegment);
nByte = (
sizeof(Fts5Structure) + /* Main structure */
sizeof(Fts5StructureLevel) * (nLevel) /* aLevel[] array */
int nTotal;
int iSeg;
- i += getVarint32(&pData[i], pLvl->nMerge);
- i += getVarint32(&pData[i], nTotal);
+ i += fts5GetVarint32(&pData[i], pLvl->nMerge);
+ i += fts5GetVarint32(&pData[i], nTotal);
assert( nTotal>=pLvl->nMerge );
pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc,
nTotal * sizeof(Fts5StructureSegment)
if( rc==SQLITE_OK ){
pLvl->nSeg = nTotal;
for(iSeg=0; iSeg<nTotal; iSeg++){
- i += getVarint32(&pData[i], pLvl->aSeg[iSeg].iSegid);
- i += getVarint32(&pData[i], pLvl->aSeg[iSeg].nHeight);
- i += getVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoFirst);
- i += getVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoLast);
+ i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].iSegid);
+ i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].nHeight);
+ i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoFirst);
+ i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoLast);
}
}else{
fts5StructureRelease(pRet);
for(il=iPromote+1; il<pStruct->nLevel; il++){
Fts5StructureLevel *pLvl = &pStruct->aLevel[il];
+ if( pLvl->nMerge ) return;
for(is=pLvl->nSeg-1; is>=0; is--){
int sz = fts5SegmentSize(&pLvl->aSeg[is]);
if( sz>szPromote ) return;
/* Check for condition (a) */
for(iTst=iLvl-1; iTst>=0 && pStruct->aLevel[iTst].nSeg==0; iTst--);
pTst = &pStruct->aLevel[iTst];
- if( iTst>=0 && pTst->nMerge==0 ){
+ assert( pTst->nMerge==0 );
+ if( iTst>=0 ){
int i;
int szMax = 0;
for(i=0; i<pTst->nSeg; i++){
}
}
- /* Check for condition (b) */
+ /* If condition (a) is not met, assume (b) is true. StructurePromoteTo()
+ ** is a no-op if it is not. */
if( iPromote<0 ){
- Fts5StructureLevel *pTst;
- for(iTst=iLvl+1; iTst<pStruct->nLevel; iTst++){
- pTst = &pStruct->aLevel[iTst];
- if( pTst->nSeg ) break;
- }
- if( iTst<pStruct->nLevel && pTst->nMerge==0 ){
- Fts5StructureSegment *pSeg2 = &pTst->aSeg[pTst->nSeg-1];
- int sz = pSeg2->pgnoLast - pSeg2->pgnoFirst + 1;
- if( sz<=szSeg ){
- iPromote = iLvl;
- szPromote = szSeg;
- }
- }
- }
-
- /* If iPromote is greater than or equal to zero at this point, then it
- ** is the level number of a level to which segments that consist of
- ** szPromote or fewer pages should be promoted. */
- if( iPromote>=0 ){
- fts5PrintStructure("BEFORE", pStruct);
- fts5StructurePromoteTo(p, iPromote, szPromote, pStruct);
- fts5PrintStructure("AFTER", pStruct);
+ iPromote = iLvl;
+ szPromote = szSeg;
}
+ fts5StructurePromoteTo(p, iPromote, szPromote, pStruct);
}
}
if( pIter->iOff<pIter->nData && 0==(pIter->aData[pIter->iOff] & 0xfe) ){
pIter->bDlidx = pIter->aData[pIter->iOff] & 0x01;
pIter->iOff++;
- pIter->iOff += getVarint32(&pIter->aData[pIter->iOff], pIter->nEmpty);
+ pIter->iOff += fts5GetVarint32(&pIter->aData[pIter->iOff], pIter->nEmpty);
}else{
pIter->nEmpty = 0;
pIter->bDlidx = 0;
pIter->iChild += pIter->nEmpty;
}else{
int nPre, nNew;
- pIter->iOff += getVarint32(&pIter->aData[pIter->iOff], nPre);
- pIter->iOff += getVarint32(&pIter->aData[pIter->iOff], nNew);
+ pIter->iOff += fts5GetVarint32(&pIter->aData[pIter->iOff], nPre);
+ pIter->iOff += fts5GetVarint32(&pIter->aData[pIter->iOff], nNew);
pIter->term.n = nPre-2;
fts5BufferAppendBlob(pRc, &pIter->term, nNew, pIter->aData+pIter->iOff);
pIter->iOff += nNew;
memset(pIter, 0, sizeof(*pIter));
pIter->aData = aData;
pIter->nData = nData;
- pIter->iOff = getVarint32(aData, pIter->iChild);
+ pIter->iOff = fts5GetVarint32(aData, pIter->iChild);
fts5NodeIterGobbleNEmpty(pIter);
}
int iOff = pIter->iLeafOffset; /* Offset to read at */
int nNew; /* Bytes of new data */
- iOff += getVarint32(&a[iOff], nNew);
+ iOff += fts5GetVarint32(&a[iOff], nNew);
pIter->term.n = nKeep;
fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]);
iOff += nNew;
i64 iDelta = 0;
int nPos;
- i += getVarint32(&a[i], nPos);
+ i += fts5GetVarint32(&a[i], nPos);
i += nPos;
if( i>=n ) break;
i += getVarint(&a[i], (u64*)&iDelta);
pIter->iRowidOffset--;
pIter->iLeafOffset = iOff = pIter->aRowidOffset[pIter->iRowidOffset];
- iOff += getVarint32(&a[iOff], nPos);
+ iOff += fts5GetVarint32(&a[iOff], nPos);
iOff += nPos;
getVarint(&a[iOff], (u64*)&iDelta);
pIter->iRowid += iDelta;
iOff = pIter->iLeafOffset;
if( iOff<n ){
int nPoslist;
- iOff += getVarint32(&a[iOff], nPoslist);
+ iOff += fts5GetVarint32(&a[iOff], nPoslist);
iOff += nPoslist;
}
fts5SegIterNextPage(p, pIter);
pIter->iLeafOffset = 4;
}else if( iOff!=fts5GetU16(&a[2]) ){
- pIter->iLeafOffset += getVarint32(&a[iOff], nKeep);
+ pIter->iLeafOffset += fts5GetVarint32(&a[iOff], nKeep);
}
}else{
pIter->iRowid -= iDelta;
i64 iDelta;
/* Position list size in bytes */
- iOff += getVarint32(&pLeaf->p[iOff], nPos);
+ iOff += fts5GetVarint32(&pLeaf->p[iOff], nPos);
iOff += nPos;
if( iOff>=pLeaf->n ) break;
int nPoslist;
/* iOff is currently the offset of the size field of a position list. */
- iOff += getVarint32(&pLeaf->p[iOff], nPoslist);
+ iOff += fts5GetVarint32(&pLeaf->p[iOff], nPoslist);
iOff += nPoslist;
if( iOff<pLeaf->n ){
pLeaf = pIter->pLeaf;
}
- iOff += getVarint32(&pLeaf->p[iOff], pIter->nRem);
+ iOff += fts5GetVarint32(&pLeaf->p[iOff], pIter->nRem);
pIter->n = MIN(pLeaf->n - iOff, pIter->nRem);
pIter->p = pLeaf->p + iOff;
if( fts5ChunkIterEof(p, &pIter->chunk) ) return 0;
pIter->iOff = 0;
}
- pIter->iOff += getVarint32(&pIter->chunk.p[pIter->iOff], iVal);
+ pIter->iOff += fts5GetVarint32(&pIter->chunk.p[pIter->iOff], iVal);
}
return iVal;
}
}
static void fts5WriteBtreeGrow(Fts5Index *p, Fts5SegWriter *pWriter){
- Fts5PageWriter *aNew;
- Fts5PageWriter *pNew;
- int nNew = sizeof(Fts5PageWriter) * (pWriter->nWriter+1);
+ if( p->rc==SQLITE_OK ){
+ Fts5PageWriter *aNew;
+ Fts5PageWriter *pNew;
+ int nNew = sizeof(Fts5PageWriter) * (pWriter->nWriter+1);
- aNew = (Fts5PageWriter*)sqlite3_realloc(pWriter->aWriter, nNew);
- if( aNew==0 ) return;
+ aNew = (Fts5PageWriter*)sqlite3_realloc(pWriter->aWriter, nNew);
+ if( aNew==0 ){
+ p->rc = SQLITE_NOMEM;
+ return;
+ }
- pNew = &aNew[pWriter->nWriter];
- memset(pNew, 0, sizeof(Fts5PageWriter));
- pNew->pgno = 1;
- fts5BufferAppendVarint(&p->rc, &pNew->buf, 1);
+ pNew = &aNew[pWriter->nWriter];
+ memset(pNew, 0, sizeof(Fts5PageWriter));
+ pNew->pgno = 1;
+ fts5BufferAppendVarint(&p->rc, &pNew->buf, 1);
- pWriter->nWriter++;
- pWriter->aWriter = aNew;
+ pWriter->nWriter++;
+ pWriter->aWriter = aNew;
+ }
}
/*
#endif
if( nBest<p->pConfig->nAutomerge
- && pStruct->aLevel[iBestLvl].nMerge==0
- ){
+ && pStruct->aLevel[iBestLvl].nMerge==0
+ ){
break;
}
fts5IndexMergeLevel(p, iIdx, &pStruct, iBestLvl, &nRem);
- fts5StructurePromote(p, iBestLvl+1, pStruct);
assert( nRem==0 || p->rc==SQLITE_OK );
+ if( p->rc==SQLITE_OK && pStruct->aLevel[iBestLvl].nMerge==0 ){
+ fts5StructurePromote(p, iBestLvl+1, pStruct);
+ }
*ppStruct = pStruct;
}
}
pSeg->pgnoFirst = 1;
pSeg->pgnoLast = pgnoLast;
}
+ fts5StructurePromote(p, 0, pStruct);
}
if( p->pConfig->nAutomerge>0 ) fts5IndexWork(p, iHash, &pStruct, pgnoLast);
}else{
int nTerm; /* Size of term on leaf in bytes */
int res; /* Comparison of term and split-key */
- iOff += getVarint32(&pLeaf->p[iOff], nTerm);
+ iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm);
res = memcmp(&pLeaf->p[iOff], iter.term.p, MIN(nTerm, iter.term.n));
if( res==0 ) res = nTerm - iter.term.n;
if( res<0 ){
}else{
pIter->i += getVarint(&pIter->a[pIter->i], (u64*)&pIter->iRowid);
}
- pIter->i += getVarint32(&pIter->a[pIter->i], pIter->nPoslist);
+ pIter->i += fts5GetVarint32(&pIter->a[pIter->i], pIter->nPoslist);
pIter->aPoslist = &pIter->a[pIter->i];
pIter->i += pIter->nPoslist;
}else{
&& ((!bAsc && iRowid>=iLastRowid) || (bAsc && iRowid<=iLastRowid))
){
- for(i=0; doclist.n && p->rc==SQLITE_OK; i++){
+ for(i=0; p->rc==SQLITE_OK && doclist.n; i++){
assert( i<nBuf );
if( aBuf[i].n==0 ){
fts5BufferSwap(&doclist, &aBuf[i]);
int iOff = 0;
while( iOff<n ){
int iVal;
- iOff += getVarint32(&a[iOff], iVal);
+ iOff += fts5GetVarint32(&a[iOff], iVal);
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %d", iVal);
}
return iOff;
}
while( iOff<n ){
int nPos;
- iOff += getVarint32(&a[iOff], nPos);
+ iOff += fts5GetVarint32(&a[iOff], nPos);
iOff += fts5DecodePoslist(pRc, pBuf, &a[iOff], MIN(n-iOff, nPos));
if( iOff<n ){
i64 iDelta;
assert( iTermOff==0 || iOff==iTermOff );
while( iOff<n ){
int nByte;
- iOff += getVarint32(&a[iOff], nByte);
+ iOff += fts5GetVarint32(&a[iOff], nByte);
term.n= nKeep;
fts5BufferAppendBlob(&rc, &term, nByte, &a[iOff]);
iOff += nByte;
);
iOff += fts5DecodeDoclist(&rc, &s, &a[iOff], n-iOff);
if( iOff<n ){
- iOff += getVarint32(&a[iOff], nKeep);
+ iOff += fts5GetVarint32(&a[iOff], nKeep);
}
}
fts5BufferFree(&term);
-C Further\stests\sand\sfixes\sfor\sfts5.
-D 2015-01-21T20:30:14.830
+C Add\sfurther\stests\sand\sfixes\sfor\sfts5.
+D 2015-01-22T19:13:08.439
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 5407a688f4d77a05c18a8142be8ae5a2829dd610
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F ext/fts5/extract_api_docs.tcl 55a6d648d516f35d9a1e580ac00de27154e1904a
F ext/fts5/fts5.c 0ba5a8f27e1aa4deab82f0fc295d55f67dfe7f34
F ext/fts5/fts5.h f931954065693898d26c51f23f1d27200184a69a
-F ext/fts5/fts5Int.h b593d5ff5f0cc6493778f88bc19db1dea42e003b
+F ext/fts5/fts5Int.h 99da8551098bb23fd94d0aa3f4ae1a411ee630b4
F ext/fts5/fts5_aux.c 549aef152b0fd46020f5595d861b1fd60b3f9b4f
F ext/fts5/fts5_buffer.c 32dd3c950392346ca69a0f1803501766c5c954f9
F ext/fts5/fts5_config.c 33534ca25198cc62c54ff7d285d455c57ad19399
F ext/fts5/fts5_expr.c 8a0e643768666dc2bffe74104141274809699808
-F ext/fts5/fts5_hash.c 63fa8379c5f2ac107d47c2b7d9ac04c95ef8a279
-F ext/fts5/fts5_index.c baf26bfee5bd776194c0e508e3c101964ae851c6
+F ext/fts5/fts5_hash.c 7a87f9f2eae2216c710064821fa0621ac6a8ce7b
+F ext/fts5/fts5_index.c ee7b141adde3dbdaa56f1e198c06a0786d298126
F ext/fts5/fts5_storage.c d56722960982d0c48ba1b88d9001fefed8cff1a4
F ext/fts5/fts5_tcl.c 1293fac2bb26903fd3d5cdee59c5885ba7e620d5
F ext/fts5/fts5_tokenize.c 7c61d5c35c3449597bdeaa54dd48afe26852c7b0
F ext/fts5/fts5_unicode2.c 9c7dd640d1f014bf5c3ee029759adfbb4d7e95a9
F ext/fts5/fts5parse.y 777da8e5819f75c217982c79c29d014c293acac9
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
-F ext/fts5/test/fts5_common.tcl 08e939096a07eb77a7a986613e960f31d3cab2cc
+F ext/fts5/test/fts5_common.tcl 7db772d34fa0139d4b58d2b321928c9ccd30f699
F ext/fts5/test/fts5aa.test 8ddbbcbedab67101dc9a86fd5c39d78b0e06515f
-F ext/fts5/test/fts5ab.test 91a3faac09ad9fab5f71494db6e4071963281536
+F ext/fts5/test/fts5ab.test 3f3ad2fb9ed60a0df57b626fa6fe6ef41d4deee0
F ext/fts5/test/fts5ac.test 48181b7c873da0e3b4a3316760fcb90d88e7fbd8
F ext/fts5/test/fts5ad.test 3b01eec8516d5631909716514e2e585a45ef0eb1
F ext/fts5/test/fts5ae.test 014d5be2f5f70407fb032d4f27704116254797c3
F ext/fts5/test/fts5content.test 4234e0b11e003fe1e80472aa637f70464396fdd0
F ext/fts5/test/fts5ea.test 04695560a444fcc00c3c4f27783bdcfbf71f030c
F ext/fts5/test/fts5eb.test 728a1f23f263548f5c29b29dfb851b5f2dbe723e
-F ext/fts5/test/fts5fault1.test 405886f4ecd255fa7a7077c021a65c9f8eaa4804
+F ext/fts5/test/fts5fault1.test f9bafb61b40061ad19b61d15003c5faeea4a57b5
F ext/fts5/test/fts5near.test 3f9f64e16cac82725d03d4e04c661090f0b3b947
F ext/fts5/test/fts5optimize.test 0028c90a7817d3e576d1148fc8dff17d89054e54
F ext/fts5/test/fts5porter.test 50322599823cb8080a99f0ec0c39f7d0c12bcb5e
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P e0d614425f7f5ffe266fdc03642931b1ec19ad25
-R c0a23f610b9ed738a5e0737db6938cae
+P c020a291ed293a66d21c5885e50a7fee04aa6366
+R 244beb886a9d1f5f10328b67a9ad3f5b
U dan
-Z 2e4179b4673c6b65260289e1eab737a6
+Z 4d510e0e441ea9491ac2e8425faae5c2