Merge leaf accidentally created by [1c4984c62f].

FossilOrigin-Name: cae949ce971ca216e0f8880b2f93866619fa05be
This commit is contained in:
dan 2009-11-20 10:23:12 +00:00
commit e6828f5503
5 changed files with 144 additions and 46 deletions

View File

@ -834,6 +834,9 @@ void sqlite3Fts3SegReaderFree(Fts3Table *p, Fts3SegReader *pReader){
}
}
/*
** Allocate a new SegReader object.
*/
int sqlite3Fts3SegReaderNew(
Fts3Table *p, /* Virtual table handle */
int iAge, /* Segment "age". */
@ -963,7 +966,8 @@ static int fts3SegReaderNew(
}
/*
** Compare the two Fts3SegReader structures. Comparison is as follows:
** Compare the entries pointed to by two Fts3SegReader structures.
** Comparison is as follows:
**
** 1) EOF is greater than not EOF.
**
@ -995,11 +999,22 @@ static int fts3SegReaderCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
return rc;
}
static int fts3SegReaderCmp2(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
/*
** A different comparison function for SegReader structures. In this
** version, it is assumed that each SegReader points to an entry in
** a doclist for identical terms. Comparison is made as follows:
**
** 1) EOF (end of doclist in this case) is greater than not EOF.
**
** 2) By current docid.
**
** 3) By segment age. An older segment is considered larger.
*/
static int fts3SegReaderDoclistCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0);
if( rc==0 ){
if( pLhs->iDocid==pRhs->iDocid ){
rc = pRhs->iIdx-pLhs->iIdx;
rc = pRhs->iIdx - pLhs->iIdx;
}else{
rc = (pLhs->iDocid > pRhs->iDocid) ? 1 : -1;
}
@ -1075,9 +1090,10 @@ static void fts3SegReaderSort(
** Insert a record into the %_segments table.
*/
static int fts3WriteSegment(
Fts3Table *p,
sqlite3_int64 iBlock,
char *z, int n
Fts3Table *p, /* Virtual table handle */
sqlite3_int64 iBlock, /* Block id for new block */
char *z, /* Pointer to buffer containing block data */
int n /* Size of buffer z in bytes */
){
sqlite3_stmt *pStmt;
int rc = fts3SqlStmt(p, SQL_INSERT_SEGMENTS, &pStmt, 0);
@ -1096,7 +1112,7 @@ static int fts3WriteSegment(
** Insert a record into the %_segdir table.
*/
static int fts3WriteSegdir(
Fts3Table *p, /* Virtual table handle */
Fts3Table *p, /* Virtual table handle */
int iLevel, /* Value for "level" field */
int iIdx, /* Value for "idx" field */
sqlite3_int64 iStartBlock, /* Value for "start_block" field */
@ -1122,16 +1138,23 @@ static int fts3WriteSegdir(
return rc;
}
static void fts3PrefixCompress(
const char *zPrev,
int nPrev,
const char *zNext,
int nNext,
int *pnPrefix
/*
** Return the size of the common prefix (if any) shared by zPrev and
** zNext, in bytes. For example,
**
** fts3PrefixCompress("abc", 3, "abcdef", 6) // returns 3
** fts3PrefixCompress("abX", 3, "abcdef", 6) // returns 2
** fts3PrefixCompress("abX", 3, "Xbcdef", 6) // returns 0
*/
static int fts3PrefixCompress(
const char *zPrev, /* Buffer containing previous term */
int nPrev, /* Size of buffer zPrev in bytes */
const char *zNext, /* Buffer containing next term */
int nNext /* Size of buffer zNext in bytes */
){
int n;
for(n=0; n<nPrev && zPrev[n]==zNext[n]; n++);
*pnPrefix = n;
return n;
}
/*
@ -1158,7 +1181,7 @@ static int fts3NodeAddTerm(
int nPrefix; /* Number of bytes of prefix compression */
int nSuffix; /* Suffix length */
fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm, &nPrefix);
nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm);
nSuffix = nTerm-nPrefix;
nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix;
@ -1263,10 +1286,20 @@ static int fts3TreeFinishNode(
}
/*
** Helper function for fts3NodeWrite().
** Write the buffer for the segment node pTree and all of its peers to the
** database. Then call this function recursively to write the parent of
** pTree and its peers to the database.
**
** Except, if pTree is a root node, do not write it to the database. Instead,
** set output variables *paRoot and *pnRoot to contain the root node.
**
** If successful, SQLITE_OK is returned and output variable *piLast is
** set to the largest blockid written to the database (or zero if no
** blocks were written to the db). Otherwise, an SQLite error code is
** returned.
*/
static int fts3NodeWrite(
Fts3Table *p, /* Virtual table handle */
Fts3Table *p, /* Virtual table handle */
SegmentNode *pTree, /* SegmentNode handle */
int iHeight, /* Height of this node in tree */
sqlite3_int64 iLeaf, /* Block id of first leaf node */
@ -1326,6 +1359,14 @@ static void fts3NodeFree(SegmentNode *pTree){
}
}
/*
** Add a term to the segment being constructed by the SegmentWriter object
** *ppWriter. When adding the first term to a segment, *ppWriter should
** be passed NULL. This function will allocate a new SegmentWriter object
** and return it via the input/output variable *ppWriter in this case.
**
** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code.
*/
static int fts3SegWriterAdd(
Fts3Table *p, /* Virtual table handle */
SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */
@ -1368,7 +1409,7 @@ static int fts3SegWriterAdd(
}
nData = pWriter->nData;
fts3PrefixCompress(pWriter->zTerm, pWriter->nTerm, zTerm, nTerm, &nPrefix);
nPrefix = fts3PrefixCompress(pWriter->zTerm, pWriter->nTerm, zTerm, nTerm);
nSuffix = nTerm-nPrefix;
/* Figure out how many bytes are required by this new entry */
@ -1458,18 +1499,26 @@ static int fts3SegWriterAdd(
return SQLITE_OK;
}
/*
** Flush all data associated with the SegmentWriter object pWriter to the
** database. This function must be called after all terms have been added
** to the segment using fts3SegWriterAdd(). If successful, SQLITE_OK is
** returned. Otherwise, an SQLite error code.
*/
static int fts3SegWriterFlush(
Fts3Table *p,
SegmentWriter *pWriter,
int iLevel,
int iIdx
Fts3Table *p, /* Virtual table handle */
SegmentWriter *pWriter, /* SegmentWriter to flush to the db */
int iLevel, /* Value for 'level' column of %_segdir */
int iIdx /* Value for 'idx' column of %_segdir */
){
int rc;
int rc; /* Return code */
if( pWriter->pTree ){
sqlite3_int64 iLast;
char *zRoot;
int nRoot;
sqlite3_int64 iLastLeaf = pWriter->iFree;
sqlite3_int64 iLast; /* Largest block id written to database */
sqlite3_int64 iLastLeaf; /* Largest leaf block id written to db */
char *zRoot; /* Pointer to buffer containing root node */
int nRoot; /* Size of buffer zRoot */
iLastLeaf = pWriter->iFree;
rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, pWriter->nData);
if( rc==SQLITE_OK ){
rc = fts3NodeWrite(p, pWriter->pTree, 1,
@ -1487,6 +1536,10 @@ static int fts3SegWriterFlush(
return rc;
}
/*
** Release all memory held by the SegmentWriter object passed as the
** first argument.
*/
static void fts3SegWriterFree(SegmentWriter *pWriter){
if( pWriter ){
sqlite3_free(pWriter->aData);
@ -1519,6 +1572,11 @@ static int fts3IsEmpty(Fts3Table *p, sqlite3_value **apVal, int *pisEmpty){
return rc;
}
/*
** Set *pnSegment to the number of segments of level iLevel in the database.
**
** Return SQLITE_OK if successful, or an SQLite error code if not.
*/
static int fts3SegmentCount(Fts3Table *p, int iLevel, int *pnSegment){
sqlite3_stmt *pStmt;
int rc;
@ -1533,6 +1591,13 @@ static int fts3SegmentCount(Fts3Table *p, int iLevel, int *pnSegment){
return sqlite3_reset(pStmt);
}
/*
** Set *pnSegment to the total number of segments in the database. Set
** *pnMax to the largest segment level in the database (segment levels
** are stored in the 'level' column of the %_segdir table).
**
** Return SQLITE_OK if successful, or an SQLite error code if not.
*/
static int fts3SegmentCountMax(Fts3Table *p, int *pnSegment, int *pnMax){
sqlite3_stmt *pStmt;
int rc;
@ -1546,11 +1611,25 @@ static int fts3SegmentCountMax(Fts3Table *p, int *pnSegment, int *pnMax){
return sqlite3_reset(pStmt);
}
/*
** This function is used after merging multiple segments into a single large
** segment to delete the old, now redundant, segment b-trees. Specifically,
** it:
**
** 1) Deletes all %_segments entries for the segments associated with
** each of the SegReader objects in the array passed as the third
** argument, and
**
** 2) deletes all %_segdir entries with level iLevel, or all %_segdir
** entries regardless of level if (iLevel<0).
**
** SQLITE_OK is returned if successful, otherwise an SQLite error code.
*/
static int fts3DeleteSegdir(
Fts3Table *p,
int iLevel,
Fts3SegReader **apSegment,
int nReader
Fts3Table *p, /* Virtual table handle */
int iLevel, /* Level of %_segdir entries to delete */
Fts3SegReader **apSegment, /* Array of SegReader objects */
int nReader /* Size of array apSegment */
){
int rc; /* Return Code */
int i; /* Iterator variable */
@ -1584,7 +1663,20 @@ static int fts3DeleteSegdir(
return rc;
}
static void fts3ColumnFilter(int iCol, char **ppList, int *pnList){
/*
** When this function is called, buffer *ppList (size *pnList bytes) contains
** a position list that may (or may not) feature multiple columns. This
** function adjusts the pointer *ppList and the length *pnList so that they
** identify the subset of the position list that corresponds to column iCol.
**
** If there are no entries in the input position list for column iCol, then
** *pnList is set to zero before returning.
*/
static void fts3ColumnFilter(
int iCol, /* Column to filter on */
char **ppList, /* IN/OUT: Pointer to position list */
int *pnList /* IN/OUT: Size of buffer *ppList in bytes */
){
char *pList = *ppList;
int nList = *pnList;
char *pEnd = &pList[nList];
@ -1614,6 +1706,10 @@ static void fts3ColumnFilter(int iCol, char **ppList, int *pnList){
*pnList = nList;
}
/*
** sqlite3Fts3SegReaderIterate() callback used when merging multiple
** segments to create a single, larger segment.
*/
static int fts3MergeCallback(
Fts3Table *p,
void *pContext,
@ -1707,7 +1803,7 @@ int sqlite3Fts3SegReaderIterate(
for(i=0; i<nMerge; i++){
fts3SegReaderFirstDocid(apSegment[i]);
}
fts3SegReaderSort(apSegment, nMerge, nMerge, fts3SegReaderCmp2);
fts3SegReaderSort(apSegment, nMerge, nMerge, fts3SegReaderDoclistCmp);
while( apSegment[0]->pOffsetList ){
int j; /* Number of segments that share a docid */
char *pList;
@ -1749,7 +1845,7 @@ int sqlite3Fts3SegReaderIterate(
}
}
fts3SegReaderSort(apSegment, nMerge, j, fts3SegReaderCmp2);
fts3SegReaderSort(apSegment, nMerge, j, fts3SegReaderDoclistCmp);
}
if( nDoclist>0 ){

View File

@ -1,5 +1,5 @@
C Add\sa\stest\sto\smake\ssure\sa\sdatabase\scan\sbe\sattached\sto\sa\ssingle\shandle\stwice\sif\snot\sin\sshared-cache\smode.
D 2009-11-20T10:18:06
C Merge\sleaf\saccidentally\screated\sby\s[1c4984c62f].
D 2009-11-20T10:23:13
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 7f6c6aa7feeeb5e26e01b344161d9aa1b5d64177
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -68,7 +68,7 @@ F ext/fts3/fts3_snippet.c 082f2906deaaa2656f19b88834e89d099352af6e
F ext/fts3/fts3_tokenizer.c 36f78d1a43a29b0feaec1ced6da9e56b9c653d1f
F ext/fts3/fts3_tokenizer.h 7ff73caa3327589bf6550f60d93ebdd1f6a0fb5c
F ext/fts3/fts3_tokenizer1.c 0a5bcc579f35de5d24a9345d7908dc25ae403ee7
F ext/fts3/fts3_write.c 6b9b4fd998fc2cbc05859b79af559b32792023ab
F ext/fts3/fts3_write.c 69e6fb5a387aa7eb1f9d89e5bce35d21b879602e
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/icu/README.txt 3b130aa66e7a681136f6add198b076a2f90d1e33
F ext/icu/icu.c 12e763d288d23b5a49de37caa30737b971a2f1e2
@ -162,7 +162,7 @@ F src/printf.c 03fabdd6112a0e23f78f8ac9a1396947ade0273b
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c aa3cb21e1ecd905c071fce8fb64d1a166cefc239
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c a727f61f3267bfa20ce1c3e85d38dc2132db1060
F src/select.c 2f9ed7482e7a25b0b127fc41693bbdbe1caf5647
F src/shell.c f4948cb6d30665d755a6b5e0ec313d1094aab828
F src/sqlite.h.in 4464e9772122f0447305d425e04d122b6f1bffec
F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
@ -209,7 +209,7 @@ F src/update.c 8efeb09822886e33c265dd96d29a3d865ea6dcf2
F src/utf.c dad16adcc0c35ef2437dca125a4b07419d361052
F src/util.c ad4f03079ba0fe83590d1cc9197e8e4844e38592
F src/vacuum.c 03309a08d549f9389cc3a3589afd4fadbdaf0679
F src/vdbe.c 95fa2b51a4e602f74594bd9a0f679b7eaf44f9c0
F src/vdbe.c 89d618dd0b4544e319dfab84db7356e7ee5aa430
F src/vdbe.h 5f35750615163d1064052785b4a9f0eb004a720d
F src/vdbeInt.h d7ea821ac7813c9bea0fe87558c35e07b2c7c44d
F src/vdbeapi.c 17680ab7a75ec938c5ba039a6c87489d01faf2cb
@ -772,7 +772,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P 9a429349ccc2fa9acd28365a86578f602e87dafb
R 46119cb7f99f2b8740a6d715a49a25dc
P 1c4984c62f393f41f9182ea82546c16d02efa46f c6ed7e2a73a7a65cfa914ffcad4f603b6b7a22a8
R a4c740bd2d6cd6d5d405c025a9a5ce19
U dan
Z 45d94d950c686cbe6192e3168ebbb70a
Z 4d4aca1de07a44952499e25e5fd5b2ca

View File

@ -1 +1 @@
1c4984c62f393f41f9182ea82546c16d02efa46f
cae949ce971ca216e0f8880b2f93866619fa05be

View File

@ -1323,11 +1323,10 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
v = sqlite3GetVdbe(pParse);
if( NEVER(v==0) ) return; /* VDBE should have already been allocated */
if( sqlite3ExprIsInteger(p->pLimit, &n) ){
sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
VdbeComment((v, "LIMIT counter"));
if( n==0 ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak);
}else{
sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
VdbeComment((v, "LIMIT counter"));
}
}else{
sqlite3ExprCode(pParse, p->pLimit, iLimit);

View File

@ -543,6 +543,7 @@ int sqlite3VdbeExec(
Op *pOp; /* Current operation */
int rc = SQLITE_OK; /* Value to return */
sqlite3 *db = p->db; /* The database */
u8 resetSchemaOnFault = 0; /* Reset schema after an error if true */
u8 encoding = ENC(db); /* The database encoding */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
u8 checkProgress; /* True if progress callbacks are enabled */
@ -4430,6 +4431,7 @@ case OP_Destroy: { /* out2-prerelease */
#ifndef SQLITE_OMIT_AUTOVACUUM
if( rc==SQLITE_OK && iMoved!=0 ){
sqlite3RootPageMoved(&db->aDb[iDb], iMoved, pOp->p1);
resetSchemaOnFault = 1;
}
#endif
}
@ -5709,6 +5711,7 @@ vdbe_error_halt:
sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
rc = SQLITE_ERROR;
if( resetSchemaOnFault ) sqlite3ResetInternalSchema(db, 0);
/* This is the only way out of this procedure. We have to
** release the mutexes on btrees that were acquired at the