Index: third_party/sqlite/src/ext/fts3/fts3_write.c |
diff --git a/third_party/sqlite/src/ext/fts3/fts3_write.c b/third_party/sqlite/src/ext/fts3/fts3_write.c |
index 0da08c62d8bd05f7650b428d254d66369244193b..d5a408222ec790eb3ed7c9a32c33182fd954039e 100644 |
--- a/third_party/sqlite/src/ext/fts3/fts3_write.c |
+++ b/third_party/sqlite/src/ext/fts3/fts3_write.c |
@@ -326,7 +326,7 @@ static int fts3SqlStmt( |
/* 25 */ "", |
/* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?", |
-/* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'", |
+/* 27 */ "SELECT ? UNION SELECT level / (1024 * ?) FROM %Q.'%q_segdir'", |
/* This statement is used to determine which level to read the input from |
** when performing an incremental merge. It returns the absolute level number |
@@ -860,10 +860,12 @@ static int fts3PendingTermsAdd( |
*/ |
static int fts3PendingTermsDocid( |
Fts3Table *p, /* Full-text table handle */ |
+ int bDelete, /* True if this op is a delete */ |
int iLangid, /* Language id of row being written */ |
sqlite_int64 iDocid /* Docid of row being written */ |
){ |
assert( iLangid>=0 ); |
+ assert( bDelete==1 || bDelete==0 ); |
/* TODO(shess) Explore whether partially flushing the buffer on |
** forced-flush would provide better performance. I suspect that if |
@@ -871,7 +873,8 @@ static int fts3PendingTermsDocid( |
** buffer was half empty, that would let the less frequent terms |
** generate longer doclists. |
*/ |
- if( iDocid<=p->iPrevDocid |
+ if( iDocid<p->iPrevDocid |
+ || (iDocid==p->iPrevDocid && p->bPrevDelete==0) |
|| p->iPrevLangid!=iLangid |
|| p->nPendingData>p->nMaxPendingData |
){ |
@@ -880,6 +883,7 @@ static int fts3PendingTermsDocid( |
} |
p->iPrevDocid = iDocid; |
p->iPrevLangid = iLangid; |
+ p->bPrevDelete = bDelete; |
return SQLITE_OK; |
} |
@@ -1069,7 +1073,8 @@ static void fts3DeleteTerms( |
if( SQLITE_ROW==sqlite3_step(pSelect) ){ |
int i; |
int iLangid = langidFromSelect(p, pSelect); |
- rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0)); |
+ i64 iDocid = sqlite3_column_int64(pSelect, 0); |
+ rc = fts3PendingTermsDocid(p, 1, iLangid, iDocid); |
for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ |
int iCol = i-1; |
if( p->abNotindexed[iCol]==0 ){ |
@@ -1317,14 +1322,19 @@ static int fts3SegReaderNext( |
if( fts3SegReaderIsPending(pReader) ){ |
Fts3HashElem *pElem = *(pReader->ppNextElem); |
- if( pElem==0 ){ |
- pReader->aNode = 0; |
- }else{ |
+ sqlite3_free(pReader->aNode); |
+ pReader->aNode = 0; |
+ if( pElem ){ |
+ char *aCopy; |
PendingList *pList = (PendingList *)fts3HashData(pElem); |
+ int nCopy = pList->nData+1; |
pReader->zTerm = (char *)fts3HashKey(pElem); |
pReader->nTerm = fts3HashKeysize(pElem); |
- pReader->nNode = pReader->nDoclist = pList->nData + 1; |
- pReader->aNode = pReader->aDoclist = pList->aData; |
+ aCopy = (char*)sqlite3_malloc(nCopy); |
+ if( !aCopy ) return SQLITE_NOMEM; |
+ memcpy(aCopy, pList->aData, nCopy); |
+ pReader->nNode = pReader->nDoclist = nCopy; |
+ pReader->aNode = pReader->aDoclist = aCopy; |
pReader->ppNextElem++; |
assert( pReader->aNode ); |
} |
@@ -1564,12 +1574,14 @@ int sqlite3Fts3MsrOvfl( |
** second argument. |
*/ |
void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){ |
- if( pReader && !fts3SegReaderIsPending(pReader) ){ |
- sqlite3_free(pReader->zTerm); |
+ if( pReader ){ |
+ if( !fts3SegReaderIsPending(pReader) ){ |
+ sqlite3_free(pReader->zTerm); |
+ } |
if( !fts3SegReaderIsRootOnly(pReader) ){ |
sqlite3_free(pReader->aNode); |
- sqlite3_blob_close(pReader->pBlob); |
} |
+ sqlite3_blob_close(pReader->pBlob); |
} |
sqlite3_free(pReader); |
} |
@@ -1625,7 +1637,10 @@ int sqlite3Fts3SegReaderNew( |
** an array of pending terms by term. This occurs as part of flushing |
** the contents of the pending-terms hash table to the database. |
*/ |
-static int fts3CompareElemByTerm(const void *lhs, const void *rhs){ |
+static int SQLITE_CDECL fts3CompareElemByTerm( |
+ const void *lhs, |
+ const void *rhs |
+){ |
char *z1 = fts3HashKey(*(Fts3HashElem **)lhs); |
char *z2 = fts3HashKey(*(Fts3HashElem **)rhs); |
int n1 = fts3HashKeysize(*(Fts3HashElem **)lhs); |
@@ -3082,8 +3097,8 @@ static int fts3PromoteSegments( |
if( bOk ){ |
int iIdx = 0; |
- sqlite3_stmt *pUpdate1; |
- sqlite3_stmt *pUpdate2; |
+ sqlite3_stmt *pUpdate1 = 0; |
+ sqlite3_stmt *pUpdate2 = 0; |
if( rc==SQLITE_OK ){ |
rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL_IDX, &pUpdate1, 0); |
@@ -3441,7 +3456,8 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){ |
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); |
if( rc==SQLITE_OK ){ |
int rc2; |
- sqlite3_bind_int(pAllLangid, 1, p->nIndex); |
+ sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid); |
+ sqlite3_bind_int(pAllLangid, 2, p->nIndex); |
while( sqlite3_step(pAllLangid)==SQLITE_ROW ){ |
int i; |
int iLangid = sqlite3_column_int(pAllLangid, 0); |
@@ -3508,7 +3524,7 @@ static int fts3DoRebuild(Fts3Table *p){ |
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ |
int iCol; |
int iLangid = langidFromSelect(p, pStmt); |
- rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0)); |
+ rc = fts3PendingTermsDocid(p, 0, iLangid, sqlite3_column_int64(pStmt, 0)); |
memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1)); |
for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){ |
if( p->abNotindexed[iCol]==0 ){ |
@@ -4773,7 +4789,7 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){ |
pHint->n = i; |
i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel); |
i += fts3GetVarint32(&pHint->a[i], pnInput); |
- if( i!=nHint ) return SQLITE_CORRUPT_VTAB; |
+ if( i!=nHint ) return FTS_CORRUPT_VTAB; |
return SQLITE_OK; |
} |
@@ -5141,7 +5157,8 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){ |
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); |
if( rc==SQLITE_OK ){ |
int rc2; |
- sqlite3_bind_int(pAllLangid, 1, p->nIndex); |
+ sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid); |
+ sqlite3_bind_int(pAllLangid, 2, p->nIndex); |
while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){ |
int iLangid = sqlite3_column_int(pAllLangid, 0); |
int i; |
@@ -5154,7 +5171,6 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){ |
} |
/* This block calculates the checksum according to the %_content table */ |
- rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); |
if( rc==SQLITE_OK ){ |
sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule; |
sqlite3_stmt *pStmt = 0; |
@@ -5251,7 +5267,7 @@ static int fts3DoIntegrityCheck( |
int rc; |
int bOk = 0; |
rc = fts3IntegrityCheck(p, &bOk); |
- if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_CORRUPT_VTAB; |
+ if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB; |
return rc; |
} |
@@ -5613,7 +5629,7 @@ int sqlite3Fts3UpdateMethod( |
} |
} |
if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ |
- rc = fts3PendingTermsDocid(p, iLangid, *pRowid); |
+ rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid); |
} |
if( rc==SQLITE_OK ){ |
assert( p->iPrevDocid==*pRowid ); |