From: dan Date: Wed, 20 Aug 2025 11:21:35 +0000 (+0000) Subject: Fix a problem with SQLITE_CHANGESET_CONFLICT conflicts caused by DELETE triggers... X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c30e1a10ef988bf15d99a89fba35f816a07d947f;p=thirdparty%2Fsqlite.git Fix a problem with SQLITE_CHANGESET_CONFLICT conflicts caused by DELETE triggers within a call to sqlite3changset_apply_v2() with SQLITE_CHANGESETAPPLY_IGNORENOOP specified. FossilOrigin-Name: 138e2aab43ac07aaf8c5389105ff6d3e107ff2d35badcb48233664fcb9661471 --- diff --git a/ext/session/sessionnoop2.test b/ext/session/sessionnoop2.test index ab8ae74cc3..5e8283d12d 100644 --- a/ext/session/sessionnoop2.test +++ b/ext/session/sessionnoop2.test @@ -175,44 +175,146 @@ do_test 3.5 { }] #------------------------------------------------------------------------- +# Test that the conflict-handler is invoked for conflicts caused by +# DELETE ops even if SQLITE_CHANGESETAPPLY_IGNORENOOP is specified. +# set ::conflict_list [list] proc xConflict {args} { lappend ::conflict_list $args return "OMIT" } -forcedelete test.db2 -do_execsql_test 4.0 { - CREATE TABLE x1(a, b, c, PRIMARY KEY(a)) WITHOUT ROWID; - INSERT INTO x1 VALUES(1, 'one', 'i'); - INSERT INTO x1 VALUES(2, 'two', 'ii'); - INSERT INTO x1 VALUES(3, 'three', 'iii'); - VACUUM INTO 'test.db2'; +foreach {tn wo} { + 1 "" + 2 " WITHOUT ROWID " +} { + reset_db + forcedelete test.db2 + do_execsql_test 4.$tn.0 " + CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c) $wo; + INSERT INTO x1 VALUES(1, 'one', 'i'); + INSERT INTO x1 VALUES(2, 'two', 'ii'); + INSERT INTO x1 VALUES(3, 'three', 'iii'); + VACUUM INTO 'test.db2'; + " + + set C [changeset_from_sql { + DELETE FROM x1 WHERE a=2; + }] + + sqlite3 db2 test.db2 + do_execsql_test -db db2 4.$tn.1 { + UPDATE x1 SET b='four hundred' WHERE a=2; + } + + do_test 4.$tn.2.1 { + set ::conflict_list [list] + sqlite3changeset_apply_v2 db2 $C xConflict + set ::conflict_list + } [list {*}{ + {DELETE x1 DATA {i 2 t two t ii} {i 2 t {four hundred} t ii}} + }] + + do_test 4.$tn.2.2 { + set ::conflict_list [list] + sqlite3changeset_apply_v2 -ignorenoop db2 $C xConflict + set ::conflict_list + } [list {*}{ + {DELETE x1 DATA {i 2 t two t ii} {i 2 t {four hundred} t ii}} + }] } -set C [changeset_from_sql { - DELETE FROM x1 WHERE a=2; -}] +foreach {tn wo} { + 1 "" + 2 " WITHOUT ROWID " +} { + reset_db + forcedelete test.db2 + do_execsql_test 5.$tn.0 " + PRAGMA foreign_keys = ON; + CREATE TABLE p1(a INTEGER PRIMARY KEY, b, c) $wo; + CREATE TABLE c1(a INTEGER PRIMARY KEY REFERENCES p1, b); + INSERT INTO p1 VALUES(1, 'one', 'i'); + INSERT INTO p1 VALUES(2, 'two', 'ii'); + INSERT INTO p1 VALUES(3, 'three', 'iii'); + VACUUM INTO 'test.db2'; + " + + set C [changeset_from_sql { + DELETE FROM p1 WHERE a=2; + }] + + sqlite3 db2 test.db2 + do_execsql_test -db db2 5.$tn.1 { + PRAGMA foreign_keys = ON; + INSERT INTO c1 VALUES(2, 'xyz'); + } -sqlite3 db2 test.db2 -do_execsql_test -db db2 4.1 { - UPDATE x1 SET b='four hundred' WHERE a=2; + do_test 5.$tn.2.1 { + set ::conflict_list [list] + sqlite3changeset_apply_v2 db2 $C xConflict + set ::conflict_list + } [list {*}{ + {FOREIGN_KEY 1} + }] + + # Reinsert the row deleted by test case 5.$tn.2.1 + execsql { INSERT INTO p1 VALUES(2, 'two', 'ii') } db2 + + do_test 5.$tn.2.2 { + set ::conflict_list [list] + sqlite3changeset_apply_v2 -ignorenoop db2 $C xConflict + set ::conflict_list + } [list {*}{ + {FOREIGN_KEY 1} + }] } -do_test 4.2.1 { - set ::conflict_list [list] - sqlite3changeset_apply_v2 db2 $C xConflict - set ::conflict_list -} [list {*}{ - {DELETE x1 DATA {i 2 t two t ii} {i 2 t {four hundred} t ii}} -}] -do_test 4.2.2 { - set ::conflict_list [list] - sqlite3changeset_apply_v2 -ignorenoop db2 $C xConflict - set ::conflict_list -} [list {*}{ - {DELETE x1 DATA {i 2 t two t ii} {i 2 t {four hundred} t ii}} -}] +foreach {tn wo} { + 1 "" + 2 " WITHOUT ROWID " +} { + reset_db + forcedelete test.db2 + do_execsql_test 6.$tn.0 " + CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c) $wo; + CREATE TABLE x2(x UNIQUE); + + INSERT INTO x1 VALUES(1, 'one', 'i'); + INSERT INTO x1 VALUES(2, 'two', 'ii'); + INSERT INTO x1 VALUES(3, 'three', 'iii'); + VACUUM INTO 'test.db2'; + " + + set C [changeset_from_sql { + DELETE FROM x1 WHERE a=2; + }] + + sqlite3 db2 test.db2 + do_execsql_test -db db2 6.$tn.1 { + INSERT INTO x2 VALUES(0); + CREATE TRIGGER tr1 AFTER DELETE ON x1 BEGIN + INSERT INTO x2 VALUES(0); + END; + } + + do_test 6.$tn.2.1 { + set ::conflict_list [list] + sqlite3changeset_apply_v2 db2 $C xConflict + set ::conflict_list + } [list {*}{ + {DELETE x1 CONSTRAINT {i 2 t two t ii}} + }] + +breakpoint + do_test 6.$tn.2.2 { + set ::conflict_list [list] + sqlite3changeset_apply_v2 -ignorenoop db2 $C xConflict + set ::conflict_list + } [list {*}{ + {DELETE x1 CONSTRAINT {i 2 t two t ii}} + }] +} finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index d92480db0f..81ba738340 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -4870,7 +4870,9 @@ static int sessionConflictHandler( int nBlob = pIter->in.iNext - pIter->in.iCurrent; sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc); return SQLITE_OK; - }else if( p->bIgnoreNoop==0 || op!=SQLITE_DELETE ){ + }else if( p->bIgnoreNoop==0 || op!=SQLITE_DELETE + || eType==SQLITE_CHANGESET_CONFLICT + ){ /* No other row with the new.* primary key. */ res = xConflict(pCtx, eType+1, pIter); if( res==SQLITE_CHANGESET_REPLACE ) rc = SQLITE_MISUSE; diff --git a/manifest b/manifest index da7f75f7be..25cbad0cb9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sbuilds\swithout\sHAVE_FCHMOD\s(e.g.\sWASI),\smake\sthe\schmod()\sof\stemp\sfiles\sa\sno-op,\sanalog\sto\show\slack\sof\sHAVE_FCHOWN\sis\shandled,\sas\sdiscussed\sin\s[forum:98d5158d3fdd7a41\s|\sforum\spost\s98d5158d3f]. -D 2025-08-20T09:43:15.813 +C Fix\sa\sproblem\swith\sSQLITE_CHANGESET_CONFLICT\sconflicts\scaused\sby\sDELETE\striggers\swithin\sa\scall\sto\ssqlite3changset_apply_v2()\swith\sSQLITE_CHANGESETAPPLY_IGNORENOOP\sspecified. +D 2025-08-20T11:21:35.942 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -567,13 +567,13 @@ F ext/session/sessioninvert.test 9018f6a7387ac745084b6374c5e1aa14d648b372e6e1181 F ext/session/sessionmem.test f2a735db84a3e9e19f571033b725b0b2daf847f3f28b1da55a0c1a4e74f1de09 F ext/session/sessionnoact.test 4c7ae5c7d351cb5323bca62b6b095592ad24bd90a6713c178b62ab0063d23e19 F ext/session/sessionnoop.test a9366a36a95ef85f8a3687856ebef46983df399541174cb1ede2ee53b8011bc7 -F ext/session/sessionnoop2.test e0d70f220495f812ea61420bc6aca83f4bfcbc13635dfbe472b818f4d26fc482 +F ext/session/sessionnoop2.test 5beecd3ffcfbc1ef199d3536e91cc3186b438d587531ff334b6b0fc9b7d8ef10 F ext/session/sessionrebase.test 702378bdcb5062f1106e74457beca8797d09c113a81768734a58b197b5b334e2 F ext/session/sessionrowid.test 85187c2f1b38861a5844868126f69f9ec62223a03449a98a80600a44396f7363 F ext/session/sessionsize.test 8fcf4685993c3dbaa46a24183940ab9f5aa9ed0d23e5fb63bfffbdb56134b795 F ext/session/sessionstat1.test 5e718d5888c0c49bbb33a7a4f816366db85f59f6a4f97544a806421b85dc2dec F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc -F ext/session/sqlite3session.c 8c570698b9a81a78f43635aa674c255b2dd8bee580ea5332058cea643c025686 +F ext/session/sqlite3session.c 9205e6e8f389ea44a8118082ce3832374da92284a60e4fb3ea6b1b421f0dbc54 F ext/session/sqlite3session.h b81e8536ce4b83babafd700f4ff67017804b6c1d71df963b30d3972958e7f4a7 F ext/session/test_session.c 8766b5973a6323934cb51248f621c3dc87ad2a98f023c3cc280d79e7d78d36fb F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c @@ -2169,8 +2169,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 78b543f85ac6643f3b69bf1250c6362f00e030f93f460ef7d04902682ef64ee9 -R a71f49d8d9f654e8f455c5338b9ab922 -U stephan -Z 08af4145a8110bad977817d5c75cc90c +P 7d13e8e403ba00d37b950caa359d74452319247495284d252efa6473bad15b64 +R ae093d0946efac31f01b7b9bdaa4b770 +U dan +Z 7b86a84e6c2cd643602bc41c4f1ab398 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 39660e68b9..24d8076ed2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7d13e8e403ba00d37b950caa359d74452319247495284d252efa6473bad15b64 +138e2aab43ac07aaf8c5389105ff6d3e107ff2d35badcb48233664fcb9661471