From 55e0fd4a9d81bde6452f276eb05532c60ad1d49e Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 17 Jul 2023 17:59:58 +0000 Subject: [PATCH] Do not allow the 'delete' command to be used on contentless_delete=1 fts5 tables. FossilOrigin-Name: cc694b83408ccb5d42204cb624145c76e95329cbe1d1fe8815c70a7a00af231a --- ext/fts5/fts5Int.h | 4 ++-- ext/fts5/fts5_index.c | 18 +++++++++--------- ext/fts5/fts5_main.c | 9 ++++++++- ext/fts5/fts5_storage.c | 12 ++++++------ ext/fts5/test/fts5contentless.test | 19 ++++++++++++++++--- manifest | 24 ++++++++++++------------ manifest.uuid | 2 +- 7 files changed, 54 insertions(+), 34 deletions(-) diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index 43f78c6d99..da2f90f230 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -536,8 +536,8 @@ int sqlite3Fts5IndexReset(Fts5Index *p); int sqlite3Fts5IndexLoadConfig(Fts5Index *p); -int sqlite3Fts5IndexGetLocation(Fts5Index *p, i64 *piLoc); -int sqlite3Fts5IndexContentlessDelete(Fts5Index *p, i64 iLoc, i64 iRowid); +int sqlite3Fts5IndexGetOrigin(Fts5Index *p, i64 *piOrigin); +int sqlite3Fts5IndexContentlessDelete(Fts5Index *p, i64 iOrigin, i64 iRowid); /* ** End of interface to code in fts5_index.c. diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 2ed9eee1fd..0bb204ea92 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -96,8 +96,8 @@ ** ** Then, for V2 structures only: ** -** + lower location counter value, -** + upper location counter value +** + lower origin counter value, +** + upper origin counter value ** ** 2. The Averages Record: ** @@ -337,7 +337,7 @@ struct Fts5DoclistIter { ** nOriginCntr: ** This value is set to non-zero for structure records created for ** contentlessdelete=1 tables only. In that case it represents the -** location value to apply to the next top-level segment created. +** origin value to apply to the next top-level segment created. */ struct Fts5StructureSegment { int iSegid; /* Segment id */ @@ -4509,7 +4509,7 @@ static void fts5IndexMergeLevel( /* Read input from all segments in the input level */ nInput = pLvl->nSeg; - /* Set the range of locations that will go into the output segment */ + /* Set the range of origins that will go into the output segment */ if( pStruct->nOriginCntr>0 ){ pSeg->iOrigin1 = pLvl->aSeg[0].iOrigin1; pSeg->iOrigin2 = pLvl->aSeg[pLvl->nSeg-1].iOrigin2; @@ -6411,11 +6411,11 @@ int sqlite3Fts5IndexLoadConfig(Fts5Index *p){ return fts5IndexReturn(p); } -int sqlite3Fts5IndexGetLocation(Fts5Index *p, i64 *piLoc){ +int sqlite3Fts5IndexGetOrigin(Fts5Index *p, i64 *piOrigin){ Fts5Structure *pStruct; pStruct = fts5StructureRead(p); if( pStruct ){ - *piLoc = pStruct->nOriginCntr; + *piOrigin = pStruct->nOriginCntr; fts5StructureRelease(pStruct); } return fts5IndexReturn(p); @@ -6684,9 +6684,9 @@ static void fts5IndexTombstoneAdd( /* ** Add iRowid to the tombstone list of the segment or segments that contain -** rows from location iLoc. +** rows from origin iOrigin. */ -int sqlite3Fts5IndexContentlessDelete(Fts5Index *p, i64 iLoc, i64 iRowid){ +int sqlite3Fts5IndexContentlessDelete(Fts5Index *p, i64 iOrigin, i64 iRowid){ Fts5Structure *pStruct; pStruct = fts5StructureRead(p); if( pStruct ){ @@ -6695,7 +6695,7 @@ int sqlite3Fts5IndexContentlessDelete(Fts5Index *p, i64 iLoc, i64 iRowid){ int iSeg; for(iSeg=0; iSegaLevel[iLvl].nSeg; iSeg++){ Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg]; - if( pSeg->iOrigin1<=(u64)iLoc && pSeg->iOrigin2>=(u64)iLoc ){ + if( pSeg->iOrigin1<=(u64)iOrigin && pSeg->iOrigin2>=(u64)iOrigin ){ fts5IndexTombstoneAdd(p, pSeg, iRowid); } } diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c index 844b5c57ef..b10da49c75 100644 --- a/ext/fts5/fts5_main.c +++ b/ext/fts5/fts5_main.c @@ -1653,7 +1653,14 @@ static int fts5UpdateMethod( if( pConfig->eContent!=FTS5_CONTENT_NORMAL && 0==sqlite3_stricmp("delete", z) ){ - rc = fts5SpecialDelete(pTab, apVal); + if( pConfig->bContentlessDelete ){ + fts5SetVtabError(pTab, + "'delete' may not be used with a contentless_delete=1 table" + ); + rc = SQLITE_ERROR; + }else{ + rc = fts5SpecialDelete(pTab, apVal); + } }else{ rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]); } diff --git a/ext/fts5/fts5_storage.c b/ext/fts5/fts5_storage.c index 35c30d06e6..f28e4d7dd2 100644 --- a/ext/fts5/fts5_storage.c +++ b/ext/fts5/fts5_storage.c @@ -136,7 +136,7 @@ static int fts5StorageGetStmt( case FTS5_STMT_LOOKUP_DOCSIZE: zSql = sqlite3_mprintf(azStmt[eStmt], - (pC->bContentlessDelete ? ",location" : ""), + (pC->bContentlessDelete ? ",origin" : ""), pC->zDb, pC->zName ); break; @@ -332,7 +332,7 @@ int sqlite3Fts5StorageOpen( if( rc==SQLITE_OK && pConfig->bColumnsize ){ const char *zCols = "id INTEGER PRIMARY KEY, sz BLOB"; if( pConfig->bContentlessDelete ){ - zCols = "id INTEGER PRIMARY KEY, sz BLOB, location INTEGER"; + zCols = "id INTEGER PRIMARY KEY, sz BLOB, origin INTEGER"; } rc = sqlite3Fts5CreateTable(pConfig, "docsize", zCols, 0, pzErr); } @@ -472,7 +472,7 @@ static int fts5StorageContentlessDelete(Fts5Storage *p, i64 iDel){ assert( p->pConfig->bContentlessDelete ); assert( p->pConfig->eContent==FTS5_CONTENT_NONE ); - /* Look up the location of the document in the %_docsize table. Store + /* Look up the origin of the document in the %_docsize table. Store ** this in stack variable iLoc. */ rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup, 0); if( rc==SQLITE_OK ){ @@ -510,9 +510,9 @@ static int fts5StorageInsertDocsize( if( rc==SQLITE_OK ){ sqlite3_bind_int64(pReplace, 1, iRowid); if( p->pConfig->bContentlessDelete ){ - i64 iLoc = 0; - rc = sqlite3Fts5IndexGetLocation(p->pIndex, &iLoc); - sqlite3_bind_int64(pReplace, 3, iLoc); + i64 iOrigin = 0; + rc = sqlite3Fts5IndexGetOrigin(p->pIndex, &iOrigin); + sqlite3_bind_int64(pReplace, 3, iOrigin); } if( rc==SQLITE_OK ){ sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC); diff --git a/ext/fts5/test/fts5contentless.test b/ext/fts5/test/fts5contentless.test index 18f05da887..181ccb177e 100644 --- a/ext/fts5/test/fts5contentless.test +++ b/ext/fts5/test/fts5contentless.test @@ -51,7 +51,7 @@ foreach {tn sql bError} { execsql { ROLLBACK } } -# Check that if contentless_delete=1 is specified, then the "location" +# Check that if contentless_delete=1 is specified, then the "origin" # column is added to the %_docsize table. reset_db do_execsql_test 3.0 { @@ -62,7 +62,7 @@ do_execsql_test 3.1 { SELECT sql FROM sqlite_schema WHERE name IN ('x1_docsize', 'x2_docsize'); } { {CREATE TABLE 'x1_docsize'(id INTEGER PRIMARY KEY, sz BLOB)} - {CREATE TABLE 'x2_docsize'(id INTEGER PRIMARY KEY, sz BLOB, location INTEGER)} + {CREATE TABLE 'x2_docsize'(id INTEGER PRIMARY KEY, sz BLOB, origin INTEGER)} } do_execsql_test 3.2.1 { @@ -77,7 +77,7 @@ do_execsql_test 3.3 { INSERT INTO x2 VALUES('second text'); } do_execsql_test 3.4 { - SELECT id, location FROM x2_docsize + SELECT id, origin FROM x2_docsize } {1 1 2 2} do_execsql_test 3.5 { SELECT level, segment, loc1, loc2 FROM fts5_structure( @@ -247,5 +247,18 @@ do_test 7.2 { do_execsql_test 7.3 { SELECT rowid FROM ft('one'); } {} do_execsql_test 7.4 { SELECT rowid FROM ft('two'); } $lRowid +#------------------------------------------------------------------------- +reset_db + +reset_db +do_execsql_test 8.0 { + CREATE VIRTUAL TABLE ft USING fts5(x, content='', contentless_delete=1); + INSERT INTO ft VALUES('hello world'); +} + +do_catchsql_test 8.1 { + INSERT INTO ft(ft, rowid, x) VALUES('delete', 1, 'hello world'); +} {1 {'delete' may not be used with a contentless_delete=1 table}} + finish_test diff --git a/manifest b/manifest index 07be41e1ec..2bd8a2d3d4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\strunk\schanges\sinto\sthis\sbranch. -D 2023-07-17T11:47:42.362 +C Do\snot\sallow\sthe\s'delete'\scommand\sto\sbe\sused\son\scontentless_delete=1\sfts5\stables. +D 2023-07-17T17:59:58.252 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -86,15 +86,15 @@ F ext/fts3/unicode/mkunicode.tcl d5aebf022fa4577ee8cdf27468f0d847879993959101f6d F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h c132a9323f22a972c4c93a8d5a3d901113a6e612faf30ca8e695788438c5ca2a -F ext/fts5/fts5Int.h 40a234875f9bddd43b4b4281d946303d227de943773b9e84505a0d6f0419c16a +F ext/fts5/fts5Int.h fa9dd8ecbda6340f406c6f21b9b524b4666817aa89850e60a42937eea87cef6a F ext/fts5/fts5_aux.c 572d5ec92ba7301df2fea3258576332f2f4d2dfd66d8263afd157d9deceac480 F ext/fts5/fts5_buffer.c 3001fbabb585d6de52947b44b455235072b741038391f830d6b729225eeaf6a5 F ext/fts5/fts5_config.c 010fabcc0aaa0dfa76b19146e8bddf7de368933eeac01e294af6607447500caa F ext/fts5/fts5_expr.c 2473c13542f463cae4b938c498d6193c90d38ea1a2a4f9849c0479736e50d24d F ext/fts5/fts5_hash.c d4fb70940359f2120ccd1de7ffe64cc3efe65de9e8995b822cd536ff64c96982 -F ext/fts5/fts5_index.c c38e8892905e9e57e22ca4441cb6fdb519f188d786efe541e9d4df24c34e9197 -F ext/fts5/fts5_main.c c036530bbd39935b4b91fddb9d1b9d456e95c3685509aa975c87fc35445a9722 -F ext/fts5/fts5_storage.c 9a84d28154cb570773b26eb9645f8670089dee45c95afebf7a041e414266b3c3 +F ext/fts5/fts5_index.c 8e5fd1f1eb9489f1ba2eff2d3667ffd78a8d936c1180d284ccc6c37f25953a8f +F ext/fts5/fts5_main.c ede405f0f11db562653b988d043a531daa66093b46c1b35b8fcddb54819cba84 +F ext/fts5/fts5_storage.c ee69d6c8195d2bf584ac8c5433e5c685812f39b48c7464f8aa76d9ed8b489119 F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee F ext/fts5/fts5_test_tok.c a2bed8edb25f6432e8cdb62aad5916935c19dba8dac2b8324950cfff397e25ff @@ -132,7 +132,7 @@ F ext/fts5/test/fts5config.test 60094712debc59286c59aef0e6cf511c37d866802776a825 F ext/fts5/test/fts5conflict.test 655925678e630d3cdf145d18725a558971806416f453ac8410ca8c04d934238d F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c073e19b3ae9126b2f4 F ext/fts5/test/fts5content.test 213506436fb2c87567b8e31f6d43ab30aab99354cec74ed679f22aad0cdbf283 -F ext/fts5/test/fts5contentless.test 08af7954537cf89acbdef4fd79f39b3a36f382683a1eb98d5c827c187f51e113 +F ext/fts5/test/fts5contentless.test 063249b7d0e92dc7ea54b4a179c466828927d720ee054031cbf6e06009c972bf F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f F ext/fts5/test/fts5corrupt3.test 7da9895dafa404efd20728f66ff4b94399788bdc042c36fe2689801bba2ccd78 @@ -535,8 +535,8 @@ F ext/wasm/index.html b768e8659b4fe311912e54d42906449d51c0f84b7f036cca47ec1f93bf F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54 F ext/wasm/jaccwabyt/jaccwabyt.md 37911f00db12cbcca73aa1ed72594430365f30aafae2fa9c886961de74e5e0eb F ext/wasm/module-symbols.html 841de62fc198988b8330e238c260e70ec93028b096e1a1234db31b187a899d10 -F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96 w ext/wasm/scratchpad-wasmfs-main.html -F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63 w ext/wasm/scratchpad-wasmfs-main.js +F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96 +F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63 F ext/wasm/speedtest1-wasmfs.html 0e9d335a9b5b5fafe6e1bc8dc0f0ca7e22e6eb916682a2d7c36218bb7d67379d F ext/wasm/speedtest1-wasmfs.mjs ac5cadbf4ffe69e9eaac8b45e8523f030521e02bb67d654c6eb5236d9c456cbe F ext/wasm/speedtest1-worker.html 97c2bf5f8534091ce718de05801090d5a80c3f13575996f095ba23638e1bdca0 @@ -2044,8 +2044,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4410e60d0c76e057ee962124f9239c6e17fd5ccafdbb4d9b703448eabd7781e3 984d491eb3fe06f714bf07d6873321f3992a072812b46508e599bfefd39dff3e -R 3a33d523b0a231ecfa8d84bbc59989ba +P c4fb2f2ea0afe638fd7cffd89fbdb0a91589577c6f8299c7bbc17ac121be518b +R 461e0bbee60dbc3aadc58386c3f130fe U dan -Z cf32871cae7a0d476c03b4d509e36da6 +Z 81dd61cf0a290b6d176bc4273c289b56 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 8d642d98f8..7ecfbd954a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c4fb2f2ea0afe638fd7cffd89fbdb0a91589577c6f8299c7bbc17ac121be518b \ No newline at end of file +cc694b83408ccb5d42204cb624145c76e95329cbe1d1fe8815c70a7a00af231a \ No newline at end of file -- 2.39.5