| Index: third_party/sqlite/src/ext/fts5/fts5_storage.c
|
| diff --git a/third_party/sqlite/src/ext/fts5/fts5_storage.c b/third_party/sqlite/src/ext/fts5/fts5_storage.c
|
| index 13297c15091413658c326af9c5382bd0c9b9cfff..a6958874582e0c63e2db03a81f5658e65f7526bf 100644
|
| --- a/third_party/sqlite/src/ext/fts5/fts5_storage.c
|
| +++ b/third_party/sqlite/src/ext/fts5/fts5_storage.c
|
| @@ -145,6 +145,7 @@ static int fts5StorageGetStmt(
|
| }
|
|
|
| *ppStmt = p->aStmt[eStmt];
|
| + sqlite3_reset(*ppStmt);
|
| return rc;
|
| }
|
|
|
| @@ -246,7 +247,11 @@ int sqlite3Fts5CreateTable(
|
| char *zErr = 0;
|
|
|
| rc = fts5ExecPrintf(pConfig->db, &zErr, "CREATE TABLE %Q.'%q_%q'(%s)%s",
|
| - pConfig->zDb, pConfig->zName, zPost, zDefn, bWithout?" WITHOUT ROWID":""
|
| + pConfig->zDb, pConfig->zName, zPost, zDefn,
|
| +#ifndef SQLITE_FTS5_NO_WITHOUT_ROWID
|
| + bWithout?" WITHOUT ROWID":
|
| +#endif
|
| + ""
|
| );
|
| if( zErr ){
|
| *pzErr = sqlite3_mprintf(
|
| @@ -338,7 +343,7 @@ int sqlite3Fts5StorageClose(Fts5Storage *p){
|
| int i;
|
|
|
| /* Finalize all SQL statements */
|
| - for(i=0; i<(int)ArraySize(p->aStmt); i++){
|
| + for(i=0; i<ArraySize(p->aStmt); i++){
|
| sqlite3_finalize(p->aStmt[i]);
|
| }
|
|
|
| @@ -362,11 +367,13 @@ static int fts5StorageInsertCallback(
|
| int tflags,
|
| const char *pToken, /* Buffer containing token */
|
| int nToken, /* Size of token in bytes */
|
| - int iStart, /* Start offset of token */
|
| - int iEnd /* End offset of token */
|
| + int iUnused1, /* Start offset of token */
|
| + int iUnused2 /* End offset of token */
|
| ){
|
| Fts5InsertCtx *pCtx = (Fts5InsertCtx*)pContext;
|
| Fts5Index *pIdx = pCtx->pStorage->pIndex;
|
| + UNUSED_PARAM2(iUnused1, iUnused2);
|
| + if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE;
|
| if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){
|
| pCtx->szCol++;
|
| }
|
| @@ -378,39 +385,52 @@ static int fts5StorageInsertCallback(
|
| ** delete-markers to the FTS index necessary to delete it. Do not actually
|
| ** remove the %_content row at this time though.
|
| */
|
| -static int fts5StorageDeleteFromIndex(Fts5Storage *p, i64 iDel){
|
| +static int fts5StorageDeleteFromIndex(
|
| + Fts5Storage *p,
|
| + i64 iDel,
|
| + sqlite3_value **apVal
|
| +){
|
| Fts5Config *pConfig = p->pConfig;
|
| - sqlite3_stmt *pSeek; /* SELECT to read row iDel from %_data */
|
| + sqlite3_stmt *pSeek = 0; /* SELECT to read row iDel from %_data */
|
| int rc; /* Return code */
|
| + int rc2; /* sqlite3_reset() return code */
|
| + int iCol;
|
| + Fts5InsertCtx ctx;
|
|
|
| - rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP, &pSeek, 0);
|
| - if( rc==SQLITE_OK ){
|
| - int rc2;
|
| + if( apVal==0 ){
|
| + rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP, &pSeek, 0);
|
| + if( rc!=SQLITE_OK ) return rc;
|
| sqlite3_bind_int64(pSeek, 1, iDel);
|
| - if( sqlite3_step(pSeek)==SQLITE_ROW ){
|
| - int iCol;
|
| - Fts5InsertCtx ctx;
|
| - ctx.pStorage = p;
|
| - ctx.iCol = -1;
|
| - rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel);
|
| - for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){
|
| - if( pConfig->abUnindexed[iCol-1] ) continue;
|
| - ctx.szCol = 0;
|
| - rc = sqlite3Fts5Tokenize(pConfig,
|
| - FTS5_TOKENIZE_DOCUMENT,
|
| - (const char*)sqlite3_column_text(pSeek, iCol),
|
| - sqlite3_column_bytes(pSeek, iCol),
|
| - (void*)&ctx,
|
| - fts5StorageInsertCallback
|
| - );
|
| - p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
|
| + if( sqlite3_step(pSeek)!=SQLITE_ROW ){
|
| + return sqlite3_reset(pSeek);
|
| + }
|
| + }
|
| +
|
| + ctx.pStorage = p;
|
| + ctx.iCol = -1;
|
| + rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel);
|
| + for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){
|
| + if( pConfig->abUnindexed[iCol-1]==0 ){
|
| + const char *zText;
|
| + int nText;
|
| + if( pSeek ){
|
| + zText = (const char*)sqlite3_column_text(pSeek, iCol);
|
| + nText = sqlite3_column_bytes(pSeek, iCol);
|
| + }else{
|
| + zText = (const char*)sqlite3_value_text(apVal[iCol-1]);
|
| + nText = sqlite3_value_bytes(apVal[iCol-1]);
|
| }
|
| - p->nTotalRow--;
|
| + ctx.szCol = 0;
|
| + rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT,
|
| + zText, nText, (void*)&ctx, fts5StorageInsertCallback
|
| + );
|
| + p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
|
| }
|
| - rc2 = sqlite3_reset(pSeek);
|
| - if( rc==SQLITE_OK ) rc = rc2;
|
| }
|
| + p->nTotalRow--;
|
|
|
| + rc2 = sqlite3_reset(pSeek);
|
| + if( rc==SQLITE_OK ) rc = rc2;
|
| return rc;
|
| }
|
|
|
| @@ -490,16 +510,17 @@ static int fts5StorageSaveTotals(Fts5Storage *p){
|
| /*
|
| ** Remove a row from the FTS table.
|
| */
|
| -int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel){
|
| +int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **apVal){
|
| Fts5Config *pConfig = p->pConfig;
|
| int rc;
|
| sqlite3_stmt *pDel = 0;
|
|
|
| + assert( pConfig->eContent!=FTS5_CONTENT_NORMAL || apVal==0 );
|
| rc = fts5StorageLoadTotals(p, 1);
|
|
|
| /* Delete the index records */
|
| if( rc==SQLITE_OK ){
|
| - rc = fts5StorageDeleteFromIndex(p, iDel);
|
| + rc = fts5StorageDeleteFromIndex(p, iDel, apVal);
|
| }
|
|
|
| /* Delete the %_docsize record */
|
| @@ -532,61 +553,6 @@ int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel){
|
| return rc;
|
| }
|
|
|
| -int sqlite3Fts5StorageSpecialDelete(
|
| - Fts5Storage *p,
|
| - i64 iDel,
|
| - sqlite3_value **apVal
|
| -){
|
| - Fts5Config *pConfig = p->pConfig;
|
| - int rc;
|
| - sqlite3_stmt *pDel = 0;
|
| -
|
| - assert( pConfig->eContent!=FTS5_CONTENT_NORMAL );
|
| - rc = fts5StorageLoadTotals(p, 1);
|
| -
|
| - /* Delete the index records */
|
| - if( rc==SQLITE_OK ){
|
| - int iCol;
|
| - Fts5InsertCtx ctx;
|
| - ctx.pStorage = p;
|
| - ctx.iCol = -1;
|
| -
|
| - rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel);
|
| - for(iCol=0; rc==SQLITE_OK && iCol<pConfig->nCol; iCol++){
|
| - if( pConfig->abUnindexed[iCol] ) continue;
|
| - ctx.szCol = 0;
|
| - rc = sqlite3Fts5Tokenize(pConfig,
|
| - FTS5_TOKENIZE_DOCUMENT,
|
| - (const char*)sqlite3_value_text(apVal[iCol]),
|
| - sqlite3_value_bytes(apVal[iCol]),
|
| - (void*)&ctx,
|
| - fts5StorageInsertCallback
|
| - );
|
| - p->aTotalSize[iCol] -= (i64)ctx.szCol;
|
| - }
|
| - p->nTotalRow--;
|
| - }
|
| -
|
| - /* Delete the %_docsize record */
|
| - if( pConfig->bColumnsize ){
|
| - if( rc==SQLITE_OK ){
|
| - rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_DOCSIZE, &pDel, 0);
|
| - }
|
| - if( rc==SQLITE_OK ){
|
| - sqlite3_bind_int64(pDel, 1, iDel);
|
| - sqlite3_step(pDel);
|
| - rc = sqlite3_reset(pDel);
|
| - }
|
| - }
|
| -
|
| - /* Write the averages record */
|
| - if( rc==SQLITE_OK ){
|
| - rc = fts5StorageSaveTotals(p);
|
| - }
|
| -
|
| - return rc;
|
| -}
|
| -
|
| /*
|
| ** Delete all entries in the FTS5 index.
|
| */
|
| @@ -679,6 +645,10 @@ int sqlite3Fts5StorageMerge(Fts5Storage *p, int nMerge){
|
| return sqlite3Fts5IndexMerge(p->pIndex, nMerge);
|
| }
|
|
|
| +int sqlite3Fts5StorageReset(Fts5Storage *p){
|
| + return sqlite3Fts5IndexReset(p->pIndex);
|
| +}
|
| +
|
| /*
|
| ** Allocate a new rowid. This is used for "external content" tables when
|
| ** a NULL value is inserted into the rowid column. The new rowid is allocated
|
| @@ -825,28 +795,76 @@ struct Fts5IntegrityCtx {
|
| int iCol;
|
| int szCol;
|
| u64 cksum;
|
| + Fts5Termset *pTermset;
|
| Fts5Config *pConfig;
|
| };
|
|
|
| +
|
| /*
|
| ** Tokenization callback used by integrity check.
|
| */
|
| static int fts5StorageIntegrityCallback(
|
| - void *pContext, /* Pointer to Fts5InsertCtx object */
|
| + void *pContext, /* Pointer to Fts5IntegrityCtx object */
|
| int tflags,
|
| const char *pToken, /* Buffer containing token */
|
| int nToken, /* Size of token in bytes */
|
| - int iStart, /* Start offset of token */
|
| - int iEnd /* End offset of token */
|
| + int iUnused1, /* Start offset of token */
|
| + int iUnused2 /* End offset of token */
|
| ){
|
| Fts5IntegrityCtx *pCtx = (Fts5IntegrityCtx*)pContext;
|
| + Fts5Termset *pTermset = pCtx->pTermset;
|
| + int bPresent;
|
| + int ii;
|
| + int rc = SQLITE_OK;
|
| + int iPos;
|
| + int iCol;
|
| +
|
| + UNUSED_PARAM2(iUnused1, iUnused2);
|
| + if( nToken>FTS5_MAX_TOKEN_SIZE ) nToken = FTS5_MAX_TOKEN_SIZE;
|
| +
|
| if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){
|
| pCtx->szCol++;
|
| }
|
| - pCtx->cksum ^= sqlite3Fts5IndexCksum(
|
| - pCtx->pConfig, pCtx->iRowid, pCtx->iCol, pCtx->szCol-1, pToken, nToken
|
| - );
|
| - return SQLITE_OK;
|
| +
|
| + switch( pCtx->pConfig->eDetail ){
|
| + case FTS5_DETAIL_FULL:
|
| + iPos = pCtx->szCol-1;
|
| + iCol = pCtx->iCol;
|
| + break;
|
| +
|
| + case FTS5_DETAIL_COLUMNS:
|
| + iPos = pCtx->iCol;
|
| + iCol = 0;
|
| + break;
|
| +
|
| + default:
|
| + assert( pCtx->pConfig->eDetail==FTS5_DETAIL_NONE );
|
| + iPos = 0;
|
| + iCol = 0;
|
| + break;
|
| + }
|
| +
|
| + rc = sqlite3Fts5TermsetAdd(pTermset, 0, pToken, nToken, &bPresent);
|
| + if( rc==SQLITE_OK && bPresent==0 ){
|
| + pCtx->cksum ^= sqlite3Fts5IndexEntryCksum(
|
| + pCtx->iRowid, iCol, iPos, 0, pToken, nToken
|
| + );
|
| + }
|
| +
|
| + for(ii=0; rc==SQLITE_OK && ii<pCtx->pConfig->nPrefix; ii++){
|
| + const int nChar = pCtx->pConfig->aPrefix[ii];
|
| + int nByte = sqlite3Fts5IndexCharlenToBytelen(pToken, nToken, nChar);
|
| + if( nByte ){
|
| + rc = sqlite3Fts5TermsetAdd(pTermset, ii+1, pToken, nByte, &bPresent);
|
| + if( bPresent==0 ){
|
| + pCtx->cksum ^= sqlite3Fts5IndexEntryCksum(
|
| + pCtx->iRowid, iCol, iPos, ii+1, pToken, nByte
|
| + );
|
| + }
|
| + }
|
| + }
|
| +
|
| + return rc;
|
| }
|
|
|
| /*
|
| @@ -882,22 +900,37 @@ int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
|
| if( pConfig->bColumnsize ){
|
| rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize);
|
| }
|
| + if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){
|
| + rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
|
| + }
|
| for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
|
| if( pConfig->abUnindexed[i] ) continue;
|
| ctx.iCol = i;
|
| ctx.szCol = 0;
|
| - rc = sqlite3Fts5Tokenize(pConfig,
|
| - FTS5_TOKENIZE_DOCUMENT,
|
| - (const char*)sqlite3_column_text(pScan, i+1),
|
| - sqlite3_column_bytes(pScan, i+1),
|
| - (void*)&ctx,
|
| - fts5StorageIntegrityCallback
|
| - );
|
| - if( pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
|
| + if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
|
| + rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
|
| + }
|
| + if( rc==SQLITE_OK ){
|
| + rc = sqlite3Fts5Tokenize(pConfig,
|
| + FTS5_TOKENIZE_DOCUMENT,
|
| + (const char*)sqlite3_column_text(pScan, i+1),
|
| + sqlite3_column_bytes(pScan, i+1),
|
| + (void*)&ctx,
|
| + fts5StorageIntegrityCallback
|
| + );
|
| + }
|
| + if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
|
| rc = FTS5_CORRUPT;
|
| }
|
| aTotalSize[i] += ctx.szCol;
|
| + if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
|
| + sqlite3Fts5TermsetFree(ctx.pTermset);
|
| + ctx.pTermset = 0;
|
| + }
|
| }
|
| + sqlite3Fts5TermsetFree(ctx.pTermset);
|
| + ctx.pTermset = 0;
|
| +
|
| if( rc!=SQLITE_OK ) break;
|
| }
|
| rc2 = sqlite3_reset(pScan);
|
| @@ -1099,5 +1132,3 @@ int sqlite3Fts5StorageConfigValue(
|
| }
|
| return rc;
|
| }
|
| -
|
| -
|
|
|