mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Merge the latest trunk changes into the reuse-schema branch.
FossilOrigin-Name: 3d1b0403d657cf147cda58eee0f05f5e2837a10f1741375db77e11cc53c4a476
This commit is contained in:
@@ -88,8 +88,11 @@ struct Fts5PhraseIter {
|
||||
** created with the "columnsize=0" option.
|
||||
**
|
||||
** xColumnText:
|
||||
** This function attempts to retrieve the text of column iCol of the
|
||||
** current document. If successful, (*pz) is set to point to a buffer
|
||||
** If parameter iCol is less than zero, or greater than or equal to the
|
||||
** number of columns in the table, SQLITE_RANGE is returned.
|
||||
**
|
||||
** Otherwise, this function attempts to retrieve the text of column iCol of
|
||||
** the current document. If successful, (*pz) is set to point to a buffer
|
||||
** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
|
||||
** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
|
||||
** if an error occurs, an SQLite error code is returned and the final values
|
||||
@@ -99,8 +102,10 @@ struct Fts5PhraseIter {
|
||||
** Returns the number of phrases in the current query expression.
|
||||
**
|
||||
** xPhraseSize:
|
||||
** Returns the number of tokens in phrase iPhrase of the query. Phrases
|
||||
** are numbered starting from zero.
|
||||
** If parameter iCol is less than zero, or greater than or equal to the
|
||||
** number of phrases in the current query, as returned by xPhraseCount,
|
||||
** 0 is returned. Otherwise, this function returns the number of tokens in
|
||||
** phrase iPhrase of the query. Phrases are numbered starting from zero.
|
||||
**
|
||||
** xInstCount:
|
||||
** Set *pnInst to the total number of occurrences of all phrases within
|
||||
@@ -116,12 +121,13 @@ struct Fts5PhraseIter {
|
||||
** Query for the details of phrase match iIdx within the current row.
|
||||
** Phrase matches are numbered starting from zero, so the iIdx argument
|
||||
** should be greater than or equal to zero and smaller than the value
|
||||
** output by xInstCount().
|
||||
** output by xInstCount(). If iIdx is less than zero or greater than
|
||||
** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned.
|
||||
**
|
||||
** Usually, output parameter *piPhrase is set to the phrase number, *piCol
|
||||
** Otherwise, output parameter *piPhrase is set to the phrase number, *piCol
|
||||
** to the column in which it occurs and *piOff the token offset of the
|
||||
** first token of the phrase. Returns SQLITE_OK if successful, or an error
|
||||
** code (i.e. SQLITE_NOMEM) if an error occurs.
|
||||
** first token of the phrase. SQLITE_OK is returned if successful, or an
|
||||
** error code (i.e. SQLITE_NOMEM) if an error occurs.
|
||||
**
|
||||
** This API can be quite slow if used with an FTS5 table created with the
|
||||
** "detail=none" or "detail=column" option.
|
||||
@@ -147,6 +153,10 @@ struct Fts5PhraseIter {
|
||||
** Invoking Api.xUserData() returns a copy of the pointer passed as
|
||||
** the third argument to pUserData.
|
||||
**
|
||||
** If parameter iPhrase is less than zero, or greater than or equal to
|
||||
** the number of phrases in the query, as returned by xPhraseCount(),
|
||||
** this function returns SQLITE_RANGE.
|
||||
**
|
||||
** If the callback function returns any value other than SQLITE_OK, the
|
||||
** query is abandoned and the xQueryPhrase function returns immediately.
|
||||
** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK.
|
||||
@@ -268,17 +278,25 @@ struct Fts5PhraseIter {
|
||||
** to a buffer containing the requested token, and *pnToken to the
|
||||
** size of this buffer in bytes.
|
||||
**
|
||||
** If iPhrase or iToken are less than zero, or if iPhrase is greater than
|
||||
** or equal to the number of phrases in the query as reported by
|
||||
** xPhraseCount(), or if iToken is equal to or greater than the number of
|
||||
** tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken
|
||||
are both zeroed.
|
||||
**
|
||||
** The output text is not a copy of the query text that specified the
|
||||
** token. It is the output of the tokenizer module. For tokendata=1
|
||||
** tables, this includes any embedded 0x00 and trailing data.
|
||||
**
|
||||
** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken)
|
||||
** This is used to access token iToken of phrase hit iIdx within the
|
||||
** current row. Output variable (*ppToken) is set to point to a buffer
|
||||
** containing the matching document token, and (*pnToken) to the size
|
||||
** of that buffer in bytes. This API is not available if the specified
|
||||
** token matches a prefix query term. In that case both output variables
|
||||
** are always set to 0.
|
||||
** current row. If iIdx is less than zero or greater than or equal to the
|
||||
** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
|
||||
** output variable (*ppToken) is set to point to a buffer containing the
|
||||
** matching document token, and (*pnToken) to the size of that buffer in
|
||||
** bytes. This API is not available if the specified token matches a
|
||||
** prefix query term. In that case both output variables are always set
|
||||
** to 0.
|
||||
**
|
||||
** The output text is not a copy of the document text that was tokenized.
|
||||
** It is the output of the tokenizer module. For tokendata=1 tables, this
|
||||
|
@@ -252,8 +252,10 @@ static void fts5HighlightFunction(
|
||||
ctx.zClose = (const char*)sqlite3_value_text(apVal[2]);
|
||||
ctx.iRangeEnd = -1;
|
||||
rc = pApi->xColumnText(pFts, iCol, &ctx.zIn, &ctx.nIn);
|
||||
|
||||
if( ctx.zIn ){
|
||||
if( rc==SQLITE_RANGE ){
|
||||
sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
|
||||
rc = SQLITE_OK;
|
||||
}else if( ctx.zIn ){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5CInstIterInit(pApi, pFts, iCol, &ctx.iter);
|
||||
}
|
||||
|
@@ -68,6 +68,7 @@ void sqlite3Fts5BufferAppendBlob(
|
||||
){
|
||||
if( nData ){
|
||||
if( fts5BufferGrow(pRc, pBuf, nData) ) return;
|
||||
assert( pBuf->p!=0 );
|
||||
memcpy(&pBuf->p[pBuf->n], pData, nData);
|
||||
pBuf->n += nData;
|
||||
}
|
||||
@@ -169,6 +170,7 @@ int sqlite3Fts5PoslistNext64(
|
||||
i64 *piOff /* IN/OUT: Current offset */
|
||||
){
|
||||
int i = *pi;
|
||||
assert( a!=0 || i==0 );
|
||||
if( i>=n ){
|
||||
/* EOF */
|
||||
*piOff = -1;
|
||||
@@ -176,6 +178,7 @@ int sqlite3Fts5PoslistNext64(
|
||||
}else{
|
||||
i64 iOff = *piOff;
|
||||
u32 iVal;
|
||||
assert( a!=0 );
|
||||
fts5FastGetVarint32(a, i, iVal);
|
||||
if( iVal<=1 ){
|
||||
if( iVal==0 ){
|
||||
|
@@ -1740,7 +1740,9 @@ static int fts5ParseTokenize(
|
||||
memset(pSyn, 0, (size_t)nByte);
|
||||
pSyn->pTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer);
|
||||
pSyn->nFullTerm = pSyn->nQueryTerm = nToken;
|
||||
if( pCtx->pConfig->bTokendata ) pSyn->nQueryTerm = strlen(pSyn->pTerm);
|
||||
if( pCtx->pConfig->bTokendata ){
|
||||
pSyn->nQueryTerm = (int)strlen(pSyn->pTerm);
|
||||
}
|
||||
memcpy(pSyn->pTerm, pToken, nToken);
|
||||
pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym;
|
||||
pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn;
|
||||
@@ -1769,7 +1771,7 @@ static int fts5ParseTokenize(
|
||||
pTerm->pTerm = sqlite3Fts5Strndup(&rc, pToken, nToken);
|
||||
pTerm->nFullTerm = pTerm->nQueryTerm = nToken;
|
||||
if( pCtx->pConfig->bTokendata && rc==SQLITE_OK ){
|
||||
pTerm->nQueryTerm = strlen(pTerm->pTerm);
|
||||
pTerm->nQueryTerm = (int)strlen(pTerm->pTerm);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1888,8 +1890,12 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */
|
||||
Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
|
||||
TokenCtx sCtx = {0,0,0}; /* Context object for fts5ParseTokenize */
|
||||
pOrig = pExpr->apExprPhrase[iPhrase];
|
||||
pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr));
|
||||
if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){
|
||||
rc = SQLITE_RANGE;
|
||||
}else{
|
||||
pOrig = pExpr->apExprPhrase[iPhrase];
|
||||
pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr));
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc,
|
||||
sizeof(Fts5ExprPhrase*));
|
||||
@@ -1916,25 +1922,27 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
}
|
||||
}
|
||||
|
||||
if( pOrig->nTerm ){
|
||||
int i; /* Used to iterate through phrase terms */
|
||||
sCtx.pConfig = pExpr->pConfig;
|
||||
for(i=0; rc==SQLITE_OK && i<pOrig->nTerm; i++){
|
||||
int tflags = 0;
|
||||
Fts5ExprTerm *p;
|
||||
for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){
|
||||
rc = fts5ParseTokenize((void*)&sCtx, tflags, p->pTerm,p->nFullTerm,0,0);
|
||||
tflags = FTS5_TOKEN_COLOCATED;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix;
|
||||
sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst;
|
||||
if( rc==SQLITE_OK ){
|
||||
if( pOrig->nTerm ){
|
||||
int i; /* Used to iterate through phrase terms */
|
||||
sCtx.pConfig = pExpr->pConfig;
|
||||
for(i=0; rc==SQLITE_OK && i<pOrig->nTerm; i++){
|
||||
int tflags = 0;
|
||||
Fts5ExprTerm *p;
|
||||
for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){
|
||||
rc = fts5ParseTokenize((void*)&sCtx,tflags,p->pTerm,p->nFullTerm,0,0);
|
||||
tflags = FTS5_TOKEN_COLOCATED;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix;
|
||||
sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
/* This happens when parsing a token or quoted phrase that contains
|
||||
** no token characters at all. (e.g ... MATCH '""'). */
|
||||
sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
|
||||
}
|
||||
}else{
|
||||
/* This happens when parsing a token or quoted phrase that contains
|
||||
** no token characters at all. (e.g ... MATCH '""'). */
|
||||
sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && ALWAYS(sCtx.pPhrase) ){
|
||||
@@ -3247,4 +3255,3 @@ void sqlite3Fts5ExprClearTokens(Fts5Expr *pExpr){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -360,6 +360,7 @@ struct Fts5Index {
|
||||
|
||||
/* Error state. */
|
||||
int rc; /* Current error code */
|
||||
int flushRc;
|
||||
|
||||
/* State used by the fts5DataXXX() functions. */
|
||||
sqlite3_blob *pReader; /* RO incr-blob open on %_data table */
|
||||
@@ -1546,9 +1547,9 @@ static int fts5DlidxLvlNext(Fts5DlidxLvl *pLvl){
|
||||
}
|
||||
|
||||
if( iOff<pData->nn ){
|
||||
i64 iVal;
|
||||
u64 iVal;
|
||||
pLvl->iLeafPgno += (iOff - pLvl->iOff) + 1;
|
||||
iOff += fts5GetVarint(&pData->p[iOff], (u64*)&iVal);
|
||||
iOff += fts5GetVarint(&pData->p[iOff], &iVal);
|
||||
pLvl->iRowid += iVal;
|
||||
pLvl->iOff = iOff;
|
||||
}else{
|
||||
@@ -4120,6 +4121,7 @@ static void fts5IndexDiscardData(Fts5Index *p){
|
||||
sqlite3Fts5HashClear(p->pHash);
|
||||
p->nPendingData = 0;
|
||||
p->nPendingRow = 0;
|
||||
p->flushRc = SQLITE_OK;
|
||||
}
|
||||
p->nContentlessDelete = 0;
|
||||
}
|
||||
@@ -5701,6 +5703,10 @@ static void fts5FlushOneHash(Fts5Index *p){
|
||||
*/
|
||||
static void fts5IndexFlush(Fts5Index *p){
|
||||
/* Unless it is empty, flush the hash table to disk */
|
||||
if( p->flushRc ){
|
||||
p->rc = p->flushRc;
|
||||
return;
|
||||
}
|
||||
if( p->nPendingData || p->nContentlessDelete ){
|
||||
assert( p->pHash );
|
||||
fts5FlushOneHash(p);
|
||||
@@ -5709,6 +5715,8 @@ static void fts5IndexFlush(Fts5Index *p){
|
||||
p->nPendingData = 0;
|
||||
p->nPendingRow = 0;
|
||||
p->nContentlessDelete = 0;
|
||||
}else if( p->nPendingData || p->nContentlessDelete ){
|
||||
p->flushRc = p->rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6879,7 +6887,7 @@ static Fts5Iter *fts5SetupTokendataIter(
|
||||
fts5IndexFlush(p);
|
||||
pStruct = fts5StructureRead(p);
|
||||
|
||||
while( 1 ){
|
||||
while( p->rc==SQLITE_OK ){
|
||||
Fts5Iter *pPrev = pSet ? pSet->apIter[pSet->nIter-1] : 0;
|
||||
Fts5Iter *pNew = 0;
|
||||
Fts5SegIter *pNewIter = 0;
|
||||
@@ -6888,14 +6896,16 @@ static Fts5Iter *fts5SetupTokendataIter(
|
||||
int iLvl, iSeg, ii;
|
||||
|
||||
pNew = fts5MultiIterAlloc(p, pStruct->nSegment);
|
||||
if( pNew==0 ) break;
|
||||
|
||||
if( pSmall ){
|
||||
fts5BufferSet(&p->rc, &bSeek, pSmall->n, pSmall->p);
|
||||
fts5BufferAppendBlob(&p->rc, &bSeek, 1, (const u8*)"\0");
|
||||
}else{
|
||||
fts5BufferSet(&p->rc, &bSeek, nToken, pToken);
|
||||
}
|
||||
if( p->rc ){
|
||||
sqlite3Fts5IterClose((Fts5IndexIter*)pNew);
|
||||
break;
|
||||
}
|
||||
|
||||
pNewIter = &pNew->aSeg[0];
|
||||
pPrevIter = (pPrev ? &pPrev->aSeg[0] : 0);
|
||||
@@ -6930,6 +6940,7 @@ static Fts5Iter *fts5SetupTokendataIter(
|
||||
|
||||
pNewIter++;
|
||||
if( pPrevIter ) pPrevIter++;
|
||||
if( p->rc ) break;
|
||||
}
|
||||
}
|
||||
fts5TokendataSetTermIfEof(pPrev, pSmall);
|
||||
@@ -7021,6 +7032,10 @@ int sqlite3Fts5IndexQuery(
|
||||
int bTokendata = pConfig->bTokendata;
|
||||
if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken);
|
||||
|
||||
if( flags & (FTS5INDEX_QUERY_NOTOKENDATA|FTS5INDEX_QUERY_SCAN) ){
|
||||
bTokendata = 0;
|
||||
}
|
||||
|
||||
/* Figure out which index to search and set iIdx accordingly. If this
|
||||
** is a prefix query for which there is no prefix index, set iIdx to
|
||||
** greater than pConfig->nPrefix to indicate that the query will be
|
||||
@@ -7032,7 +7047,6 @@ int sqlite3Fts5IndexQuery(
|
||||
** for internal sanity checking by the integrity-check in debug
|
||||
** mode only. */
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( flags & FTS5INDEX_QUERY_NOTOKENDATA ) bTokendata = 0;
|
||||
if( pConfig->bPrefixIndex==0 || (flags & FTS5INDEX_QUERY_TEST_NOIDX) ){
|
||||
assert( flags & FTS5INDEX_QUERY_PREFIX );
|
||||
iIdx = 1+pConfig->nPrefix;
|
||||
@@ -7211,7 +7225,7 @@ int sqlite3Fts5IterToken(
|
||||
*/
|
||||
void sqlite3Fts5IndexIterClearTokendata(Fts5IndexIter *pIndexIter){
|
||||
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
|
||||
if( pIter->pTokenDataIter ){
|
||||
if( pIter && pIter->pTokenDataIter ){
|
||||
pIter->pTokenDataIter->nMap = 0;
|
||||
}
|
||||
}
|
||||
@@ -7930,7 +7944,7 @@ static void fts5IndexIntegrityCheckEmpty(
|
||||
}
|
||||
|
||||
static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){
|
||||
int iTermOff = 0;
|
||||
i64 iTermOff = 0;
|
||||
int ii;
|
||||
|
||||
Fts5Buffer buf1 = {0,0,0};
|
||||
@@ -7939,7 +7953,7 @@ static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){
|
||||
ii = pLeaf->szLeaf;
|
||||
while( ii<pLeaf->nn && p->rc==SQLITE_OK ){
|
||||
int res;
|
||||
int iOff;
|
||||
i64 iOff;
|
||||
int nIncr;
|
||||
|
||||
ii += fts5GetVarint32(&pLeaf->p[ii], nIncr);
|
||||
|
@@ -118,7 +118,7 @@ struct Fts5FullTable {
|
||||
Fts5Global *pGlobal; /* Global (connection wide) data */
|
||||
Fts5Cursor *pSortCsr; /* Sort data from this cursor */
|
||||
int iSavepoint; /* Successful xSavepoint()+1 */
|
||||
int bInSavepoint;
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
struct Fts5TransactionState ts;
|
||||
#endif
|
||||
@@ -1911,7 +1911,10 @@ static int fts5ApiColumnText(
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
|
||||
if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab))
|
||||
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
|
||||
if( iCol<0 || iCol>=pTab->pConfig->nCol ){
|
||||
rc = SQLITE_RANGE;
|
||||
}else if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab))
|
||||
|| pCsr->ePlan==FTS5_PLAN_SPECIAL
|
||||
){
|
||||
*pz = 0;
|
||||
@@ -1936,8 +1939,9 @@ static int fts5CsrPoslist(
|
||||
int rc = SQLITE_OK;
|
||||
int bLive = (pCsr->pSorter==0);
|
||||
|
||||
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){
|
||||
|
||||
if( iPhrase<0 || iPhrase>=sqlite3Fts5ExprPhraseCount(pCsr->pExpr) ){
|
||||
rc = SQLITE_RANGE;
|
||||
}else if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){
|
||||
if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
|
||||
Fts5PoslistPopulator *aPopulator;
|
||||
int i;
|
||||
@@ -1961,15 +1965,21 @@ static int fts5CsrPoslist(
|
||||
CsrFlagClear(pCsr, FTS5CSR_REQUIRE_POSLIST);
|
||||
}
|
||||
|
||||
if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){
|
||||
Fts5Sorter *pSorter = pCsr->pSorter;
|
||||
int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
|
||||
*pn = pSorter->aIdx[iPhrase] - i1;
|
||||
*pa = &pSorter->aPoslist[i1];
|
||||
if( rc==SQLITE_OK ){
|
||||
if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){
|
||||
Fts5Sorter *pSorter = pCsr->pSorter;
|
||||
int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
|
||||
*pn = pSorter->aIdx[iPhrase] - i1;
|
||||
*pa = &pSorter->aPoslist[i1];
|
||||
}else{
|
||||
*pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa);
|
||||
}
|
||||
}else{
|
||||
*pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa);
|
||||
*pa = 0;
|
||||
*pn = 0;
|
||||
}
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2667,9 +2677,7 @@ static int fts5RenameMethod(
|
||||
){
|
||||
int rc;
|
||||
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
|
||||
pTab->bInSavepoint = 1;
|
||||
rc = sqlite3Fts5StorageRename(pTab->pStorage, zName);
|
||||
pTab->bInSavepoint = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2686,26 +2694,12 @@ int sqlite3Fts5FlushToDisk(Fts5Table *pTab){
|
||||
static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
|
||||
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
|
||||
int rc = SQLITE_OK;
|
||||
char *zSql = 0;
|
||||
|
||||
fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
|
||||
|
||||
if( pTab->bInSavepoint==0 ){
|
||||
zSql = sqlite3_mprintf("INSERT INTO %Q.%Q(%Q) VALUES('flush')",
|
||||
pTab->p.pConfig->zDb, pTab->p.pConfig->zName, pTab->p.pConfig->zName
|
||||
);
|
||||
if( zSql ){
|
||||
pTab->bInSavepoint = 1;
|
||||
rc = sqlite3_exec(pTab->p.pConfig->db, zSql, 0, 0, 0);
|
||||
pTab->bInSavepoint = 0;
|
||||
sqlite3_free(zSql);
|
||||
}else{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
pTab->iSavepoint = iSavepoint+1;
|
||||
}
|
||||
rc = sqlite3Fts5FlushToDisk((Fts5Table*)pVtab);
|
||||
if( rc==SQLITE_OK ){
|
||||
pTab->iSavepoint = iSavepoint+1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2966,7 +2960,7 @@ static int fts5ShadowName(const char *zName){
|
||||
** if anything is found amiss. Return a NULL pointer if everything is
|
||||
** OK.
|
||||
*/
|
||||
static int fts5Integrity(
|
||||
static int fts5IntegrityMethod(
|
||||
sqlite3_vtab *pVtab, /* the FTS5 virtual table to check */
|
||||
const char *zSchema, /* Name of schema in which this table lives */
|
||||
const char *zTabname, /* Name of the table itself */
|
||||
@@ -3024,7 +3018,7 @@ static int fts5Init(sqlite3 *db){
|
||||
/* xRelease */ fts5ReleaseMethod,
|
||||
/* xRollbackTo */ fts5RollbackToMethod,
|
||||
/* xShadowName */ fts5ShadowName,
|
||||
/* xIntegrity */ fts5Integrity
|
||||
/* xIntegrity */ fts5IntegrityMethod
|
||||
};
|
||||
|
||||
int rc;
|
||||
|
@@ -673,7 +673,7 @@ int sqlite3Fts5StorageRebuild(Fts5Storage *p){
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0);
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, pConfig->pzErrmsg);
|
||||
}
|
||||
|
||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pScan) ){
|
||||
|
@@ -629,7 +629,7 @@ static int fts5VocabFilterMethod(
|
||||
if( pEq ){
|
||||
zTerm = (const char *)sqlite3_value_text(pEq);
|
||||
nTerm = sqlite3_value_bytes(pEq);
|
||||
f = 0;
|
||||
f = FTS5INDEX_QUERY_NOTOKENDATA;
|
||||
}else{
|
||||
if( pGe ){
|
||||
zTerm = (const char *)sqlite3_value_text(pGe);
|
||||
|
@@ -61,6 +61,12 @@ proc fts5_test_collist {cmd} {
|
||||
set res
|
||||
}
|
||||
|
||||
proc fts5_collist {cmd iPhrase} {
|
||||
set res [list]
|
||||
$cmd xPhraseColumnForeach $iPhrase c { lappend res $c }
|
||||
set res
|
||||
}
|
||||
|
||||
proc fts5_test_columnsize {cmd} {
|
||||
set res [list]
|
||||
for {set i 0} {$i < [$cmd xColumnCount]} {incr i} {
|
||||
@@ -69,6 +75,10 @@ proc fts5_test_columnsize {cmd} {
|
||||
set res
|
||||
}
|
||||
|
||||
proc fts5_columntext {cmd iCol} {
|
||||
$cmd xColumnText $iCol
|
||||
}
|
||||
|
||||
proc fts5_test_columntext {cmd} {
|
||||
set res [list]
|
||||
for {set i 0} {$i < [$cmd xColumnCount]} {incr i} {
|
||||
@@ -125,6 +135,13 @@ proc fts5_test_queryphrase {cmd} {
|
||||
set res
|
||||
}
|
||||
|
||||
proc fts5_queryphrase {cmd iPhrase} {
|
||||
set cnt [list]
|
||||
for {set j 0} {$j < [$cmd xColumnCount]} {incr j} { lappend cnt 0 }
|
||||
$cmd xQueryPhrase $iPhrase [list test_queryphrase_cb cnt]
|
||||
set cnt
|
||||
}
|
||||
|
||||
proc fts5_test_phrasecount {cmd} {
|
||||
$cmd xPhraseCount
|
||||
}
|
||||
@@ -154,6 +171,9 @@ proc fts5_aux_test_functions {db} {
|
||||
|
||||
fts5_test_queryphrase
|
||||
fts5_test_phrasecount
|
||||
fts5_columntext
|
||||
fts5_queryphrase
|
||||
fts5_collist
|
||||
} {
|
||||
sqlite3_fts5_create_function $db $f $f
|
||||
}
|
||||
|
@@ -334,4 +334,47 @@ do_execsql_test 11.2 {
|
||||
SELECT fts5_hitcount(x1) FROM x1('one') LIMIT 1;
|
||||
} {5}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that xColumnText returns SQLITE_RANGE when it should.
|
||||
#
|
||||
reset_db
|
||||
fts5_aux_test_functions db
|
||||
do_execsql_test 12.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, b, c);
|
||||
INSERT INTO t1 VALUES('one', 'two', 'three');
|
||||
INSERT INTO t1 VALUES('one', 'one', 'one');
|
||||
INSERT INTO t1 VALUES('two', 'two', 'two');
|
||||
INSERT INTO t1 VALUES('three', 'three', 'three');
|
||||
}
|
||||
|
||||
do_catchsql_test 12.1.1 {
|
||||
SELECT fts5_columntext(t1, -1) FROM t1('two');
|
||||
} {1 SQLITE_RANGE}
|
||||
do_catchsql_test 12.1.2 {
|
||||
SELECT fts5_columntext(t1, 3) FROM t1('two');
|
||||
} {1 SQLITE_RANGE}
|
||||
do_catchsql_test 12.1.2 {
|
||||
SELECT fts5_columntext(t1, 1) FROM t1('one AND two');
|
||||
} {0 two}
|
||||
|
||||
do_catchsql_test 12.2.1 {
|
||||
SELECT fts5_queryphrase(t1, -1) FROM t1('one AND two');
|
||||
} {1 SQLITE_RANGE}
|
||||
do_catchsql_test 12.2.2 {
|
||||
SELECT fts5_queryphrase(t1, 2) FROM t1('one AND two');
|
||||
} {1 SQLITE_RANGE}
|
||||
do_catchsql_test 12.2.3 {
|
||||
SELECT fts5_queryphrase(t1, 1) FROM t1('one AND two');
|
||||
} {0 {{1 2 1}}}
|
||||
|
||||
do_catchsql_test 12.3.1 {
|
||||
SELECT fts5_collist(t1, -1) FROM t1('one AND two');
|
||||
} {1 SQLITE_RANGE}
|
||||
do_catchsql_test 12.3.2 {
|
||||
SELECT fts5_collist(t1, 2) FROM t1('one AND two');
|
||||
} {1 SQLITE_RANGE}
|
||||
do_catchsql_test 12.3.3 {
|
||||
SELECT fts5_collist(t1, 1) FROM t1('one AND two');
|
||||
} {0 1}
|
||||
|
||||
finish_test
|
||||
|
@@ -293,4 +293,39 @@ do_catchsql_test 7.2.5 {
|
||||
SELECT * FROM t1('abc') ORDER BY rank;
|
||||
} {1 {recursively defined fts5 content table}}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Check that if the content table is a view, and that view contains an
|
||||
# error, a reasonable error message is returned if the user tries to
|
||||
# read from the view via the fts5 table.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 8.1 {
|
||||
CREATE VIEW a1 AS
|
||||
SELECT 1 AS r, text_value(1) AS t
|
||||
UNION ALL
|
||||
SELECT 2 AS r, text_value(2) AS t;
|
||||
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(t, content='a1', content_rowid='r');
|
||||
}
|
||||
|
||||
foreach {tn sql} {
|
||||
1 "SELECT * FROM t1"
|
||||
2 "INSERT INTO t1(t1) VALUES('rebuild')"
|
||||
3 "SELECT * FROM t1 WHERE rowid=1"
|
||||
} {
|
||||
do_catchsql_test 8.2.$tn $sql {1 {no such function: text_value}}
|
||||
}
|
||||
|
||||
proc text_value {i} {
|
||||
if {$i==1} { return "one" }
|
||||
if {$i==2} { return "two" }
|
||||
return "many"
|
||||
}
|
||||
db func text_value text_value
|
||||
|
||||
do_execsql_test 8.3.1 { SELECT * FROM t1 } {one two}
|
||||
do_execsql_test 8.3.2 { INSERT INTO t1(t1) VALUES('rebuild') }
|
||||
do_execsql_test 8.3.3 { SELECT * FROM t1 WHERE rowid=1 } {one}
|
||||
do_execsql_test 8.3.4 { SELECT rowid FROM t1('two') } {2}
|
||||
|
||||
finish_test
|
||||
|
@@ -966,6 +966,262 @@ do_catchsql_test 6.2 {
|
||||
UPDATE t1 SET content=randomblob(500) WHERE t1;
|
||||
} {1 {constraint failed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 7.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 40960 pagesize 4096 filename crash-d8b4a99207c10b.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 0a .....@ ........
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 00 0d 00 00 00 04 ................
|
||||
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
|
||||
| 96: 00 00 00 00 0d 00 00 00 0d 0b 62 00 0f 97 0f 40 ..........b....@
|
||||
| 112: 0e d5 0e 75 0e 18 0d c0 0d 66 0d 0f 0c a4 0c 44 ...u.....f.....D
|
||||
| 128: 0b ec 0b a7 0b 62 00 00 00 00 00 00 00 00 00 00 .....b..........
|
||||
| 2912: 00 00 43 0d 06 17 11 11 08 75 74 61 62 6c 65 74 ..C......utablet
|
||||
| 2928: 34 74 34 43 52 45 41 54 45 20 56 49 52 54 55 41 4t4CREATE VIRTUA
|
||||
| 2944: 4c 20 54 41 42 4c 45 20 74 34 20 55 53 49 4e 47 L TABLE t4 USING
|
||||
| 2960: 20 66 74 73 35 76 6f 63 61 62 28 27 74 32 27 2c fts5vocab('t2',
|
||||
| 2976: 20 27 72 6f 77 27 29 43 0c 06 17 11 11 08 75 74 'row')C......ut
|
||||
| 2992: 61 62 6c 65 74 33 74 33 43 52 45 41 54 45 20 56 ablet3t3CREATE V
|
||||
| 3008: 49 52 54 55 41 4c 20 54 41 42 4c 45 20 74 33 20 IRTUAL TABLE t3
|
||||
| 3024: 55 53 49 4e 47 20 66 74 73 35 76 6f 63 61 62 28 USING fts5vocab(
|
||||
| 3040: 27 74 31 27 2c 20 27 72 6f 77 27 29 56 0b 06 17 't1', 'row')V...
|
||||
| 3056: 1f 1f 01 7d 74 61 62 6c 65 74 32 5f 63 6f 6e 66 ....tablet2_conf
|
||||
| 3072: 69 67 74 32 5f 63 6f 6e 66 69 67 0a 43 52 45 41 igt2_config.CREA
|
||||
| 3088: 54 45 20 54 41 42 4c 45 20 27 74 32 5f 63 6f 6e TE TABLE 't2_con
|
||||
| 3104: 66 69 67 27 28 6b 20 50 52 49 4d 41 52 59 20 4b fig'(k PRIMARY K
|
||||
| 3120: 45 59 2c 20 76 29 20 57 49 54 48 4f 55 54 20 52 EY, v) WITHOUT R
|
||||
| 3136: 4f 57 49 44 5e 0a 07 17 21 21 01 81 07 74 61 62 OWID^...!!...tab
|
||||
| 3152: 6c 65 74 32 5f 63 6f 6e 74 65 6e 74 74 32 5f 63 let2_contentt2_c
|
||||
| 3168: 6f 6e 74 65 6e 74 09 43 52 45 41 54 45 20 54 41 ontent.CREATE TA
|
||||
| 3184: 42 4c 45 20 27 74 32 5f 63 6f 6e 74 65 6e 74 27 BLE 't2_content'
|
||||
| 3200: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
|
||||
| 3216: 41 52 59 20 4b 45 59 2c 20 63 30 2c 20 63 31 2c ARY KEY, c0, c1,
|
||||
| 3232: 20 63 32 29 69 09 07 17 19 19 01 81 2d 74 61 62 c2)i.......-tab
|
||||
| 3248: 6c 65 74 32 5f 69 64 78 74 32 5f 69 64 78 08 43 let2_idxt2_idx.C
|
||||
| 3264: 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 32 5f REATE TABLE 't2_
|
||||
| 3280: 69 64 78 27 28 73 65 67 69 64 2c 20 74 65 72 6d idx'(segid, term
|
||||
| 3296: 2c 20 70 67 6e 6f 2c 20 50 52 49 4d 41 52 59 20 , pgno, PRIMARY
|
||||
| 3312: 4b 45 59 28 73 65 67 69 64 2c 20 74 65 72 6d 29 KEY(segid, term)
|
||||
| 3328: 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 55 ) WITHOUT ROWIDU
|
||||
| 3344: 08 07 17 1b 1b 01 81 01 74 61 62 6c 65 74 32 5f ........tablet2_
|
||||
| 3360: 64 61 74 61 74 32 5f 64 61 74 61 07 43 52 45 41 datat2_data.CREA
|
||||
| 3376: 54 45 20 54 41 42 4c 45 20 27 74 32 5f 64 61 74 TE TABLE 't2_dat
|
||||
| 3392: 61 27 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 a'(id INTEGER PR
|
||||
| 3408: 49 4d 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b IMARY KEY, block
|
||||
| 3424: 20 42 4c 4f 42 29 58 07 07 17 11 11 08 81 1d 74 BLOB)X........t
|
||||
| 3440: 61 62 6c 65 74 32 74 32 43 52 45 41 54 45 20 56 ablet2t2CREATE V
|
||||
| 3456: 49 52 54 55 41 4c 20 54 41 42 4c 45 20 74 32 20 IRTUAL TABLE t2
|
||||
| 3472: 55 53 49 4e 47 20 66 74 73 35 28 27 61 27 2c 5b USING fts5('a',[
|
||||
| 3488: 62 5d 2c 22 63 22 2c 64 65 74 61 69 6c 3d 6e 6f b],.c.,detail=no
|
||||
| 3504: 6e 65 2c 63 6f 6c 75 6d 6e 73 69 7a 65 3d 30 29 ne,columnsize=0)
|
||||
| 3520: 56 06 06 17 1f 1f 01 7d 74 61 62 6c 65 74 31 5f V.......tablet1_
|
||||
| 3536: 63 6f 6e 66 69 67 74 31 5f 63 6f 6e 66 69 67 06 configt1_config.
|
||||
| 3552: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 CREATE TABLE 't1
|
||||
| 3568: 5f 63 6f 6e 66 69 67 27 28 6b 20 50 52 49 4d 41 _config'(k PRIMA
|
||||
| 3584: 52 59 20 4b 45 59 2c 20 76 29 20 57 49 54 48 4f RY KEY, v) WITHO
|
||||
| 3600: 55 54 20 52 4f 57 49 44 5b 05 07 17 21 21 01 81 UT ROWID[...!!..
|
||||
| 3616: 01 74 61 62 6c 65 74 31 5f 64 6f 63 73 69 7a 65 .tablet1_docsize
|
||||
| 3632: 74 31 5f 64 6f 63 73 69 7a 65 05 43 52 45 41 54 t1_docsize.CREAT
|
||||
| 3648: 45 20 54 41 42 4c 45 20 27 74 31 5f 64 6f 63 73 E TABLE 't1_docs
|
||||
| 3664: 69 7a 65 27 28 69 64 20 49 4e 54 45 47 45 52 20 ize'(id INTEGER
|
||||
| 3680: 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 73 7a 20 PRIMARY KEY, sz
|
||||
| 3696: 42 4c 4f 42 29 5e 04 07 17 21 21 01 81 07 74 61 BLOB)^...!!...ta
|
||||
| 3712: 62 6c 65 74 31 5f 63 6f 6e 74 65 6e 74 74 31 5f blet1_contentt1_
|
||||
| 3728: 63 6f 6e 74 65 6e 74 04 43 52 45 41 54 45 20 54 content.CREATE T
|
||||
| 3744: 41 42 4c 45 20 27 74 31 5f 63 6f 6e 74 65 6e 74 ABLE 't1_content
|
||||
| 3760: 27 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 '(id INTEGER PRI
|
||||
| 3776: 4d 41 52 59 20 4b 45 59 2c 20 63 30 2c 20 63 31 MARY KEY, c0, c1
|
||||
| 3792: 2c 20 63 32 29 69 03 07 17 19 19 01 81 2d 74 61 , c2)i.......-ta
|
||||
| 3808: 62 6c 65 74 31 5f 69 64 78 74 31 5f 69 64 78 03 blet1_idxt1_idx.
|
||||
| 3824: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 CREATE TABLE 't1
|
||||
| 3840: 5f 69 64 78 27 28 73 65 67 69 64 2c 20 74 65 72 _idx'(segid, ter
|
||||
| 3856: 6d 2c 20 70 67 6e 6f 2c 20 50 52 49 4d 41 52 59 m, pgno, PRIMARY
|
||||
| 3872: 20 4b 45 59 28 73 65 67 69 64 2c 20 74 65 72 6d KEY(segid, term
|
||||
| 3888: 29 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 )) WITHOUT ROWID
|
||||
| 3904: 55 02 07 17 1b 1b 01 81 01 74 61 62 6c 65 74 31 U........tablet1
|
||||
| 3920: 5f 64 61 74 61 74 31 5f 64 61 74 61 02 43 52 45 _datat1_data.CRE
|
||||
| 3936: 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 64 61 ATE TABLE 't1_da
|
||||
| 3952: 74 61 27 28 69 64 20 49 4e 54 45 47 45 52 20 50 ta'(id INTEGER P
|
||||
| 3968: 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 RIMARY KEY, bloc
|
||||
| 3984: 6b 20 42 4c 4f 42 29 67 01 07 17 11 11 08 81 3b k BLOB)g.......;
|
||||
| 4000: 74 61 62 6c 65 74 31 74 31 43 52 45 41 54 45 20 tablet1t1CREATE
|
||||
| 4016: 56 49 52 54 55 41 4c 20 54 41 42 4c 45 20 74 31 VIRTUAL TABLE t1
|
||||
| 4032: 20 55 53 49 4e 47 20 66 74 73 35 28 61 2c 62 20 USING fts5(a,b
|
||||
| 4048: 75 6e 69 6e 64 65 78 65 64 2c 63 2c 74 6f 6b 65 unindexed,c,toke
|
||||
| 4064: 6e 69 7a 65 3d 22 70 6f 72 74 65 72 20 61 73 63 nize=.porter asc
|
||||
| 4080: 69 69 22 2c 74 6f 6b 65 6e 64 61 74 61 3d 31 29 ii.,tokendata=1)
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 0f 68 00 05 0f 13 00 0f e6 0f 13 0f a8 0f 7c ..h............|
|
||||
| 16: 0f 2a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .*..............
|
||||
| 3856: 00 00 00 15 0a 03 00 30 00 00 00 00 01 03 03 00 .......0........
|
||||
| 3872: 03 01 01 01 02 01 01 03 01 01 37 8c 80 80 80 80 ..........7.....
|
||||
| 3888: 01 03 00 74 00 00 00 2e 02 30 61 03 02 02 01 01 ...t.....0a.....
|
||||
| 3904: 62 03 02 03 01 01 63 03 02 04 01 01 67 03 06 01 b.....c.....g...
|
||||
| 3920: 02 02 01 01 68 03 06 01 02 03 01 01 69 03 06 01 ....h.......i...
|
||||
| 3936: 02 04 04 06 06 06 08 08 0f ef 00 14 2a 00 00 00 ............*...
|
||||
| 3952: 00 01 02 02 00 02 01 01 01 02 01 01 25 88 80 80 ............%...
|
||||
| 3968: 80 80 01 03 00 50 00 00 00 1f 02 30 67 02 08 02 .....P.....0g...
|
||||
| 3984: 01 02 02 01 01 68 02 08 03 01 02 03 01 01 69 02 .....h........i.
|
||||
| 4000: 08 04 01 02 04 04 09 09 37 84 80 80 80 7f f1 03 ........7.......
|
||||
| 4016: 00 74 00 00 00 2e 02 30 61 01 02 02 01 01 62 01 .t.....0a.....b.
|
||||
| 4032: 02 03 01 01 63 01 02 04 01 01 67 01 06 01 02 02 ....c.....g.....
|
||||
| 4048: 01 01 68 01 06 01 02 03 01 01 69 01 06 01 02 04 ..h.......i.....
|
||||
| 4064: 04 06 06 06 08 08 07 01 03 00 14 03 09 00 09 00 ................
|
||||
| 4080: 00 00 11 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
|
||||
| page 3 offset 8192
|
||||
| 0: 0a 00 00 00 03 0f ec 00 0f fa 0f f3 0f ec 00 00 ................
|
||||
| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 06 04 01 0c ................
|
||||
| 4080: 01 03 02 06 04 01 0c 01 02 02 05 04 09 0c 01 02 ................
|
||||
| page 4 offset 12288
|
||||
| 0: 0d 00 00 00 03 0f be 00 0f ea 0f d4 0f be 00 00 ................
|
||||
| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 03 ................
|
||||
| 4032: 05 00 17 17 17 61 20 62 20 63 67 20 68 20 69 67 .....a b cg h ig
|
||||
| 4048: 20 68 20 69 14 02 05 00 17 17 17 67 20 68 20 69 h i.......g h i
|
||||
| 4064: 61 20 62 20 63 67 20 68 20 69 14 01 05 00 17 17 a b cg h i......
|
||||
| 4080: 17 61 20 62 20 63 64 20 65 20 66 67 20 68 20 69 .a b cd e fg h i
|
||||
| page 5 offset 16384
|
||||
| 0: 0d 00 00 00 03 0f e8 00 0f f8 0f f0 0f e8 00 00 ................
|
||||
| 4064: 00 00 00 00 00 00 00 00 06 03 03 00 12 03 00 03 ................
|
||||
| 4080: 06 02 03 00 12 03 00 03 06 01 03 00 12 03 00 03 ................
|
||||
| page 6 offset 20480
|
||||
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
|
||||
| page 7 offset 24576
|
||||
| 0: 0d 00 00 00 03 0f 9e 00 0f e6 0f ef 0f 9e 00 00 ................
|
||||
| 3984: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 41 84 ..............A.
|
||||
| 4000: 80 80 80 80 01 04 00 81 06 00 00 00 34 02 30 61 ............4.0a
|
||||
| 4016: 01 01 01 01 01 62 01 01 01 01 01 63 01 01 01 01 .....b.....c....
|
||||
| 4032: 01 64 01 01 01 65 01 01 01 66 01 01 01 67 01 01 .d...e...f...g..
|
||||
| 4048: 01 01 01 68 01 01 01 01 01 69 01 01 01 04 06 06 ...h.....i......
|
||||
| 4064: 06 04 04 04 06 06 07 01 03 00 14 03 09 09 09 0f ................
|
||||
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
|
||||
| page 8 offset 28672
|
||||
| 0: 0a 00 00 00 01 0f fa 00 0f fa 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
|
||||
| page 9 offset 32768
|
||||
| 0: 0d 00 00 00 03 0f be 00 0f ea 0f d4 0f be 00 00 ................
|
||||
| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 03 ................
|
||||
| 4032: 05 00 17 17 17 61 20 62 20 63 67 20 68 20 69 67 .....a b cg h ig
|
||||
| 4048: 20 68 20 69 14 02 05 00 17 17 17 67 20 68 20 69 h i.......g h i
|
||||
| 4064: 61 20 62 20 63 67 20 68 20 69 14 01 05 00 17 17 a b cg h i......
|
||||
| 4080: 17 61 20 62 20 63 64 20 65 20 66 67 20 68 20 69 .a b cd e fg h i
|
||||
| page 10 offset 36864
|
||||
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
|
||||
| end crash-d8b4a99207c10b.db
|
||||
}]} {}
|
||||
|
||||
do_catchsql_test 7.1 {
|
||||
SELECT snippet(t1, -1, '.', '..', '[', ']'),
|
||||
highlight(t1, 2, '[', ']')
|
||||
FROM t1('g + h')
|
||||
WHERE rank MATCH 'bm25(1.0, 1.0)' ORDER BY rank;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 8.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 20480 pagesize 4096 filename crash-d57c01958e48ab.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 05 .....@ ........
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 04 ................
|
||||
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
|
||||
| 96: 00 00 00 00 0d 00 00 00 05 0e 10 00 0f 97 0f 40 ...............@
|
||||
| 112: 0e d5 0e 68 0e 10 01 00 00 00 00 00 00 00 00 00 ...h............
|
||||
| 3600: 56 05 06 17 1f 1f 01 7d 74 61 62 6c 65 74 31 5f V.......tablet1_
|
||||
| 3616: 63 6f 6e 66 69 67 74 31 5f 63 6f 6e 66 69 67 05 configt1_config.
|
||||
| 3632: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 CREATE TABLE 't1
|
||||
| 3648: 5f 63 6f 6e 66 69 67 27 28 6b 20 50 52 49 4d 41 _config'(k PRIMA
|
||||
| 3664: 52 59 20 4b 45 59 2c 20 76 29 20 57 49 54 48 4f RY KEY, v) WITHO
|
||||
| 3680: 55 54 20 52 4f 57 49 44 6b 04 07 17 21 21 01 81 UT ROWIDk...!!..
|
||||
| 3696: 21 74 61 62 6c 65 74 31 5f 64 6f 63 73 69 7a 65 !tablet1_docsize
|
||||
| 3712: 74 31 5f 64 6f 63 73 69 7a 65 04 43 52 45 41 54 t1_docsize.CREAT
|
||||
| 3728: 45 20 54 41 42 4c 45 20 27 74 31 5f 64 6f 63 73 E TABLE 't1_docs
|
||||
| 3744: 69 7a 65 27 28 69 64 20 49 4e 54 45 47 45 52 20 ize'(id INTEGER
|
||||
| 3760: 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 73 7a 20 PRIMARY KEY, sz
|
||||
| 3776: 42 4c 4f 42 2c 20 6f 72 69 67 69 6e 20 49 4e 54 BLOB, origin INT
|
||||
| 3792: 45 47 45 52 29 69 03 07 17 19 19 01 81 2d 74 61 EGER)i.......-ta
|
||||
| 3808: 62 6c 65 74 31 5f 69 64 78 74 31 5f 69 64 78 03 blet1_idxt1_idx.
|
||||
| 3824: 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 CREATE TABLE 't1
|
||||
| 3840: 5f 69 64 78 27 28 73 65 67 69 64 2c 20 74 65 72 _idx'(segid, ter
|
||||
| 3856: 6d 2c 20 70 67 6e 6f 2c 20 50 52 49 4d 41 52 59 m, pgno, PRIMARY
|
||||
| 3872: 20 4b 45 59 28 73 65 67 69 64 2c 20 74 65 72 6d KEY(segid, term
|
||||
| 3888: 29 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 )) WITHOUT ROWID
|
||||
| 3904: 55 02 07 17 1b 1b 01 81 01 74 61 62 6c 65 74 31 U........tablet1
|
||||
| 3920: 5f 64 61 74 61 74 31 5f 64 61 74 61 02 43 52 45 _datat1_data.CRE
|
||||
| 3936: 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 64 61 ATE TABLE 't1_da
|
||||
| 3952: 74 61 27 28 69 64 20 49 4e 54 45 47 45 52 20 50 ta'(id INTEGER P
|
||||
| 3968: 52 49 4d 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 RIMARY KEY, bloc
|
||||
| 3984: 6b 20 42 4c 4f 42 29 67 01 07 17 11 11 08 81 3b k BLOB)g.......;
|
||||
| 4000: 74 61 62 6c 65 74 31 74 31 43 52 45 41 54 45 20 tablet1t1CREATE
|
||||
| 4016: 56 49 52 54 55 41 4c 20 54 41 42 4c 45 20 74 31 VIRTUAL TABLE t1
|
||||
| 4032: 20 55 53 49 4e 47 20 66 74 73 35 28 61 2c 20 62 USING fts5(a, b
|
||||
| 4048: 2c 20 63 6f 6e 74 65 6e 74 3d 27 27 2c 20 63 6f , content='', co
|
||||
| 4064: 6e 74 65 6e 74 6c 65 73 73 5f 64 65 6c 65 74 65 ntentless_delete
|
||||
| 4080: 3d 31 2c 20 74 6f 6b 65 6e 64 61 74 61 3d 31 29 =1, tokendata=1)
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 0f eb 00 03 0e 17 00 0f e2 0e 17 0e 31 00 00 .............1..
|
||||
| 16: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 3600: 00 00 00 00 00 00 00 18 0a 03 00 36 00 00 00 00 ...........6....
|
||||
| 3616: ff 00 00 01 01 01 01 00 01 01 01 01 01 01 00 00 ................
|
||||
| 3632: 07 83 29 84 80 80 80 80 01 04 00 86 56 00 00 01 ..).........V...
|
||||
| 3648: 96 04 30 61 61 61 01 02 02 01 04 02 04 01 08 02 ..0aaa..........
|
||||
| 3664: 04 04 04 01 10 02 04 04 04 04 04 04 04 01 20 02 .............. .
|
||||
| 3680: 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 01 ................
|
||||
| 3696: 40 02 04 04 04 04 04 04 04 04 04 04 04 04 04 04 @...............
|
||||
| 3712: 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 ................
|
||||
| 3728: 04 01 81 00 02 04 04 04 04 04 04 04 04 04 04 04 ................
|
||||
| 3744: 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 ................
|
||||
| 3760: 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 ................
|
||||
| 3776: 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 ................
|
||||
| 3792: 04 04 04 04 02 02 62 63 01 06 01 01 02 01 03 62 ......bc.......b
|
||||
| 3808: 62 62 02 02 03 01 04 03 06 01 08 03 06 06 06 01 bb..............
|
||||
| 3824: 10 03 06 06 06 06 06 06 06 01 20 03 06 06 06 06 .......... .....
|
||||
| 3840: 06 06 06 06 06 06 06 06 06 06 06 01 40 03 06 06 ............@...
|
||||
| 3856: 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 ................
|
||||
| 3872: 06 06 06 06 06 06 06 06 06 06 16 06 06 02 02 63 ...............c
|
||||
| 3888: 64 02 06 01 01 02 01 03 63 63 63 03 02 05 01 04 d.......ccc.....
|
||||
| 3904: 05 0a 01 08 05 0a 0a 0a 01 10 05 0a 0a 0a 0a 0a ................
|
||||
| 3920: 0a 0a 01 20 05 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a ... ............
|
||||
| 3936: 0a 0a 0a 0a 02 02 64 65 03 06 01 01 02 01 03 64 ......de.......d
|
||||
| 3952: 64 64 04 02 09 01 04 09 12 01 08 09 12 12 12 01 dd..............
|
||||
| 3968: 10 09 12 12 12 12 12 12 12 02 02 65 66 04 06 01 ...........ef...
|
||||
| 3984: 01 02 01 03 65 65 65 05 02 11 01 04 11 22 01 08 ....eee.........
|
||||
| 4000: 11 22 22 22 02 02 66 67 05 06 01 01 02 01 03 66 ......fg.......f
|
||||
| 4016: 56 66 06 02 21 01 04 21 42 02 02 67 68 06 06 01 Vf..!..!B..gh...
|
||||
| 4032: 01 02 cb 03 67 67 67 07 02 41 02 02 68 69 07 06 ....ggg..A..hi..
|
||||
| 4048: 01 01 02 04 81 13 09 50 09 2e 09 1c 09 12 09 0c .......P........
|
||||
| 4064: 09 08 07 01 03 00 14 07 81 77 07 00 00 00 15 22 .........w......
|
||||
| 4080: 00 00 00 00 ff 00 00 01 00 00 00 00 00 00 05 0c ................
|
||||
| page 3 offset 8192
|
||||
| 0: 0a 00 00 00 01 0f fa 00 0f fa 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
|
||||
| page 4 offset 12288
|
||||
| 0: 0d 00 00 00 07 0f c8 00 0f f8 0f f0 0f e8 0f e0 ................
|
||||
| 16: 0f d8 0f d0 0f c8 00 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4032: 00 00 00 00 00 00 00 00 06 07 04 00 10 09 7f 01 ................
|
||||
| 4048: 06 06 04 00 10 09 3f 01 06 05 04 00 10 09 1f 01 ......?.........
|
||||
| 4064: 06 04 04 00 10 09 0f 01 06 03 04 00 10 09 07 01 ................
|
||||
| 4080: 06 02 04 00 10 09 03 01 06 01 04 00 10 09 01 01 ................
|
||||
| page 5 offset 16384
|
||||
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
|
||||
| end crash-d57c01958e48ab.db
|
||||
}]} {}
|
||||
|
||||
do_catchsql_test 8.1 {
|
||||
SELECT rowid FROM t1('a* NOT ý') ;
|
||||
} {0 {1 2 3 4 5 6 7}}
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
|
@@ -88,6 +88,54 @@ do_faultsim_test 2 -faults oom* -prep {
|
||||
faultsim_test_result {0 {10 24}}
|
||||
}
|
||||
|
||||
reset_db
|
||||
sqlite3_fts5_register_origintext db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(
|
||||
x, tokenize="origintext unicode61", tokendata=1
|
||||
);
|
||||
INSERT INTO t1(t1, rank) VALUES('pgsz', 64);
|
||||
|
||||
INSERT INTO t1(rowid, x) VALUES(9, 'bbb Bbb BBB');
|
||||
BEGIN;
|
||||
INSERT INTO t1(rowid, x) VALUES(10, 'aaa bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(11, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(12, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(13, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(14, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(15, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(16, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(17, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(18, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(19, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(20, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(21, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(22, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(23, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(24, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(25, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(26, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(27, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(28, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(29, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(30, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(31, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(32, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(33, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(34, 'bbb Bbb BBB');
|
||||
INSERT INTO t1(rowid, x) VALUES(35, 'aaa bbb BBB');
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_faultsim_test 3 -faults oom* -prep {
|
||||
} -body {
|
||||
execsql {
|
||||
SELECT rowid FROM t1('BBB AND AAA');
|
||||
}
|
||||
} -test {
|
||||
faultsim_integrity_check
|
||||
faultsim_test_result {0 {10 35}}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
@@ -91,7 +91,6 @@ do_execsql_test 2.2.1 {
|
||||
INSERT INTO vt0(c0) VALUES ('xyz');
|
||||
}
|
||||
|
||||
breakpoint
|
||||
do_execsql_test 2.2.2 {
|
||||
ALTER TABLE t0 RENAME TO t1;
|
||||
}
|
||||
@@ -500,6 +499,21 @@ do_execsql_test 17.5 {
|
||||
SELECT c0 FROM t0 WHERE c0 GLOB '*faul*';
|
||||
} {assertionfaultproblem}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 18.0 {
|
||||
BEGIN;
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(text);
|
||||
ALTER TABLE t1 RENAME TO t2;
|
||||
}
|
||||
|
||||
do_execsql_test 18.1 {
|
||||
DROP TABLE t2;
|
||||
}
|
||||
|
||||
do_execsql_test 18.2 {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
@@ -21,6 +21,19 @@ ifcapable !fts5 {
|
||||
return
|
||||
}
|
||||
|
||||
# The tests below verify that a doclist-index is used to limit the number
|
||||
# of pages loaded into the cache. It does this by querying sqlite3_db_status()
|
||||
# for the amount of memory used by the pager cache.
|
||||
#
|
||||
# memsubsys1 effectively limits the page-cache to 24 pages. Which masks
|
||||
# the effect tested by the tests in this file. And "mmap" prevents the
|
||||
# cache from being used, also preventing these tests from working.
|
||||
#
|
||||
if {[permutation]=="memsubsys1" || [permutation]=="mmap"} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
sqlite3_fts5_register_origintext db
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
|
@@ -86,71 +86,76 @@ do_execsql_test 2.8 {
|
||||
# Tests with large/small rowid values.
|
||||
#
|
||||
|
||||
reset_db
|
||||
|
||||
expr srand(0)
|
||||
|
||||
set vocab {
|
||||
Popper Poppins Popsicle Porfirio Porrima Porsche
|
||||
Porter Portia Portland Portsmouth Portugal Portuguese
|
||||
Poseidon Post PostgreSQL Potemkin Potomac Potsdam
|
||||
Pottawatomie Potter Potts Pound Poussin Powell
|
||||
PowerPC PowerPoint Powers Powhatan Poznan Prada
|
||||
Prado Praetorian Prague Praia Prakrit Pratchett
|
||||
Pratt Pravda Praxiteles Preakness Precambrian Preminger
|
||||
Premyslid Prensa Prentice Pres Presbyterian Presbyterianism
|
||||
}
|
||||
proc newdoc {} {
|
||||
for {set i 0} {$i<8} {incr i} {
|
||||
lappend ret [lindex $::vocab [expr int(abs(rand()) * [llength $::vocab])]]
|
||||
foreach {tn cfg} {
|
||||
1 ""
|
||||
2 "INSERT INTO fff(fff, rank) VALUES('secure-delete', 1)"
|
||||
} {
|
||||
reset_db
|
||||
|
||||
expr srand(0)
|
||||
|
||||
set vocab {
|
||||
Popper Poppins Popsicle Porfirio Porrima Porsche
|
||||
Porter Portia Portland Portsmouth Portugal Portuguese
|
||||
Poseidon Post PostgreSQL Potemkin Potomac Potsdam
|
||||
Pottawatomie Potter Potts Pound Poussin Powell
|
||||
PowerPC PowerPoint Powers Powhatan Poznan Prada
|
||||
Prado Praetorian Prague Praia Prakrit Pratchett
|
||||
Pratt Pravda Praxiteles Preakness Precambrian Preminger
|
||||
Premyslid Prensa Prentice Pres Presbyterian Presbyterianism
|
||||
}
|
||||
set ret
|
||||
}
|
||||
db func newdoc newdoc
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE fff USING fts5(y);
|
||||
INSERT INTO fff(fff, rank) VALUES('pgsz', 64);
|
||||
|
||||
WITH s(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM s WHERE x<1000 )
|
||||
INSERT INTO fff(rowid, y) SELECT random() , newdoc() FROM s;
|
||||
|
||||
WITH s(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM s WHERE x<1000 )
|
||||
INSERT INTO fff(rowid, y) SELECT random() , newdoc() FROM s;
|
||||
|
||||
WITH s(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM s WHERE x<1000 )
|
||||
INSERT INTO fff(rowid, y) SELECT random() , newdoc() FROM s;
|
||||
|
||||
INSERT INTO fff(fff, rank) VALUES('secure-delete', 1);
|
||||
}
|
||||
|
||||
proc lshuffle {in} {
|
||||
set out [list]
|
||||
while {[llength $in]>0} {
|
||||
set idx [expr int(abs(rand()) * [llength $in])]
|
||||
lappend out [lindex $in $idx]
|
||||
set in [lreplace $in $idx $idx]
|
||||
}
|
||||
set out
|
||||
}
|
||||
|
||||
#dump fff
|
||||
|
||||
set iTest 1
|
||||
foreach ii [lshuffle [db eval {SELECT rowid FROM fff}]] {
|
||||
#if {$iTest==1} { dump fff }
|
||||
#if {$iTest==1} { breakpoint }
|
||||
do_execsql_test 3.1.$iTest.$ii {
|
||||
DELETE FROM fff WHERE rowid=$ii;
|
||||
}
|
||||
#if {$iTest==1} { dump fff }
|
||||
if {($iTest % 20)==0} {
|
||||
do_execsql_test 3.1.$iTest.$ii.ic {
|
||||
INSERT INTO fff(fff) VALUES('integrity-check');
|
||||
proc newdoc {} {
|
||||
for {set i 0} {$i<8} {incr i} {
|
||||
lappend ret [lindex $::vocab [expr int(abs(rand()) * [llength $::vocab])]]
|
||||
}
|
||||
set ret
|
||||
}
|
||||
db func newdoc newdoc
|
||||
|
||||
do_execsql_test 3.$tn.0 {
|
||||
CREATE VIRTUAL TABLE fff USING fts5(y);
|
||||
INSERT INTO fff(fff, rank) VALUES('pgsz', 64);
|
||||
|
||||
WITH s(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM s WHERE x<1000 )
|
||||
INSERT INTO fff(rowid, y) SELECT random() , newdoc() FROM s;
|
||||
|
||||
WITH s(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM s WHERE x<1000 )
|
||||
INSERT INTO fff(rowid, y) SELECT random() , newdoc() FROM s;
|
||||
|
||||
WITH s(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM s WHERE x<1000 )
|
||||
INSERT INTO fff(rowid, y) SELECT random() , newdoc() FROM s;
|
||||
}
|
||||
|
||||
execsql $cfg
|
||||
|
||||
proc lshuffle {in} {
|
||||
set out [list]
|
||||
while {[llength $in]>0} {
|
||||
set idx [expr int(abs(rand()) * [llength $in])]
|
||||
lappend out [lindex $in $idx]
|
||||
set in [lreplace $in $idx $idx]
|
||||
}
|
||||
set out
|
||||
}
|
||||
|
||||
#dump fff
|
||||
|
||||
set iTest 1
|
||||
foreach ii [lshuffle [db eval {SELECT rowid FROM fff}]] {
|
||||
#if {$iTest==1} { dump fff }
|
||||
#if {$iTest==1} { breakpoint }
|
||||
do_execsql_test 3.$tn.1.$iTest.$ii {
|
||||
DELETE FROM fff WHERE rowid=$ii;
|
||||
}
|
||||
#if {$iTest==1} { dump fff }
|
||||
if {($iTest % 20)==0} {
|
||||
do_execsql_test 3.$tn.1.$iTest.$ii.ic {
|
||||
INSERT INTO fff(fff) VALUES('integrity-check');
|
||||
}
|
||||
}
|
||||
#if {$iTest==1} { break }
|
||||
incr iTest
|
||||
}
|
||||
#if {$iTest==1} { break }
|
||||
incr iTest
|
||||
}
|
||||
|
||||
#execsql_pp { SELECT rowid FROM fff('post') ORDER BY rowid ASC }
|
||||
|
@@ -42,7 +42,7 @@ proc fts5_test_bothlist {cmd} {
|
||||
}
|
||||
sqlite3_fts5_create_function db fts5_test_bothlist fts5_test_bothlist
|
||||
|
||||
proc fts5_rowid {cmd} { expr [$cmd xColumnText -1] }
|
||||
proc fts5_rowid {cmd} { expr [$cmd xRowid] }
|
||||
sqlite3_fts5_create_function db fts5_rowid fts5_rowid
|
||||
|
||||
do_execsql_test 1.$tok.0.1 "
|
||||
|
@@ -280,6 +280,30 @@ do_catchsql_test 5.2 {
|
||||
INSERT INTO t1 SELECT randomblob(3000) FROM v1
|
||||
} {1 {query aborted}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
sqlite3_fts5_may_be_corrupt 1
|
||||
|
||||
do_execsql_test 6.0 {
|
||||
BEGIN TRANSACTION;
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a,b unindexed,c,tokenize="porter ascii",tokendata=1);
|
||||
REPLACE INTO t1_data VALUES(1,X'03090009');
|
||||
REPLACE INTO t1_data VALUES(10,X'000000000103030003010101020101030101');
|
||||
REPLACE INTO t1_data VALUES(137438953473,X'0000002e023061010202010162010203010163010204010167010601020201016801060102030101690106010204040606060808');
|
||||
REPLACE INTO t1_data VALUES(274877906945,X'0000001f013067020802010202010168020803010203010169020804010204040909');
|
||||
REPLACE INTO t1_data VALUES(412316860417,X'0000002e023061030202010162030203010163030204010167030601020201016803060102030101690306010204040606060808');
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 6.1 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts5vocab('t1', 'row');
|
||||
}
|
||||
|
||||
do_catchsql_test 6.2 {
|
||||
SELECT * FROM t3;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
|
||||
finish_test
|
||||
|
||||
|
@@ -107,6 +107,12 @@
|
||||
# undef SQLITE_OMIT_UTF16 1
|
||||
#endif
|
||||
|
||||
/**********************************************************************/
|
||||
/* SQLITE_S... */
|
||||
#ifndef SQLITE_STRICT_SUBTYPE
|
||||
# define SQLITE_STRICT_SUBTYPE 1
|
||||
#endif
|
||||
|
||||
/**********************************************************************/
|
||||
/* SQLITE_T... */
|
||||
#ifndef SQLITE_TEMP_STORE
|
||||
|
@@ -26,9 +26,14 @@
|
||||
**
|
||||
** .load ./randomjson
|
||||
** SELECT random_json(1);
|
||||
** SELECT random_json5(1);
|
||||
*/
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#ifdef SQLITE_STATIC_RANDOMJSON
|
||||
# include "sqlite3.h"
|
||||
#else
|
||||
# include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@@ -51,17 +56,18 @@ static unsigned int prngInt(Prng *p){
|
||||
return p->x ^ p->y;
|
||||
}
|
||||
|
||||
static const char *azJsonAtoms[] = {
|
||||
/* JSON /* JSON-5 */
|
||||
static char *azJsonAtoms[] = {
|
||||
/* JSON JSON-5 */
|
||||
"0", "0",
|
||||
"1", "1",
|
||||
"-1", "-1",
|
||||
"2", "+2",
|
||||
"3", "3",
|
||||
"2.5", "2.5",
|
||||
"3DDDD", "3DDDD",
|
||||
"2.5DD", "2.5DD",
|
||||
"0.75", ".75",
|
||||
"-4.0e2", "-4.e2",
|
||||
"5.0e-3", "+5e-3",
|
||||
"6.DDe+0DD", "6.DDe+0DD",
|
||||
"0", "0x0",
|
||||
"512", "0x200",
|
||||
"256", "+0x100",
|
||||
@@ -73,12 +79,14 @@ static const char *azJsonAtoms[] = {
|
||||
"-9.0e999", "-Infinity",
|
||||
"9.0e999", "+Infinity",
|
||||
"null", "NaN",
|
||||
"-0.0005123", "-0.0005123",
|
||||
"-0.0005DD", "-0.0005DD",
|
||||
"4.35e-3", "+4.35e-3",
|
||||
"\"gem\\\"hay\"", "\"gem\\\"hay\"",
|
||||
"\"icy'joy\"", "'icy\\'joy\'",
|
||||
"\"keylog\"", "\"key\\\nlog\"",
|
||||
"\"mix\\\\\\tnet\"", "\"mix\\\\\\tnet\"",
|
||||
"\"oat\\r\\n\"", "\"oat\\r\\n\"",
|
||||
"\"\\fpan\\b\"", "\"\\fpan\\b\"",
|
||||
"{}", "{}",
|
||||
"[]", "[]",
|
||||
"[]", "[/*empty*/]",
|
||||
@@ -89,19 +97,20 @@ static const char *azJsonAtoms[] = {
|
||||
"\"day\"", "\"day\"",
|
||||
"\"end\"", "'end'",
|
||||
"\"fly\"", "\"fly\"",
|
||||
"\"\\u00XX\\u00XX\"", "\"\\xXX\\xXX\"",
|
||||
"\"y\\uXXXXz\"", "\"y\\uXXXXz\"",
|
||||
"\"\"", "\"\"",
|
||||
};
|
||||
static const char *azJsonTemplate[] = {
|
||||
static char *azJsonTemplate[] = {
|
||||
/* JSON JSON-5 */
|
||||
"{\"a\":%,\"b\":%,\"c\":%}", "{a:%,b:%,c:%}",
|
||||
"{\"a\":%,\"b\":%,\"cDD\":%}", "{a:%,b:%,cDD:%}",
|
||||
"{\"a\":%,\"b\":%,\"c\":%,\"d\":%,\"e\":%}", "{a:%,b:%,c:%,d:%,e:%}",
|
||||
"{\"a\":%,\"b\":%,\"c\":%,\"d\":%,\"\":%}", "{a:%,b:%,c:%,d:%,\"\":%}",
|
||||
"{\"a\":%,\"b\":%,\"c\":%,\"d\":%,\"\":%}", "{a:%,b:%,c:%,d:%,'':%}",
|
||||
"{\"d\":%}", "{d:%}",
|
||||
"{\"eeee\":%, \"ffff\":%}", "{eeee:% /*and*/, ffff:%}",
|
||||
"{\"$g\":%,\"_h_\":%}", "{$g:%,_h_:%,}",
|
||||
"{\"$g\":%,\"_h_\":%,\"a b c d\":%}", "{$g:%,_h_:%,\"a b c d\":%}",
|
||||
"{\"x\":%,\n \"y\":%}", "{\"x\":%,\n \"y\":%}",
|
||||
"{\"a b c d\":%,\"e\":%,\"f\":%,\"x\":%,\"y\":%}",
|
||||
"{\"a b c d\":%,e:%,f:%,x:%,y:%}",
|
||||
"{\"\\u00XX\":%,\"\\uXXXX\":%}", "{\"\\xXX\":%,\"\\uXXXX\":%}",
|
||||
"{\"Z\":%}", "{Z:%,}",
|
||||
"[%]", "[%,]",
|
||||
"[%,%]", "[%,%]",
|
||||
@@ -122,15 +131,13 @@ static void jsonExpand(
|
||||
unsigned int r /* Growth probability 0..1000. 0 means no growth */
|
||||
){
|
||||
unsigned int i, j, k;
|
||||
const char *z;
|
||||
char *z;
|
||||
char *zX;
|
||||
size_t n;
|
||||
char zBuf[200];
|
||||
|
||||
j = 0;
|
||||
if( zSrc==0 ){
|
||||
k = prngInt(p)%(count(azJsonTemplate)/2);
|
||||
k = k*2 + eType;
|
||||
zSrc = azJsonTemplate[k];
|
||||
}
|
||||
if( zSrc==0 ) zSrc = "%";
|
||||
if( strlen(zSrc)>=STRSZ/10 ) r = 0;
|
||||
for(i=0; zSrc[i]; i++){
|
||||
if( zSrc[i]!='%' ){
|
||||
@@ -149,9 +156,36 @@ static void jsonExpand(
|
||||
z = azJsonTemplate[k];
|
||||
}
|
||||
n = strlen(z);
|
||||
if( (zX = strstr(z,"XX"))!=0 ){
|
||||
unsigned int y = prngInt(p);
|
||||
if( (y&0xff)==((y>>8)&0xff) ) y += 0x100;
|
||||
while( (y&0xff)==((y>>16)&0xff) || ((y>>8)&0xff)==((y>>16)&0xff) ){
|
||||
y += 0x10000;
|
||||
}
|
||||
memcpy(zBuf, z, n+1);
|
||||
z = zBuf;
|
||||
zX = strstr(z,"XX");
|
||||
while( zX!=0 ){
|
||||
zX[0] = "0123456789abcdef"[y%16]; y /= 16;
|
||||
zX[1] = "0123456789abcdef"[y%16]; y /= 16;
|
||||
zX = strstr(zX, "XX");
|
||||
}
|
||||
}else if( (zX = strstr(z,"DD"))!=0 ){
|
||||
unsigned int y = prngInt(p);
|
||||
memcpy(zBuf, z, n+1);
|
||||
z = zBuf;
|
||||
zX = strstr(z,"DD");
|
||||
while( zX!=0 ){
|
||||
zX[0] = "0123456789"[y%10]; y /= 10;
|
||||
zX[1] = "0123456789"[y%10]; y /= 10;
|
||||
zX = strstr(zX, "DD");
|
||||
}
|
||||
}
|
||||
assert( strstr(z, "XX")==0 );
|
||||
assert( strstr(z, "DD")==0 );
|
||||
if( j+n<STRSZ ){
|
||||
memcpy(&zDest[j], z, n);
|
||||
j += n;
|
||||
j += (int)n;
|
||||
}
|
||||
}
|
||||
zDest[STRSZ-1] = 0;
|
||||
@@ -178,7 +212,7 @@ static void randJsonFunc(
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_randomjson_init(
|
||||
sqlite3 *db,
|
||||
@@ -188,7 +222,11 @@ int sqlite3_randomjson_init(
|
||||
static int cOne = 1;
|
||||
static int cZero = 0;
|
||||
int rc = SQLITE_OK;
|
||||
#ifdef SQLITE_STATIC_RANDOMJSON
|
||||
(void)pApi; /* Unused parameter */
|
||||
#else
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
#endif
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
rc = sqlite3_create_function(db, "random_json", 1,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
|
||||
|
@@ -1087,4 +1087,4 @@ endif
|
||||
|
||||
# Run local web server for the test/demo pages.
|
||||
httpd:
|
||||
althttpd -max-age 1 -enable-sab -page index.html
|
||||
althttpd -max-age 1 -enable-sab 1 -page index.html
|
||||
|
@@ -147,6 +147,12 @@
|
||||
# define SQLITE_OS_KV_OPTIONAL 1
|
||||
#endif
|
||||
|
||||
/**********************************************************************/
|
||||
/* SQLITE_S... */
|
||||
#ifndef SQLITE_STRICT_SUBTYPE
|
||||
# define SQLITE_STRICT_SUBTYPE 1
|
||||
#endif
|
||||
|
||||
/**********************************************************************/
|
||||
/* SQLITE_T... */
|
||||
#ifndef SQLITE_TEMP_STORE
|
||||
|
Reference in New Issue
Block a user