mirror of https://github.com/sqlite/sqlite
Merge leaf accidentally created by [1c4984c62f].
FossilOrigin-Name: cae949ce971ca216e0f8880b2f93866619fa05be
This commit is contained in:
commit
e6828f5503
|
@ -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 ){
|
||||
|
|
16
manifest
16
manifest
|
@ -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
|
||||
|
|
|
@ -1 +1 @@
|
|||
1c4984c62f393f41f9182ea82546c16d02efa46f
|
||||
cae949ce971ca216e0f8880b2f93866619fa05be
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue