| Index: third_party/sqlite/sqlite-src-3100200/ext/fts3/fts3_write.c
|
| diff --git a/third_party/sqlite/sqlite-src-3080704/ext/fts3/fts3_write.c b/third_party/sqlite/sqlite-src-3100200/ext/fts3/fts3_write.c
|
| similarity index 99%
|
| copy from third_party/sqlite/sqlite-src-3080704/ext/fts3/fts3_write.c
|
| copy to third_party/sqlite/sqlite-src-3100200/ext/fts3/fts3_write.c
|
| index 0da08c62d8bd05f7650b428d254d66369244193b..d5a408222ec790eb3ed7c9a32c33182fd954039e 100644
|
| --- a/third_party/sqlite/sqlite-src-3080704/ext/fts3/fts3_write.c
|
| +++ b/third_party/sqlite/sqlite-src-3100200/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 );
|
|
|