diff options
Diffstat (limited to 'ext/fts5')
-rw-r--r-- | ext/fts5/fts5_index.c | 38 | ||||
-rw-r--r-- | ext/fts5/test/fts5vocab2.test | 21 |
2 files changed, 58 insertions, 1 deletions
diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 613ceaf2b..ea10b357c 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -838,6 +838,40 @@ int sqlite3Fts5StructureTest(Fts5Index *p, void *pStruct){ } /* +** Ensure that structure object (*pp) is writable. +** +** This function is a no-op if (*pRc) is not SQLITE_OK when it is called. If +** an error occurs, (*pRc) is set to an SQLite error code before returning. +*/ +static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){ + Fts5Structure *p = *pp; + if( *pRc==SQLITE_OK && p->nRef>1 ){ + int nByte = sizeof(Fts5Structure)+(p->nLevel-1)*sizeof(Fts5StructureLevel); + Fts5Structure *pNew; + pNew = (Fts5Structure*)sqlite3Fts5MallocZero(pRc, nByte); + if( pNew ){ + int i; + memcpy(pNew, p, nByte); + for(i=0; i<p->nLevel; i++) pNew->aLevel[i].aSeg = 0; + for(i=0; i<p->nLevel; i++){ + Fts5StructureLevel *pLvl = &pNew->aLevel[i]; + int nByte = sizeof(Fts5StructureSegment) * pNew->aLevel[i].nSeg; + pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(pRc, nByte); + if( pLvl->aSeg==0 ){ + for(i=0; i<p->nLevel; i++){ + sqlite3_free(pNew->aLevel[i].aSeg); + } + sqlite3_free(pNew); + return; + } + memcpy(pLvl->aSeg, p->aLevel[i].aSeg, nByte); + } + } + *pp = pNew; + } +} + +/* ** Deserialize and return the structure record currently stored in serialized ** form within buffer pData/nData. ** @@ -938,9 +972,11 @@ static int fts5StructureDecode( } /* -** +** Add a level to the Fts5Structure.aLevel[] array of structure object +** (*ppStruct). */ static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){ + fts5StructureMakeWritable(pRc, ppStruct); if( *pRc==SQLITE_OK ){ Fts5Structure *pStruct = *ppStruct; int nLevel = pStruct->nLevel; diff --git a/ext/fts5/test/fts5vocab2.test b/ext/fts5/test/fts5vocab2.test index e736303cf..baef71887 100644 --- a/ext/fts5/test/fts5vocab2.test +++ b/ext/fts5/test/fts5vocab2.test @@ -255,6 +255,27 @@ do_test 5.1 { do_execsql_test 5.2 { SELECT * FROM t1 } {one two three four five} + +#------------------------------------------------------------------------- +# Check that the fts5 table cannot be written while there are vocab +# cursors open. +reset_db +do_execsql_test 5.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a); + CREATE VIRTUAL TABLE v1 USING fts5vocab(t1, instance); + WITH s(i) AS ( + VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<10000 + ) + INSERT INTO t1 SELECT + 'State Emergency Service (SES), Rural Fire Service (RFS) and Volunteers' + FROM s; +} + +do_catchsql_test 5.1 { + INSERT INTO t1 SELECT rowid FROM v1 +} {1 {query aborted}} + + finish_test |