Index: third_party/sqlite/src/ext/fts3/fts3.c |
diff --git a/third_party/sqlite/src/ext/fts3/fts3.c b/third_party/sqlite/src/ext/fts3/fts3.c |
index a8d16a9a2163a105c3d693b00223447e0e8105cb..2a24b78f37835c3a6079443598ec3ea2c246b2d3 100644 |
--- a/third_party/sqlite/src/ext/fts3/fts3.c |
+++ b/third_party/sqlite/src/ext/fts3/fts3.c |
@@ -493,6 +493,7 @@ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){ |
assert( p->pSegments==0 ); |
/* Free any prepared statements held */ |
+ sqlite3_finalize(p->pSeekStmt); |
for(i=0; i<SizeofArray(p->aStmt); i++){ |
sqlite3_finalize(p->aStmt[i]); |
} |
@@ -1364,9 +1365,9 @@ static int fts3InitVtab( |
p->pTokenizer = pTokenizer; |
p->nMaxPendingData = FTS3_MAX_PENDING_DATA; |
p->bHasDocsize = (isFts4 && bNoDocsize==0); |
- p->bHasStat = isFts4; |
- p->bFts4 = isFts4; |
- p->bDescIdx = bDescIdx; |
+ p->bHasStat = (u8)isFts4; |
+ p->bFts4 = (u8)isFts4; |
+ p->bDescIdx = (u8)bDescIdx; |
p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */ |
p->zContentTbl = zContent; |
p->zLanguageid = zLanguageid; |
@@ -1682,13 +1683,33 @@ static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ |
} |
/* |
+** Finalize the statement handle at pCsr->pStmt. |
+** |
+** Or, if that statement handle is one created by fts3CursorSeekStmt(), |
+** and the Fts3Table.pSeekStmt slot is currently NULL, save the statement |
+** pointer there instead of finalizing it. |
+*/ |
+static void fts3CursorFinalizeStmt(Fts3Cursor *pCsr){ |
+ if( pCsr->bSeekStmt ){ |
+ Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; |
+ if( p->pSeekStmt==0 ){ |
+ p->pSeekStmt = pCsr->pStmt; |
+ sqlite3_reset(pCsr->pStmt); |
+ pCsr->pStmt = 0; |
+ } |
+ pCsr->bSeekStmt = 0; |
+ } |
+ sqlite3_finalize(pCsr->pStmt); |
+} |
+ |
+/* |
** Close the cursor. For additional information see the documentation |
** on the xClose method of the virtual table interface. |
*/ |
static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){ |
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; |
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); |
- sqlite3_finalize(pCsr->pStmt); |
+ fts3CursorFinalizeStmt(pCsr); |
sqlite3Fts3ExprFree(pCsr->pExpr); |
sqlite3Fts3FreeDeferredTokens(pCsr); |
sqlite3_free(pCsr->aDoclist); |
@@ -1706,20 +1727,23 @@ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){ |
** |
** (or the equivalent for a content=xxx table) and set pCsr->pStmt to |
** it. If an error occurs, return an SQLite error code. |
-** |
-** Otherwise, set *ppStmt to point to pCsr->pStmt and return SQLITE_OK. |
*/ |
-static int fts3CursorSeekStmt(Fts3Cursor *pCsr, sqlite3_stmt **ppStmt){ |
+static int fts3CursorSeekStmt(Fts3Cursor *pCsr){ |
int rc = SQLITE_OK; |
if( pCsr->pStmt==0 ){ |
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; |
char *zSql; |
- zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist); |
- if( !zSql ) return SQLITE_NOMEM; |
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); |
- sqlite3_free(zSql); |
+ if( p->pSeekStmt ){ |
+ pCsr->pStmt = p->pSeekStmt; |
+ p->pSeekStmt = 0; |
+ }else{ |
+ zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist); |
+ if( !zSql ) return SQLITE_NOMEM; |
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); |
+ sqlite3_free(zSql); |
+ } |
+ if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1; |
} |
- *ppStmt = pCsr->pStmt; |
return rc; |
} |
@@ -1731,9 +1755,7 @@ static int fts3CursorSeekStmt(Fts3Cursor *pCsr, sqlite3_stmt **ppStmt){ |
static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){ |
int rc = SQLITE_OK; |
if( pCsr->isRequireSeek ){ |
- sqlite3_stmt *pStmt = 0; |
- |
- rc = fts3CursorSeekStmt(pCsr, &pStmt); |
+ rc = fts3CursorSeekStmt(pCsr); |
if( rc==SQLITE_OK ){ |
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId); |
pCsr->isRequireSeek = 0; |
@@ -1829,7 +1851,7 @@ static int fts3ScanInteriorNode( |
*/ |
if( nPrefix<0 || nSuffix<0 /* || nPrefix>nBuffer */ |
|| &zCsr[nSuffix]<zCsr || &zCsr[nSuffix]>zEnd ){ |
- rc = SQLITE_CORRUPT; |
+ rc = FTS_CORRUPT_VTAB; |
goto finish_scan; |
} |
if( nPrefix+nSuffix>nAlloc ){ |
@@ -3197,7 +3219,7 @@ static int fts3FilterMethod( |
assert( iIdx==nVal ); |
/* In case the cursor has been used before, clear it now. */ |
- sqlite3_finalize(pCsr->pStmt); |
+ fts3CursorFinalizeStmt(pCsr); |
sqlite3_free(pCsr->aDoclist); |
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); |
sqlite3Fts3ExprFree(pCsr->pExpr); |
@@ -3265,7 +3287,7 @@ static int fts3FilterMethod( |
rc = SQLITE_NOMEM; |
} |
}else if( eSearch==FTS3_DOCID_SEARCH ){ |
- rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt); |
+ rc = fts3CursorSeekStmt(pCsr); |
if( rc==SQLITE_OK ){ |
rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons); |
} |
@@ -3429,7 +3451,7 @@ static int fts3SetHasStat(Fts3Table *p){ |
if( rc==SQLITE_OK ){ |
int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW); |
rc = sqlite3_finalize(pStmt); |
- if( rc==SQLITE_OK ) p->bHasStat = bHasStat; |
+ if( rc==SQLITE_OK ) p->bHasStat = (u8)bHasStat; |
} |
sqlite3_free(zSql); |
}else{ |