]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Changes so that sqlite3_vtab_nochange() works with "UPDATE ... FROM...". Use this... fts5-contentless-delete
authordan <Dan Kennedy>
Mon, 7 Aug 2023 16:15:56 +0000 (16:15 +0000)
committerdan <Dan Kennedy>
Mon, 7 Aug 2023 16:15:56 +0000 (16:15 +0000)
FossilOrigin-Name: 16cd2161e312cf97129011fc829079db8f762b822b2f4fabf7ff6742c071302f

ext/fts5/fts5_main.c
ext/fts5/test/fts5contentless.test
ext/fts5/test/fts5contentless5.test [new file with mode: 0644]
manifest
manifest.uuid
src/expr.c
src/select.c
src/update.c

index d1c79d36046453cd4124feefe6ba15f119f7df8a..c34a5a332bf3adb7f8e84e3a602501b5693caa95 100644 (file)
@@ -1689,7 +1689,7 @@ static int fts5UpdateMethod(
     ** VIRTUAL TABLE statement contained "contentless_delete=1". */
     if( eType0==SQLITE_INTEGER 
      && pConfig->eContent==FTS5_CONTENT_NONE 
-     && (nArg>1 || pConfig->bContentlessDelete==0)
+     && pConfig->bContentlessDelete==0
     ){
       pTab->p.base.zErrMsg = sqlite3_mprintf(
           "cannot %s contentless fts5 table: %s", 
@@ -2544,6 +2544,12 @@ static int fts5ColumnMethod(
       sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
     }
     pConfig->pzErrmsg = 0;
+  }else if( pConfig->bContentlessDelete && sqlite3_vtab_nochange(pCtx) ){
+    char *zErr = sqlite3_mprintf("cannot UPDATE a subset of "
+        "columns on fts5 contentless-delete table: %s", pConfig->zName
+    );
+    sqlite3_result_error(pCtx, zErr, -1);
+    sqlite3_free(zErr);
   }
   return rc;
 }
index 41a78e9c8fb48541fc0579f97fca69ae907984f3..f75ccb44c2381999e4d6d8575a0d87f8693840b7 100644 (file)
@@ -188,11 +188,11 @@ do_execsql_test 5.2 {
 
 do_catchsql_test 5.3 {
   UPDATE ft SET x='four six' WHERE rowid=3
-} {1 {cannot UPDATE contentless fts5 table: ft}}
+} {0 {}}
 
 do_execsql_test 5.4 {
   SELECT rowid FROM ft('one');
-} {1 4 5}
+} {1 4 5}
 
 do_execsql_test 5.5 {
   REPLACE INTO ft(rowid, x) VALUES(3, 'four six');
diff --git a/ext/fts5/test/fts5contentless5.test b/ext/fts5/test/fts5contentless5.test
new file mode 100644 (file)
index 0000000..1541b0c
--- /dev/null
@@ -0,0 +1,59 @@
+# 2023 August 7
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# This file contains tests for the content= and content_rowid= options.
+#
+
+source [file join [file dirname [info script]] fts5_common.tcl]
+set testprefix fts5contentless5
+
+# If SQLITE_ENABLE_FTS5 is defined, omit this file.
+ifcapable !fts5 {
+  finish_test
+  return
+}
+
+do_execsql_test 1.0 {
+  CREATE VIRTUAL TABLE t1 USING fts5(a, b, c, content='', contentless_delete=1);
+  INSERT INTO t1 VALUES('A', 'B', 'C');
+  INSERT INTO t1 VALUES('D', 'E', 'F');
+  INSERT INTO t1 VALUES('G', 'H', 'I');
+}
+
+do_execsql_test 1.01 {
+  CREATE TABLE t2(x, y);
+  INSERT INTO t2 VALUES('x', 'y');
+}
+
+# explain_i "UPDATE t1 SET a='a' WHERE t1.rowid=1"    
+breakpoint
+explain_i "UPDATE t1 SET a='a' FROM t2 WHERE t1.rowid=1 AND b IS NULL"     
+
+#breakpoint
+#explain_i "UPDATE t1 SET a='a' WHERE b IS NULL AND rowid=?"
+
+foreach {tn up err} {
+  1   "UPDATE t1 SET a='a', b='b', c='c' WHERE rowid=1"                  0
+  2   "UPDATE t1 SET a='a', b='b'        WHERE rowid=1"                  1
+  3   "UPDATE t1 SET        b='b', c='c' WHERE rowid=1"                  1
+  4   "UPDATE t1 SET a='a',        c='c' WHERE rowid=1"                  1
+  5   "UPDATE t1 SET a='a',        c='c' WHERE t1.rowid=1 AND b IS NULL" 1
+  6   "UPDATE t1 SET a='a' FROM t2 WHERE t1.rowid=1"                     1
+  7   "UPDATE t1 SET a='a', b='b', c='c' FROM t2 WHERE t1.rowid=1"       0
+} {
+
+  set res(0) {0 {}}
+  set res(1) {1 {cannot UPDATE a subset of columns on fts5 contentless-delete table: t1}}
+  do_catchsql_test 1.$tn $up $res($err)
+}
+
+finish_test
+
index d8d3391f11478ea4783203b55e33ef67ed68ad45..d159c83a4eb05e6c7a7842976fe1b8456e5827eb 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Rename\sfts5_api\spContext\sparameters\sto\spUserData,\sper\s/chat\sdiscussion.\sThis\sis\sa\scosmetic\schange\smade\sto\sreduce\sconfusion\sbetween\sthose\sparameters\sand\sthe\stwo\sother\scontext-type\sparameters\sin\sthat\sAPI.
-D 2023-08-07T09:44:00.281
+C Changes\sso\sthat\ssqlite3_vtab_nochange()\sworks\swith\s"UPDATE\s...\sFROM...".\sUse\sthis\sto\sallow\sUPDATE\son\sa\scontentless\sfts5\stable\sif\snew\svalues\sare\ssupplied\sfor\sall\sindexed\scolumns.
+D 2023-08-07T16:15:56.046
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -93,7 +93,7 @@ F ext/fts5/fts5_config.c 054359543566cbff1ba65a188330660a5457299513ac71c53b3a07d
 F ext/fts5/fts5_expr.c 2473c13542f463cae4b938c498d6193c90d38ea1a2a4f9849c0479736e50d24d
 F ext/fts5/fts5_hash.c 65e7707bc8774706574346d18c20218facf87de3599b995963c3e6d6809f203d
 F ext/fts5/fts5_index.c 93b4cd116b76b6adf224cd3d213f1e06cfe10ae0eb21d6372b1c53b8f0c382a3
-F ext/fts5/fts5_main.c 2f87ee44fdb21539c264541149f07f70e065d58f37420063e5ddef80ba0f5ede
+F ext/fts5/fts5_main.c 7070031993ba5b5d89b13206ec4ef624895f2f7c0ec72725913d301e4d382445
 F ext/fts5/fts5_storage.c 3c9b41fce41b6410f2e8f82eb035c6a29b2560483f773e6dc98cf3cb2e4ddbb5
 F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
 F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
@@ -132,10 +132,11 @@ 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 9a42a86822670792ba632f5c57459addeb774d93b29d5e6ddae08faa64c2b6d9
+F ext/fts5/test/fts5contentless.test eb31159d62811b3a32fb1cfb36be20f9d9db75637c7fe6aa7f5c533db2d00576
 F ext/fts5/test/fts5contentless2.test 12c778d134a121b8bad000fbf3ae900d53226fee840ce36fe941b92737f1fda7
 F ext/fts5/test/fts5contentless3.test 487dce16b6677f68b44d7cbd158b9b7275d25e2c14d713f9188d9645bb699286
 F ext/fts5/test/fts5contentless4.test 0f43ededc2874f65d7da99b641a82239854d98d3fa43db729f284b723f23b69f
+F ext/fts5/test/fts5contentless5.test 216962d51376b62e4ff45e8db00aa3e1ab548cb36b7fd450633e73b2d678f88e
 F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe
 F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f
 F ext/fts5/test/fts5corrupt3.test 7da9895dafa404efd20728f66ff4b94399788bdc042c36fe2689801bba2ccd78
@@ -593,7 +594,7 @@ F src/date.c f73f203b3877cef866c60ab402aec2bf89597219b60635cf50cbe3c5e4533e94
 F src/dbpage.c f3eea5f7ec47e09ee7da40f42b25092ecbe961fc59566b8e5f705f34335b2387
 F src/dbstat.c ec92074baa61d883de58c945162d9e666c13cd7cf3a23bc38b4d1c4d0b2c2bef
 F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
-F src/expr.c ef4a81822da6f767696bd7f4b9983328af061158958138540142285a5b1181b7
+F src/expr.c 1affe0cc049683ef0ef3545d9b6901508556b0ef7e2892a344c3df6d7288d79d
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c a7fcbf7e66d14dbb73cf49f31489ebf66d0e6006c62b95246924a3bae9f37b36
 F src/func.c cc1da67fd643a43cfe691784158ec656d8ec6d13bb17e67018b01b38b3e4f5ab
@@ -643,7 +644,7 @@ F src/printf.c e3ba080e2f409f9bfcc8d34724e6fc160e9c718dc92d0548f6b71b8b6f860ce2
 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
 F src/resolve.c 37953a5f36c60bea413c3c04efcd433b6177009f508ef2ace0494728912fe2e9
 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
-F src/select.c abf48be202d35c4f450325b61992e98ac4aa81ed1e29709069432877d3b555d3
+F src/select.c 5f545a2c8702d4d3430bbb188cfec47d6c122d899061ef00cbe56af14591c574
 F src/shell.c.in 694aaf751f00610381533d4a31c83d142cfc83ef91ef65e2aa6912ace7c39b40
 F src/sqlite.h.in 7b07a33d2af82ee974aa91e6294abce0282b2f4c5934b291d2fff961810dd867
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
@@ -708,7 +709,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
 F src/tokenize.c 0fb405f9adf3f757c26bfc1ae6d58ac5dccbb918917ba9e5ef0e6673a06563d3
 F src/treeview.c 1d52fbc4e97161e65858d36e3424ea6e3fc045dd8a679c82b4b9593dc30de3bd
 F src/trigger.c ad6ab9452715fa9a8075442e15196022275b414b9141b566af8cdb7a1605f2b0
-F src/update.c d5b755580a86d235b12faf10de81e60ad97c8117f8c3063d92c772df94455d44
+F src/update.c 0bb9171afaa4d0b100ad946873bccda7aef90ffe083ef5c63668fce08c4df9da
 F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
 F src/util.c b3532a95ad56db67b3acd3955e688e4cb80ebec6fd1f459a8eb51cceedd6de69
@@ -2049,8 +2050,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 8ede50082e7bcf0226a3b42a590f188b5a139bbf081c9eed7ff8f6f2a6a274a0
-R 7643277fee9d7d8c9b719b0a83935d9f
-U stephan
-Z 84e0aac57037c35f1739965aedd50f66
+P 2ca064d8eb37252e16b0fec9924e9ba9289d96a737346431c6ba9cb1c161e5de
+R cb2871ec0eb1a937adec492d1c792b96
+T *branch * fts5-contentless-delete
+T *sym-fts5-contentless-delete *
+T -sym-trunk *
+U dan
+Z b30ed14be16970913bfed643626fe629
 # Remove this line to create a well-formed Fossil manifest.
index 86338d27274c44848d9bf6dcb79a917b35074c0a..ea2017dc469c2787ba29a8127b5c230343328c3b 100644 (file)
@@ -1 +1 @@
-2ca064d8eb37252e16b0fec9924e9ba9289d96a737346431c6ba9cb1c161e5de
\ No newline at end of file
+16cd2161e312cf97129011fc829079db8f762b822b2f4fabf7ff6742c071302f
\ No newline at end of file
index 0c41f6684a5e9ce6a25c0c53d0a65b3b3397ca48..d96f362856b19d4380f3b87a5dc96ae333147531 100644 (file)
@@ -3972,10 +3972,13 @@ int sqlite3ExprCodeGetColumn(
   u8 p5            /* P5 value for OP_Column + FLAGS */
 ){
   assert( pParse->pVdbe!=0 );
+  assert( (p5 & (OPFLAG_NOCHNG|OPFLAG_TYPEOFARG|OPFLAG_LENGTHARG))==p5 );
+  assert( IsVirtual(pTab) || (p5 & OPFLAG_NOCHNG)==0 );
   sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pTab, iTable, iColumn, iReg);
   if( p5 ){
     VdbeOp *pOp = sqlite3VdbeGetLastOp(pParse->pVdbe);
     if( pOp->opcode==OP_Column ) pOp->p5 = p5;
+    if( pOp->opcode==OP_VColumn ) pOp->p5 = (p5 & OPFLAG_NOCHNG);
   }
   return iReg;
 }
index 41e42b68085f7def5a19477380bb4ddf03156719..321badd07f94608f524aa15b928936b78ffe76ae 100644 (file)
@@ -1298,6 +1298,16 @@ static void selectInnerLoop(
       testcase( eDest==SRT_Fifo );
       testcase( eDest==SRT_DistFifo );
       sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg);
+#if !defined(SQLITE_ENABLE_NULL_TRIM) && defined(SQLITE_DEBUG)
+      /* A destination of SRT_Table and a non-zero iSDParm2 parameter means
+      ** that this is an "UPDATE ... FROM" on a virtual table or view. In this
+      ** case set the p5 parameter of the OP_MakeRecord to OPFLAG_NOCHNG_MAGIC.
+      ** This does not affect operation in any way - it just allows MakeRecord
+      ** to process OPFLAG_NOCHANGE values without an assert() failing. */
+      if( eDest==SRT_Table && pDest->iSDParm2 ){
+        sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC);
+      }
+#endif
 #ifndef SQLITE_OMIT_CTE
       if( eDest==SRT_DistFifo ){
         /* If the destination is DistFifo, then cursor (iParm+1) is open
index 2101aa82843587b98778dfb914179bb28feb9d67..3b3c2f838b05405d86e27a74a90d75c261cb24bc 100644 (file)
@@ -1259,7 +1259,9 @@ static void updateVirtualTable(
           sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0)
         );
       }else{
-        pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
+        Expr *pRow = exprRowColumn(pParse, i);
+        if( pRow ) pRow->op2 = OPFLAG_NOCHNG;
+        pList = sqlite3ExprListAppend(pParse, pList, pRow);
       }
     }