aboutsummaryrefslogtreecommitdiff
path: root/ext/fts5
diff options
context:
space:
mode:
Diffstat (limited to 'ext/fts5')
-rw-r--r--ext/fts5/fts5_index.c38
-rw-r--r--ext/fts5/test/fts5vocab2.test21
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