]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a problem applying changesets that contain multiple UPDATE constraint loops.
authordan <Dan Kennedy>
Mon, 18 May 2026 20:34:56 +0000 (20:34 +0000)
committerdan <Dan Kennedy>
Mon, 18 May 2026 20:34:56 +0000 (20:34 +0000)
FossilOrigin-Name: 8e89aafab1b8fa7d59ac98c39b7f1c1cc23a98ba868a5dac83dee63688786a3f

ext/session/sessionconflict2.test
ext/session/sqlite3session.c
manifest
manifest.uuid

index d6fcde73abdc8700025e14d45866b1aed5b2390c..f0301428d15440b28269c8cd776711983a40d970 100755 (executable)
@@ -20,12 +20,6 @@ ifcapable !session {finish_test; return}
 
 set testprefix sessionconflict2
 
-#db close
-#sqlite3_shutdown
-#test_sqlite3_log log
-#proc log {code msg} { puts "LOG $code $msg" }
-#sqlite3 db test.db
-
 forcedelete test.db2
 sqlite3 db2 test.db2
 
@@ -62,7 +56,184 @@ do_execsql_test -db db2 1.3 {
   3 3 3 1
 }
 
+#--------------------------------------------------------------------------
+reset_db
+db2 close
+forcedelete test.db2
+sqlite3 db2 test.db2
+
+do_test 2.0 {
+  do_common_sql {
+    CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE) WITHOUT ROWID;
+    INSERT INTO t1 VALUES(1, 1, 1);
+    INSERT INTO t1 VALUES(2, 2, 2);
+    INSERT INTO t1 VALUES(3, 3, 3);
+  }
+} {}
+
+do_test 2.1 {
+  do_then_apply_sql {
+    UPDATE t1 SET c=NULL WHERE a=1;
+    UPDATE t1 SET c=1 WHERE a=3;
+    UPDATE t1 SET c=3 WHERE a=1;
+  }
+} {}
+
+do_execsql_test -db db 2.2 {
+  SELECT * FROM t1
+} {
+  1 1 3
+  2 2 2
+  3 3 1
+}
+
+do_execsql_test -db db2 2.3 {
+  SELECT * FROM t1
+} {
+  1 1 3
+  2 2 2
+  3 3 1
+}
+
+#--------------------------------------------------------------------------
+reset_db
+db2 close
+forcedelete test.db2
+sqlite3 db2 test.db2
+
+do_test 3.0 {
+  do_common_sql {
+    CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c UNIQUE);
+    INSERT INTO t1 VALUES(1, 1, 1);
+    INSERT INTO t1 VALUES(2, 2, 2);
+    INSERT INTO t1 VALUES(3, 3, 3);
+  }
+} {}
+
+do_test 3.1 {
+  do_then_apply_sql {
+    UPDATE t1 SET c=NULL WHERE a=1;
+    UPDATE t1 SET c=1 WHERE a=3;
+    UPDATE t1 SET c=3 WHERE a=1;
+  }
+} {}
+
+do_execsql_test -db db 3.2 {
+  SELECT rowid, * FROM t1
+} {
+  1 1 1 3
+  2 2 2 2
+  3 3 3 1
+}
+
+do_execsql_test -db db2 3.3 {
+  SELECT rowid, * FROM t1
+} {
+  1 1 1 3
+  2 2 2 2
+  3 3 3 1
+}
+
+#-------------------------------------------------------------------------
+reset_db
+db2 close
+forcedelete test.db2
+sqlite3 db2 test.db2
+
+set ::conflict_list [list]
+proc xConflict {args} {
+  lappend ::conflict_list $args
+  return "OMIT"
+}
+
+proc do_conflict_test {tn script clist} {
+
+  uplevel [list do_test $tn.1 [subst -nocommands {
+    sqlite3session S db "main"
+    S attach *
+    eval {$script}
+    set ::changeset [S changeset]
+    S delete
+  }] {}]
+
+  uplevel [list do_test $tn.2 {
+    set ::conflict_list [list]
+    sqlite3changeset_apply_v2 db2 $::changeset xConflict
+    set ::conflict_list
+  } [list {*}$clist]]
+}
+
+do_test 4.0 {
+  do_common_sql {
+    CREATE TABLE t1(a INT PRIMARY KEY, b, c UNIQUE, d UNIQUE);
+    WITH s(i) AS (
+      SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10
+    )
+    INSERT INTO t1 SELECT i, i, i, i FROM s;
+  }
+} {}
 
+proc swap {tbl pkcol valcol pk1 pk2} {
+  set val1 [db one "SELECT $valcol FROM $tbl WHERE $pkcol = \$pk1"]
+  set val2 [db one "SELECT $valcol FROM $tbl WHERE $pkcol = \$pk2"]
+
+  db eval "
+    UPDATE $tbl SET $valcol = NULL WHERE $pkcol IN (\$pk1, \$pk2);
+    UPDATE $tbl SET $valcol = \$val2 WHERE $pkcol = \$pk1;
+    UPDATE $tbl SET $valcol = \$val1 WHERE $pkcol = \$pk2;
+  "
+}
+
+do_conflict_test 4.1.1 {
+  swap t1 a c 4 5
+  swap t1 a c 2 3
+  swap t1 a c 8 1
+} {
+}
+
+do_execsql_test -db db 4.1.2 {
+  SELECT a, c FROM t1
+} {
+  1 8 2 3 3 2 4 5 5 4 6 6 7 7 8 1 9 9 10 10
+}
+do_execsql_test -db db2 4.1.3 {
+  SELECT a, c FROM t1
+} {
+  1 8 2 3 3 2 4 5 5 4 6 6 7 7 8 1 9 9 10 10
+}
+
+do_conflict_test 4.2.1 {
+  swap t1 a d 10 9
+  swap t1 a d  8 7
+  swap t1 a d  7 6
+  swap t1 a d  5 4
+  swap t1 a d  4 8
+} {
+}
+
+do_execsql_test -db db 4.2.2 {
+  SELECT a, d FROM t1
+} {
+  1 1  2 2  3 3  4 7  5 4  6 8  7 6  8 5  9 10  10 9
+}
+do_execsql_test -db db2 4.2.3 {
+  SELECT a, d FROM t1
+} {
+  1 1  2 2  3 3  4 7  5 4  6 8  7 6  8 5  9 10  10 9
+}
+
+do_execsql_test -db db2 4.3 {
+  INSERT INTO t1(a, b, c, d) VALUES(11, 11, 11, 11);
+}
+
+do_conflict_test 4.3.1 {
+  swap t1 a c 3 6
+  db eval { UPDATE t1 SET d=11 WHERE a=10; }
+  swap t1 a d 4 8
+} {
+  {UPDATE t1 CONSTRAINT {i 10 {} {} {} {} i 9} {{} {} {} {} {} {} i 11}}
+}
 
 db2 close
 finish_test
+
index e8fc626a3e26b05cca95cf8aacc3b0290419f56b..96de0caafb1ca72224ad90dd92701ec30dd73b2f 100644 (file)
@@ -5506,6 +5506,7 @@ static int sessionRetryConstraints(
         if( pApply->constraints.nBuf>=app.nBuf ){
           break;
         }
+        iSkip = -1;
       }
     }
 
index 8bf4b6321edf984ffb3c42bc798b812e03341ef5..7029ee904eab67c07f9af305f47050b45d5ef2d3 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Update\sthe\ssession\smodule\sso\sthat\sit\scan\sapply\schangesets\scontaining\stwo\sor\smore\sUPDATE\schanges\sthat\sform\sa\sdependency\sloop\s-\sso\sthat\sno\ssingle\sUPDATE\scan\sbe\sapplied\sindependently\swithout\sviolating\sa\sconstraint.
-D 2026-05-18T18:59:06.664
+C Fix\sa\sproblem\sapplying\schangesets\sthat\scontain\smultiple\sUPDATE\sconstraint\sloops.
+D 2026-05-18T20:34:56.095
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -559,7 +559,7 @@ F ext/session/sessionblob.test 87faf667870b72f08e91969abd9f52a383ab7b514506ee194
 F ext/session/sessionchange.test 6618cb1c1338a4b6df173b6ac42d09623fb71269962abf23ebb7617fe9f45a50
 F ext/session/sessionchange2.test 8f59185216882adc8b34bb5ba63887459acf3df58493bcffa12e4d05ab6a6b85
 F ext/session/sessionconflict.test 19e4a53795c4c930bfec49e809311e09b2a9e202d9446e56d7a8b139046a0c07 x
-F ext/session/sessionconflict2.test 9d65dd1b23c6ddd94134260c68ac3a7513683fbcfecc4d32344a416db115efa9 x
+F ext/session/sessionconflict2.test 79e4922450355f5ee3929d53a5d4158d0ed5cec284399eb8f5cb756176fa601b x
 F ext/session/sessiondiff.test e89f7aedcdd89e5ebac3a455224eb553a171e9586fc3e1e6a7b3388d2648ba8d
 F ext/session/sessionfault.test c2b43d01213b389a3f518e90775fca2120812ba51e50444c4066962263e45c11
 F ext/session/sessionfault2.test b0d6a7c1d7398a7e800d84657404909c7d385965ea8576dc79ed344c46fbf41c
@@ -574,7 +574,7 @@ F ext/session/sessionrowid.test 85187c2f1b38861a5844868126f69f9ec62223a03449a98a
 F ext/session/sessionsize.test 8fcf4685993c3dbaa46a24183940ab9f5aa9ed0d23e5fb63bfffbdb56134b795
 F ext/session/sessionstat1.test 5e718d5888c0c49bbb33a7a4f816366db85f59f6a4f97544a806421b85dc2dec
 F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
-F ext/session/sqlite3session.c c29ee85aba67f456aad2abfe8cdfded71f4c5c7e1d741c98938be245cba1727a
+F ext/session/sqlite3session.c b02885cbe7135283b8c908f9d0a4321324090e01d4fc91a5a35e90fec5c8ebcb
 F ext/session/sqlite3session.h 063e7bf7be2fff874456f452a224b5b3013b25682d108933b0351c93a1279b9c
 F ext/session/test_session.c 21524e86610986c8296ad08e71a1af1804b823b5830ed1189623b15ceb886c7c
 F ext/wasm/GNUmakefile 65feef4ec48e62249f90278c4c08a3fe3c69e2461ff560b61c03cd73606e0949
@@ -2206,11 +2206,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
 F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
 F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P ac3a958b0ab7766544bb406aa990668d2235ab26fb68c75ded3f71273d97b18c
-R bc7ae802611a6dcb6a03884dbae18d5f
-T *branch * session-update-loops
-T *sym-session-update-loops *
-T -sym-trunk *
+P 5f8010599fb33fbe1dadc894a679056a5d38040ab4f09772cd59827941e9348b
+R 0e16a12d6b8b38337384a7915987c0d2
 U dan
-Z b8bca31cc23b62b1a53ed4be75c6b16d
+Z c71ece5751b3bebe9c49c58b00d28025
 # Remove this line to create a well-formed Fossil manifest.
index 0b26bbc82c407596e6a40546e4299c0ae3f06c31..6ef08e75951984d934b7383fd5844f3db665d6e5 100644 (file)
@@ -1 +1 @@
-5f8010599fb33fbe1dadc894a679056a5d38040ab4f09772cd59827941e9348b
+8e89aafab1b8fa7d59ac98c39b7f1c1cc23a98ba868a5dac83dee63688786a3f