diff --git a/manifest b/manifest index 57155ac277..a6f329f957 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Ensure\sthat\seponymous\svirtual\stable\sobjects\sare\snot\sleft\swith\sdangling\sschema\spointers\sif\sthe\smain\sdatabase\sis\soverwritten\susing\ssqlite3_serialize(). -D 2026-10-05T14:13:52.993 +C Handle\stemp\striggers\sattached\sto\sdatabases\sclobbered\sby\ssqlite3_deserialize()\sin\sthe\ssame\sway\sas\sthose\sattached\sto\sDETACHed\sdatabases. +D 2026-10-05T18:11:38.016 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -676,7 +676,7 @@ F sqlite3.1 1b9c24374a85dfc7eb8fa7c4266ee0db4f9609cceecfc5481cd8307e5af04366 F sqlite3.pc.in e6dee284fba59ef500092fdc1843df3be8433323a3733c91da96690a50a5b398 F src/alter.c d7cbe4332a7a2c3a21ab58ee2609efade493f6ae78254613ada0759898629ee3 F src/analyze.c 42ed904f4a81d0e4f32491e10ff8ea3cdf2f98a29b04a015f0a29046b32b4e0f -F src/attach.c 833a90efe85acedc38c6231e38bb763a9fb0fd0757bcb05dad61b8cabc143c59 +F src/attach.c dc4be11e8bd4d6656facdc62992cc2d171e6fd6c9aac109af9db8d2316f9847a F src/auth.c ebec42df26b34a62b6750d30d9c2c03554a1c522020182476f7729a439fef04f F src/backup.c a3181d1a979bca40dd2b60393cf664c9659e71c25938661c1d3a786e489880f0 F src/bitvec.c e242d4496774dfc88fa278177dd23b607dce369ccafb3f61b41638eea2c9b399 @@ -1429,7 +1429,7 @@ F test/malloctraceviewer.tcl 3e3ddf11e30d2b20f53aa16aa6615082fb24a100bea61cca721 F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7 -F test/memdb1.test bc34f7a0fca53be99417007569d9409c548a31121485e60cc8c77ea053f4ad7e +F test/memdb1.test 5ae1afad50df9d3ac63bc7bcdd1db39533b5c68f969efdffdba3af4dda179182 F test/memdb2.test 4ba1fc09e2f51df80d148a540e4a3fa66d0462e91167b27497084de4d1f6b5b4 F test/memjournal.test 70f3a00c7f84ee2978ad14e831231caa1e7f23915a2c54b4f775a021d5740c6c F test/memjournal2.test dbc2c5cb5f7b38950f4f6dc3e73fcecf0fcbed3fc32c7ce913bba164d288da1e @@ -2207,9 +2207,9 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P fc3b85a1b75bb880195b88523f6d75f825f6874c487cd4d69254d588c9123c67 -Q +18d2646f6fa56244be12122873cd9aa48b2074a22f0be637edfcc9b5de99158b -R cbd271c83b87bce14ce05596d18bdd92 +P 794e3e0fe386284327c3a58f7071087ab9d3580aae44efe835663597f74e39c2 +Q +84c773fcc2f785346fd12e8a17ac45f9068797d9629ddc367318994b6fed421b +R 777a55f2c40fa66f94e2eb9c2dcce8af U dan -Z 9c8c0c2d23ad65c9418341125a69d51c +Z 386fc9eedeb6167cb33d766410e272b8 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index eaa991d9fb..6751a1d89a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -794e3e0fe386284327c3a58f7071087ab9d3580aae44efe835663597f74e39c2 +872587e1567020e32c6c833b40818ba88a0b02de97b9db7b16daae08762508a8 diff --git a/src/attach.c b/src/attach.c index ce301b5a34..1ae8165065 100644 --- a/src/attach.c +++ b/src/attach.c @@ -56,6 +56,23 @@ int sqlite3DbIsNamed(sqlite3 *db, int iDb, const char *zName){ ); } +/* +** If any TEMP triggers reference schema pSchema, move those triggers to +** reference the TEMP schema itself. +*/ +static void detachTempTriggers(sqlite3 *db, Schema *pSchema){ + HashElem *pEntry; + assert( db->aDb[1].pSchema ); + pEntry = sqliteHashFirst(&db->aDb[1].pSchema->trigHash); + while( pEntry ){ + Trigger *pTrig = (Trigger*)sqliteHashData(pEntry); + if( pTrig->pTabSchema==pSchema ){ + pTrig->pTabSchema = pTrig->pSchema; + } + pEntry = sqliteHashNext(pEntry); + } +} + /* ** An SQL user-function registered to do the work of an ATTACH statement. The ** three arguments to the function come directly from an attach statement: @@ -125,6 +142,7 @@ static void attachFunc( /* Both the Btree and the new Schema were allocated successfully. ** Close the old db and update the aDb[] slot with the new memdb ** values. */ + detachTempTriggers(db, pNew->pSchema); sqlite3BtreeClose(pNew->pBt); pNew->pBt = pNewBt; pNew->pSchema = pNewSchema; @@ -304,7 +322,6 @@ static void detachFunc( sqlite3 *db = sqlite3_context_db_handle(context); int i; Db *pDb = 0; - HashElem *pEntry; char zErr[128]; UNUSED_PARAMETER(NotUsed); @@ -331,18 +348,7 @@ static void detachFunc( goto detach_error; } - /* If any TEMP triggers reference the schema being detached, move those - ** triggers to reference the TEMP schema itself. */ - assert( db->aDb[1].pSchema ); - pEntry = sqliteHashFirst(&db->aDb[1].pSchema->trigHash); - while( pEntry ){ - Trigger *pTrig = (Trigger*)sqliteHashData(pEntry); - if( pTrig->pTabSchema==pDb->pSchema ){ - pTrig->pTabSchema = pTrig->pSchema; - } - pEntry = sqliteHashNext(pEntry); - } - + detachTempTriggers(db, pDb->pSchema); sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; pDb->pSchema = 0; diff --git a/test/memdb1.test b/test/memdb1.test index a5cf71802a..5679a2ac68 100644 --- a/test/memdb1.test +++ b/test/memdb1.test @@ -363,4 +363,45 @@ do_execsql_test 1250 { SELECT value FROM json_each('[4,5]'); } {4 5} +#------------------------------------------------------------------------- +# A TEMP trigger on a table in a database overwritten by a deserialize() +# is orphaned in the same way as if the db was DETACHed. +# +reset_db +do_execsql_test 1400 { + CREATE TABLE t1(x); +} +set blob [db serialize main] + +do_execsql_test 1410 { + CREATE TEMP TABLE tlog(y); + CREATE TEMP TRIGGER tr AFTER INSERT ON main.t1 BEGIN + INSERT INTO tlog VALUES(new.x); + END; + INSERT INTO t1 VALUES(1); + SELECT * FROM tlog; +} {1} + +do_test 1420 { db deserialize main $blob } {} + +do_execsql_test 1430 { + INSERT INTO t1 VALUES(2); + SELECT * FROM tlog; +} {1} + +do_execsql_test 1440 { + SELECT name, tbl_name FROM temp.sqlite_schema WHERE type='trigger'; +} {tr t1} + +do_execsql_test 1450 { + CREATE TEMP TABLE t1(x); + INSERT INTO temp.t1 VALUES(3); + SELECT * FROM tlog; +} {1} + +do_execsql_test 1460 { + DROP TRIGGER temp.tr; + SELECT name FROM temp.sqlite_schema WHERE type='trigger'; +} {} + finish_test