]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix multiple problems with RETURNING on a DML statement against a view.
authordrh <>
Tue, 28 Mar 2023 11:21:09 +0000 (11:21 +0000)
committerdrh <>
Tue, 28 Mar 2023 11:21:09 +0000 (11:21 +0000)
(1) Do not allow a RETURNING clause to trick the code generator into thinking
that the view being updated has an INSTEAD OF trigger.
(2) Generate all result columns for a view in a DML statement.
(3) The automatic covering index for a view should cover all result columns
of the view.

FossilOrigin-Name: b49816fcce24d28ac2147a3b9afdc8b5b95ed68f89c74b0e6afb1ad5b9bd8741

manifest
manifest.uuid
src/delete.c
src/insert.c
src/sqliteInt.h
src/trigger.c
src/update.c
src/where.c
test/returning1.test
test/window1.test

index 15d7b6660b0846ba878a9125caeed9b5b56854b8..f162c5c15e39ee154dffebe67f18e9cb4384d7d1 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Do\snot\sallow\sconstant\sfactoring\sduring\sPRAGMA\sintegrity_check,\ssince\sthe\nconstants\smight\sbe\sstored\sin\sregisters\sthat\sare\slater\sreused\sfor\sother\npurposes.
-D 2023-03-27T13:27:25.639
+C Fix\smultiple\sproblems\swith\sRETURNING\son\sa\sDML\sstatement\sagainst\sa\sview.\n(1)\sDo\snot\sallow\sa\sRETURNING\sclause\sto\strick\sthe\scode\sgenerator\sinto\sthinking\nthat\sthe\sview\sbeing\supdated\shas\san\sINSTEAD\sOF\strigger.\n(2)\sGenerate\sall\sresult\scolumns\sfor\sa\sview\sin\sa\sDML\sstatement.\n(3)\sThe\sautomatic\scovering\sindex\sfor\sa\sview\sshould\scover\sall\sresult\scolumns\nof\sthe\sview.
+D 2023-03-28T11:21:09.049
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -570,7 +570,7 @@ F src/ctime.c 20507cc0b0a6c19cd882fcd0eaeda32ae6a4229fb4b024cfdf3183043d9b703d
 F src/date.c f21815ca7172ce073db3163ac54c8d9f2841077165c1a6123b4d1c376a0c7ec7
 F src/dbpage.c d47549716549311f79dc39fe5c8fb19390a6eb2c960f8e37c89a9c4de0c1052e
 F src/dbstat.c ec92074baa61d883de58c945162d9e666c13cd7cf3a23bc38b4d1c4d0b2c2bef
-F src/delete.c 201fe0763c52783d205c8c13cdd9d55c1bd5cb21c1f036753f99103b43284b90
+F src/delete.c a9c6d3f51c0a31e9b831e0a0580a98d702904b42d216fee530940e40dec34873
 F src/expr.c 8017306e96d8c061443f33f568293704a509101fddbc6b52fa382b6239c327e7
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c 722f20779f5342a787922deded3628d8c74b5249cab04098cf17ee2f2aaff002
@@ -580,7 +580,7 @@ F src/hash.c c6af5f96a7a76d000f07c5402c48c318c2566beecdee9e78b9d9f60ce7119565
 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
 F src/hwtime.h b638809e083b601b618df877b2e89cb87c2a47a01f4def10be4c4ebb54664ac7
 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
-F src/insert.c 1b11a2e33ee52db93c02fddac67e39d00161d61b69fac2675b82f2aa68c1b61c
+F src/insert.c 05ffee42b1e66282989b12fcf99bb1cf42c76c33ee162a8957704924b4c03c66
 F src/json.c c85ed6fce06f43d414b0d7fff64749d43a0dbd1067123ee407bd3a0752454161
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
 F src/loadext.c b04eb648cedc45efe4298e1ef439ac4f0096ae27b5f01accb0a1f49d57789128
@@ -626,7 +626,7 @@ F src/shell.c.in a608a209c3f61f9debce155b5c7d56c9a785d52eb62b6831be449e2a5b97622
 F src/sqlite.h.in 662a2fa083d093896b92560c871dea6d86792b49dc4bf7b4e8dbeca8e7171488
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h da473ce2b3d0ae407a6300c4a164589b9a6bfdbec9462688a8593ff16f3bb6e4
-F src/sqliteInt.h 059c8784afc51876196c4bdbf481bc6789774e7f1ebc3704ad26aa3c05cb2648
+F src/sqliteInt.h fc2e4e97faadb6ae4cd018913ce3847ab7064f13df3d5833d1cab659e46f21de
 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
 F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -685,8 +685,8 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
 F src/tokenize.c 1305797eab3542a0896b552c6e7669c972c1468e11e92b370533c1f37a37082b
 F src/treeview.c fccf3b8c517c1f55cb380c1522febe6921fcb2bd800c16c78cab571d0eb0ccbd
-F src/trigger.c f34367fad4df451b5dfe63fcc1d384fd16e40077e42092b1c3682dedeef5a7e3
-F src/update.c 76664e1beae86e8e961983ebe19a4ee9ebd7e26683ead2b288ba08f81fc7ba4e
+F src/trigger.c ad6ab9452715fa9a8075442e15196022275b414b9141b566af8cdb7a1605f2b0
+F src/update.c 3f4fb5ad7c9b48d7911974d6579192bb3a6c27f46140b6cbb9139cc8a77b8691
 F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
 F src/util.c 3ff7bc2b48dd425b1448304bb86273b05da1621f136d51dbb9789f8803559a1f
@@ -706,7 +706,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
 F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d
 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
 F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
-F src/where.c 5cd8ce282d29160fb855abf54c46826a19e2942252de6740c00641769175d958
+F src/where.c 9286604a250b5748cda8c5ac8c21d880a34c6d5839b5f2456a74f223eb6d4f48
 F src/whereInt.h e25203e5bfee149f5f1225ae0166cfb4f1e65490c998a024249e98bb0647377c
 F src/wherecode.c b82d0d33315e1526904b95155e55e61149c4462147668e1cc4567c812735eff1
 F src/whereexpr.c 16d1eefd95f69843b45aba6d04fe2b63fc4f51584dff85ae380f5c20718f3c75
@@ -1404,7 +1404,7 @@ F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2
 F test/releasetest_data.tcl b550dd1b122a9c969df794d05ea272df535f10ff1a245062e7ba080822378016
 F test/resetdb.test 54c06f18bc832ac6d6319e5ab23d5c8dd49fdbeec7c696d791682a8006bd5fc3
 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
-F test/returning1.test c78efa2829d5f44165fcc7959961b298ae005d7775f09e5542bb2815bbaee692
+F test/returning1.test db532cde29d6aebbc48c6ddc3149b30476f8e69ca7a2c4b53986c7635e6fd8ec
 F test/returningfault.test ae4c4b5e8745813287a359d9ccdb9d5c883c2e68afb18fb0767937d5de5692a4
 F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
 F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
@@ -1895,7 +1895,7 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
 F test/win32lock.test e0924eb8daac02bf80e9da88930747bd44dd9b230b7759fed927b1655b467c9c
 F test/win32longpath.test 4baffc3acb2e5188a5e3a895b2b543ed09e62f7c72d713c1feebf76222fe9976
 F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
-F test/window1.test 5ad2f3e2aec3f2dc5cf4a66998d42a455b8ebd57ec173c0329f6b8788bcae0aa
+F test/window1.test 71e51e4d5ed34c2c7427fcfb74056713560aa7f0e8ed49728b858893716fe772
 F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476
 F test/window2.test e466a88bd626d66edc3d352d7d7e1d5531e0079b549ba44efb029d1fbff9fd3c
 F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
@@ -2045,9 +2045,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 636f6fad8d4cf7238ed2281d6c3c29736663935ff58709a783a50bc0289d40f4
-Q +0bba27b78112b2b2271e498f41c437df985aa2faab302ee5b29d9b60003a8379
-R 2395e95d2389c8ef2cc081fe4cb2f951
+P a4b5f499d9429ca219c1a706b4767e528a2baf7ddb45bde9d01a4ce5f15cbb0f
+Q +c8bedef0d61731c29ae34de1594222d15b578f9e2cddbbd5b74fb3059644fe0f
+R b317dcfb609efc7ef3378748cbdc130d
 U drh
-Z 23c6255513149a9e6277371e6bd28100
+Z f2139bc0b8f2733162583471652327e9
 # Remove this line to create a well-formed Fossil manifest.
index 65ac256583713397e8200d18c35ecc47cfd391f8..9c208fcaab6217fd8d3c34f736fbb57d79c69480 100644 (file)
@@ -1 +1 @@
-a4b5f499d9429ca219c1a706b4767e528a2baf7ddb45bde9d01a4ce5f15cbb0f
\ No newline at end of file
+b49816fcce24d28ac2147a3b9afdc8b5b95ed68f89c74b0e6afb1ad5b9bd8741
\ No newline at end of file
index 22ef7ab658137051778edaca2defad236a4915d0..27a554916a835847fa14cfa638eb2616d694318c 100644 (file)
@@ -114,13 +114,15 @@ static int tabIsReadOnly(Parse *pParse, Table *pTab){
 ** If pTab is writable but other errors have occurred -> return 1.
 ** If pTab is writable and no prior errors -> return 0;
 */
-int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
+int sqlite3IsReadOnly(Parse *pParse, Table *pTab, Trigger *pTrigger){
   if( tabIsReadOnly(pParse, pTab) ){
     sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
     return 1;
   }
 #ifndef SQLITE_OMIT_VIEW
-  if( !viewOk && IsView(pTab) ){
+  if( IsView(pTab) 
+   && (pTrigger==0 || (pTrigger->bReturning && pTrigger->pNext==0))
+  ){
     sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
     return 1;
   }
@@ -374,7 +376,7 @@ void sqlite3DeleteFrom(
     goto delete_from_cleanup;
   }
 
-  if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){
+  if( sqlite3IsReadOnly(pParse, pTab, pTrigger) ){
     goto delete_from_cleanup;
   }
   iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
index 65d11bee5468b017198c43957909608f7c9e9218..809067ff82c60916eda57c917d66b896d288106b 100644 (file)
@@ -794,7 +794,7 @@ void sqlite3Insert(
 
   /* Cannot insert into a read-only table.
   */
-  if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
+  if( sqlite3IsReadOnly(pParse, pTab, pTrigger) ){
     goto insert_cleanup;
   }
 
@@ -1241,7 +1241,7 @@ void sqlite3Insert(
     }
 
     /* Copy the new data already generated. */
-    assert( pTab->nNVCol>0 );
+    assert( pTab->nNVCol>0 || pParse->nErr>0 );
     sqlite3VdbeAddOp3(v, OP_Copy, regRowid+1, regCols+1, pTab->nNVCol-1);
 
 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
index b1a15e8866b3a245b9eb02380a04327766a478f4..a70694305b469a676bb7063c822352ea5fbfd7f1 100644 (file)
@@ -4799,7 +4799,7 @@ Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
                          Expr*,ExprList*,u32,Expr*);
 void sqlite3SelectDelete(sqlite3*, Select*);
 Table *sqlite3SrcListLookup(Parse*, SrcList*);
-int sqlite3IsReadOnly(Parse*, Table*, int);
+int sqlite3IsReadOnly(Parse*, Table*, Trigger*);
 void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
 #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
 Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*);
index d179d747af25a35278650108c895db0e9413b85e..bcb2132f0b9de0e29d315b6e62a75bd72447d7d6 100644 (file)
@@ -1453,6 +1453,9 @@ u32 sqlite3TriggerColmask(
   Trigger *p;
 
   assert( isNew==1 || isNew==0 );
+  if( IsView(pTab) ){
+    return 0xffffffff;
+  }
   for(p=pTrigger; p; p=p->pNext){
     if( p->op==op
      && (tr_tm&p->tr_tm)
index bd1ddb1a309ce1286c56626b407a577924c35650..c1f136398010c950eedd7c1fb2999b453e041fe1 100644 (file)
@@ -408,7 +408,7 @@ void sqlite3Update(
   if( sqlite3ViewGetColumnNames(pParse, pTab) ){
     goto update_cleanup;
   }
-  if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
+  if( sqlite3IsReadOnly(pParse, pTab, pTrigger) ){
     goto update_cleanup;
   }
 
index f41d5d4ae397ce4855032ced4e7bd114dd9e1f23..f68e4485aa77fa4da6a55231f86f551534daeeb6 100644 (file)
@@ -962,7 +962,11 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
   ** original table changes and the index and table cannot both be used
   ** if they go out of sync.
   */
-  extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1));
+  if( IsView(pTable) ){
+    extraCols = ALLBITS;
+  }else{
+    extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1));
+  }
   mxBitCol = MIN(BMS-1,pTable->nCol);
   testcase( pTable->nCol==BMS-1 );
   testcase( pTable->nCol==BMS-2 );
index 5ab44f2cb7e4d89bfead3534ad86de4b54ea5a32..6c098dc25674a21599aea3c9e9bece65ce314acd 100644 (file)
@@ -414,6 +414,7 @@ do_execsql_test 17.0 {
 do_execsql_test 18.0 {
   CREATE TABLE v0(c1 INT);
   CREATE VIEW view_2(c1) AS SELECT CASE WHEN c1 COLLATE TRUE THEN TRUE ELSE TRUE END FROM v0;
+  CREATE TRIGGER x1 INSTEAD OF INSERT ON view_2 BEGIN SELECT true; END;
 }
 do_catchsql_test 18.1 {
   INSERT INTO view_2 DEFAULT VALUES RETURNING *;
index 471ac2dce888f41ece1d051447d44b357d5c886a..b906a761a6d31172c4873f2673d55d7e9f8466f8 100644 (file)
@@ -2225,5 +2225,56 @@ do_execsql_test 72.1 {
   WHERE ('1' IS NOT ('abcde' NOTNULL)); 
 } {1}
 
+# 2023-03-28 https://sqlite.org/forum/forumpost/dc3b92cfa0 (Song Liu)
+#
+reset_db
+do_execsql_test 73.0 {
+  CREATE TABLE t1(a INT);
+  INSERT INTO t1(a) VALUES(1),(2),(4);
+  CREATE VIEW t2(b,c) AS SELECT * FROM t1 JOIN t1 A ORDER BY sum(0) OVER(PARTITION BY 0);
+  CREATE TRIGGER x1 INSTEAD OF UPDATE ON t2 BEGIN SELECT true; END;
+}
+do_execsql_test 73.1 {
+  SELECT * FROM t2;
+} {1 1 1 2 1 4 2 1 2 2 2 4 4 1 4 2 4 4}
+do_execsql_test 73.2 {
+  UPDATE t2 SET c=99 WHERE b=4 RETURNING *;
+} {4 99 4 99 4 99}
+do_execsql_test 73.3 {
+  SELECT *, nth_value(15,2) OVER() FROM t2, t1 WHERE b=4;
+} {
+  4 1 1 15
+  4 2 1 15
+  4 4 1 15
+  4 1 2 15
+  4 2 2 15
+  4 4 2 15
+  4 1 4 15
+  4 2 4 15
+  4 4 4 15
+}
+do_execsql_test 73.4 {
+  UPDATE t2 SET c=nth_value(15,2) OVER() FROM (SELECT * FROM t1) WHERE b=4 RETURNING *;
+} {
+  4 15
+  4 15
+  4 15
+  4 15
+  4 15
+  4 15
+  4 15
+  4 15
+  4 15
+}
+do_execsql_test 73.5 {
+  DROP TRIGGER x1;
+}
+do_catchsql_test 73.6 {
+  UPDATE t2 SET c=99 WHERE b=4 RETURNING *;
+} {1 {cannot modify t2 because it is a view}}
+do_catchsql_test 73.7 {
+  UPDATE t2 SET c=nth_value(15,2) OVER() FROM (SELECT * FROM t1) WHERE b=4 RETURNING *;
+} {1 {cannot modify t2 because it is a view}}
+
 
 finish_test