]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Avoid dropping RETURNING triggers when the schema is reset while preparing a statement. returning-fix
authordan <Dan Kennedy>
Mon, 10 Nov 2025 17:37:59 +0000 (17:37 +0000)
committerdan <Dan Kennedy>
Mon, 10 Nov 2025 17:37:59 +0000 (17:37 +0000)
FossilOrigin-Name: e26bcef7522a6f6ee8d55fa30e7fe06419566cf4e8c2df0c33c92a4c89f58c05

manifest
manifest.tags
manifest.uuid
src/callback.c
src/hash.c
src/hash.h
test/returning1.test

index 6f6610152bba60ca0d20e9c1d2b6173b029beb9a..77e1baca39cf72dbce5c90f59dd70a9e5a89fe87 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\smissing\sva_end()\scall\sin\sthe\sintckMprintf()\sfunction\sof\sthe\nincremental\sintegrity-check\sextension.
-D 2025-11-10T11:05:36.073
+C Avoid\sdropping\sRETURNING\striggers\swhen\sthe\sschema\sis\sreset\swhile\spreparing\sa\sstatement.
+D 2025-11-10T17:37:59.666
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -675,7 +675,7 @@ F src/btree.c 0ad524883ec4ccac3221c97bdc2c5d5f6e149504e14cf269bbed31362c3f4393
 F src/btree.h e823c46d87f63d904d735a24b76146d19f51f04445ea561f71cc3382fd1307f0
 F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
 F src/build.c 611e07299d72ff04bbcb9e7109183467e30925d203c3e121ef9bb3cf6876289b
-F src/callback.c acae8c8dddda41ee85cfdf19b926eefe830f371069f8aadca3aa39adf5b1c859
+F src/callback.c afa59adfaa483f668260ce69f740c8273dee3e6fee9106846e0499ebdd1ac076
 F src/carray.c ff6081a31878fc34df8fa1052a9cbf17ddc22652544dcb3e2326886ed1053b55
 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
 F src/date.c e19e0cfff9a41bfdd884c655755f6f00bca4c1a22272b56e0dd6667b7ea893a2
@@ -687,8 +687,8 @@ F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
 F src/func.c 0b802107498048d3dcac0b757720bcb8506507ce02159e213ab8161458eb293b
 F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
-F src/hash.c 73934a7f7ab1cb110614a9388cb516893b0cf5b7b69e4fd1a0780ac4ce166be7
-F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
+F src/hash.c e592527b97e99cd9046946a397d9ed63d8b466b385c8129249175a3bf22ee33c
+F src/hash.h c5f4a02aaf1dca835a68b51c8b906af265c6ca3d8d53d255e0453f0abce561be
 F src/hwtime.h d4d1b98c1afdc56986a5c0eba882786ef017e2180a320da25b4231b8e7e463e8
 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
 F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
@@ -1522,7 +1522,7 @@ F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2
 F test/reservebytes.test 6163640b5a5120c0dee6591481e673a0fa0bf0d12d4da7513bad692c1a49a162
 F test/resetdb.test 54c06f18bc832ac6d6319e5ab23d5c8dd49fdbeec7c696d791682a8006bd5fc3
 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
-F test/returning1.test 212cd4111bb941a60abf608f20250db666c21eb1bc4d49217e96c87ff3ab9d1a
+F test/returning1.test cd32517148948859db214dd814354597dd40e7489259590fac1a4f7bf44deb97
 F test/returningfault.test ae4c4b5e8745813287a359d9ccdb9d5c883c2e68afb18fb0767937d5de5692a4
 F test/rollback.test 952c4d805bca96adc2be76f621ea22115fe40b330015af36fcc8028c8547fcee
 F test/rollback2.test 3f3a4e20401825017df7e7671e9f31b6de5fae5620c2b9b49917f52f8c160a8f
@@ -2167,8 +2167,11 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd
 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
 F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 7a644178c8d289ca18631844b2d73b32fddc72afcc80906633dd38c14eba2ca9
-R bd6b05ffc04557a9ff7d69a81e6084d5
-U drh
-Z a1230748ab427e1519659da8a04065cb
+P 62ad2350e368dc337ba2d0fb6847d07c40a6f79520dd6414d22b5b54983b0b12
+R 43727fa3b19bd9f550a5daad80497dd6
+T *branch * returning-fix
+T *sym-returning-fix *
+T -sym-trunk *
+U dan
+Z 7df20ffae687bc1753586d20b75ba681
 # Remove this line to create a well-formed Fossil manifest.
index bec971799ff1b8ee641c166c7aeb22d12c785393..3f06d6cb86f4a63c09826d66401a710c6ee394a3 100644 (file)
@@ -1,2 +1,2 @@
-branch trunk
-tag trunk
+branch returning-fix
+tag returning-fix
index 835eaab8b5e3d6e6874fef70ab4e67b2d92b2154..5bcbb58eafed7071ff89cf5c9c430bb808c7da00 100644 (file)
@@ -1 +1 @@
-62ad2350e368dc337ba2d0fb6847d07c40a6f79520dd6414d22b5b54983b0b12
+e26bcef7522a6f6ee8d55fa30e7fe06419566cf4e8c2df0c33c92a4c89f58c05
index 6fe21a295621ecdcf4b5e45fc72bbda0a718353e..9ea3616b383307a88720140f1d8a3c00f36f19c2 100644 (file)
@@ -504,8 +504,16 @@ void sqlite3SchemaClear(void *p){
   temp2 = pSchema->trigHash;
   sqlite3HashInit(&pSchema->trigHash);
   sqlite3HashClear(&pSchema->idxHash);
-  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
-    sqlite3DeleteTrigger(&xdb, (Trigger*)sqliteHashData(pElem));
+  for(pElem=sqliteHashFirst(&temp2); pElem; ){
+    HashElem *pNext = sqliteHashNext(pElem);
+    Trigger *pTrig = (Trigger*)sqliteHashData(pElem);
+    if( pTrig->bReturning ){
+      /* Do not remove RETURNING triggers from the temp-triggers hash */
+      sqlite3HashTransfer(&pSchema->trigHash, &temp2, pElem);
+    }else{
+      sqlite3DeleteTrigger(&xdb, pTrig);
+    }
+    pElem = pNext;
   }
   sqlite3HashClear(&temp2);
   sqlite3HashInit(&pSchema->tblHash);
index 8cc6c09663c05beffeaa1194ffb09497323bb13e..1984a463c2081fa715b39bc4392af0f34b3e5907 100644 (file)
@@ -270,3 +270,25 @@ void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){
   insertElement(pH, pH->ht ? &pH->ht[new_elem->h % pH->htsize] : 0, new_elem);
   return 0;
 }
+
+/*
+** Parameter pElem is currently part of hash table pFrom. Add it to hash 
+** table pTo. 
+**
+** This procedure corrupts hash table pFrom. Specifically, it removes element
+** pElem from the list of all elements in the hash table, but may leave
+** a pointer to it in one of the hash buckets of pFrom. This is not a problem
+** because this function is only called if hash table pFrom will be cleared
+** before any further lookups or inserts are attempted.
+*/
+void sqlite3HashTransfer(Hash *pTo, Hash *pFrom, HashElem *pElem){
+  if( pElem->prev ){
+    pElem->prev->next = pElem->next; 
+  }else{
+    assert( pFrom->first==pElem );
+    pFrom->first = pElem->next;
+  }
+  insertElement(pTo, pTo->ht ? &pTo->ht[pElem->h % pTo->htsize] : 0, pElem);
+}
+
+
index cff65d6e508717c7b6ac63bf92429e1139bbc265..4cb1fbe47b08d76adafaae12c66057f4c6425ad3 100644 (file)
@@ -70,6 +70,7 @@ void sqlite3HashInit(Hash*);
 void *sqlite3HashInsert(Hash*, const char *pKey, void *pData);
 void *sqlite3HashFind(const Hash*, const char *pKey);
 void sqlite3HashClear(Hash*);
+void sqlite3HashTransfer(Hash*, Hash*, HashElem *pElem);
 
 /*
 ** Macros for looping over all elements of a hash table.  The idiom is
index e7be7c65a3e997a3e520c90660bfdb6c6b4dfa70..9ab646a3b74b5799b5303e14cbf2b4b9f9a77a44 100644 (file)
@@ -544,4 +544,54 @@ do_catchsql_test 22.1 {
 } {1 {no such column: sqlite_master.name}}
 
 
+#-------------------------------------------------------------------------
+reset_db 
+do_execsql_test 23.0 {
+  PRAGMA recursive_triggers = 1;
+  CREATE TABLE t1(x, y);
+  CREATE TRIGGER t1insert AFTER INSERT ON t1 WHEN new.x<5 BEGIN
+    INSERT INTO t1 VALUES(new.x+1, new.y);
+  END;
+}
+
+do_execsql_test 23.1 {
+  INSERT INTO t1 VALUES(1, 'one') RETURNING *;
+} {1 one}
+
+do_execsql_test 23.2 {
+  SELECT * FROM t1
+} {1 one 2 one 3 one 4 one 5 one}
+
+#-------------------------------------------------------------------------
+reset_db 
+ifcapable fts5 {
+
+  do_execsql_test 24.0 {
+    CREATE VIRTUAL TABLE ft USING fts5(c);
+    CREATE TABLE t1(x);
+    INSERT INTO t1 VALUES('x');
+  }
+  
+  db close
+  
+  sqlite3 db test.db
+  sqlite3 db2 test.db
+  
+  do_execsql_test 24.1 {
+    SELECT * FROM t1
+  } {x}
+  
+  do_execsql_test -db db2 24.2 {
+    CREATE TABLE t2(y);
+    INSERT INTO t2 VALUES('y');
+  } {}
+
+  db2 close
+  
+  do_execsql_test 24.3 {
+    INSERT INTO ft VALUES('hello world') RETURNING *
+  } {{hello world}}
+}
+
+
 finish_test