]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the SQLITE_CHANGESETAPPLY_IGNORENOOP flag, which may be passed to sqlite3changese...
authordan <Dan Kennedy>
Wed, 8 Mar 2023 18:03:04 +0000 (18:03 +0000)
committerdan <Dan Kennedy>
Wed, 8 Mar 2023 18:03:04 +0000 (18:03 +0000)
FossilOrigin-Name: cb023fe28560ce0f8c2fd48042553fcdb9db81eba9552be75165de0d46a2645c

15 files changed:
ext/session/session2.test
ext/session/sessionG.test
ext/session/sessionH.test
ext/session/session_common.tcl
ext/session/sessionat.test
ext/session/sessionbig.test
ext/session/sessionfault.test
ext/session/sessionfault2.test
ext/session/sessionnoop.test
ext/session/sessionstat1.test
ext/session/sqlite3session.c
ext/session/sqlite3session.h
ext/session/test_session.c
manifest
manifest.uuid

index 806687745e5f2c7fd924b5845a9c7b2cccea1efa..207b98740e06eeddadbc95ad27d1fac6b214bbc6 100644 (file)
@@ -191,7 +191,7 @@ do_common_sql {
 }
 
 foreach {tn sql} [string map {%T1% t1 %T2% t2 %T3% t3 %T4% t4} $set_of_tests] {
-  do_then_apply_sql $sql
+  do_then_apply_sql -ignorenoop $sql
   do_test 2.$tn { compare_db db db2 } {}
 }
 
@@ -598,7 +598,7 @@ do_common_sql {
   INSERT INTO t1 SELECT NULL, 0, 0, 0, 0, 0 FROM s
 }
 
-do_then_apply_sql {
+do_then_apply_sql -ignorenoop {
   UPDATE t1 SET                             f=f+1 WHERE a=1;
   UPDATE t1 SET                      e=e+1        WHERE a=2;
   UPDATE t1 SET                      e=e+1, f=f+1 WHERE a=3;
index 58ea17d2eeacc6f290f36963759e6647f898442d..1ebcc926a5f4e26a271b0821aefb4d85893c6864 100644 (file)
@@ -34,7 +34,7 @@ do_test 1.0 {
     INSERT INTO t1 VALUES(2, 'two');
     INSERT INTO t1 VALUES(3, 'three');
   }
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     DELETE FROM t1 WHERE a=1;
     INSERT INTO t1 VALUES(4, 'one');
   }
@@ -42,7 +42,7 @@ do_test 1.0 {
 } {}
 
 do_test 1.1 {
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     DELETE FROM t1 WHERE a=4;
     INSERT INTO t1 VALUES(1, 'one');
   }
@@ -51,7 +51,7 @@ do_test 1.1 {
 
 do_test 1.2 {
   execsql { INSERT INTO t1 VALUES(5, 'five') } db2
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     INSERT INTO t1 VALUES(11, 'eleven');
     INSERT INTO t1 VALUES(12, 'five');
   }
@@ -82,7 +82,7 @@ do_test 2.2.1 {
   # It is not possible to apply the changeset generated by the following
   # SQL, as none of the three updated rows may be updated as part of the
   # first pass.
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     UPDATE t1 SET b=0 WHERE a=1;
     UPDATE t1 SET b=1 WHERE a=2;
     UPDATE t1 SET b=2 WHERE a=3;
@@ -109,7 +109,7 @@ do_test 3.1 {
 } {}
 
 do_test 3.3 {
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     UPDATE t1 SET b=4 WHERE a=3;
     UPDATE t1 SET b=3 WHERE a=2;
     UPDATE t1 SET b=2 WHERE a=1;
@@ -118,7 +118,7 @@ do_test 3.3 {
 } {}
 
 do_test 3.4 {
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     UPDATE t1 SET b=1 WHERE a=1;
     UPDATE t1 SET b=2 WHERE a=2;
     UPDATE t1 SET b=3 WHERE a=3;
@@ -148,7 +148,7 @@ do_test 4.1 {
 } {}
 
 do_test 4.2 {
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     UPDATE t1 SET b=4 WHERE a=3;
     UPDATE t1 SET b=3 WHERE a=2;
     UPDATE t1 SET b=2 WHERE a=1;
@@ -161,7 +161,7 @@ do_test 4.2 {
 } {}
 
 do_test 4.3 {
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     UPDATE t1 SET b=1 WHERE a=1;
     UPDATE t1 SET b=2 WHERE a=2;
     UPDATE t1 SET b=3 WHERE a=3;
@@ -191,7 +191,7 @@ do_execsql_test -db db2 5.0.2 {
 }
 
 do_test 5.1 {
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     INSERT INTO t1 VALUES(1, 2, 3);
     INSERT INTO t2 VALUES(4, 5, 6);
     INSERT INTO t3 VALUES(7, 8, 9);
index 8ba23119c809509d3de9ab6b36faeedba446fa00..e1b12571c694174af5e09a5de18835157a32e867 100644 (file)
@@ -25,7 +25,7 @@ do_test 1.0 {
   do_common_sql {
     CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b));
   }
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     WITH s(i) AS (
       VALUES(1) UNION ALL SELECT i+1 FROM s WHERe i<10000
     )
index c52ac457c0cf1f0cafeb6f1761d54ffd68cb7445..22e427f2be2d2ec5580f0776a3b87006ae272f33 100644 (file)
@@ -112,20 +112,52 @@ proc patchset_from_sql {sql {dbname main}} {
   return $patchset
 }
 
-proc do_then_apply_sql {sql {dbname main}} {
-  proc xConflict args { return "OMIT" }
+# Usage: do_then_apply_sql ?-ignorenoop? SQL ?DBNAME? 
+#
+proc do_then_apply_sql {args} {
+  
+  set bIgnoreNoop 0
+  set a1 [lindex $args 0]
+  if {[string length $a1]>1 && [string first $a1 -ignorenoop]==0} {
+    set bIgnoreNoop 1
+    set args [lrange $args 1 end]
+  }
+
+  if {[llength $args]!=1 && [llength $args]!=2} {
+    error "usage: do_then_apply_sql ?-ignorenoop? SQL ?DBNAME?"
+  }
+
+  set sql [lindex $args 0]
+  if {[llength $args]==1} {
+    set dbname main
+  } else {
+    set dbname [lindex $args 1]
+  }
+
+  set ::n_conflict 0
+  proc xConflict args { incr ::n_conflict ; return "OMIT" }
   set rc [catch {
     sqlite3session S db $dbname
     db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" {
       S attach $name
     }
     db eval $sql
-    sqlite3changeset_apply db2 [S changeset] xConflict
+    set ::changeset [S changeset]
+    sqlite3changeset_apply db2 $::changeset xConflict
   } msg]
 
   catch { S delete }
-
   if {$rc} {error $msg}
+
+  if {$bIgnoreNoop} {
+    set nSave $::n_conflict
+    set ::n_conflict 0
+    proc xConflict args { incr ::n_conflict ; return "OMIT" }
+    sqlite3changeset_apply_v2 -ignorenoop db2 $::changeset xConflict
+    if {$::n_conflict!=$nSave} {
+      error "-ignorenoop problem ($::n_conflict $nSave)..."
+    }
+  }
 }
 
 proc do_iterator_test {tn tbl_list sql res} {
index e3f9e31ed78e6dda6dcce2a9e5fac2e0d3c5c502..e14901e8b505e43c18f2f96140802565101fec90 100644 (file)
@@ -110,7 +110,7 @@ eval [string map [list %WR% $trailing] {
     CREATE TABLE t3(a, b, c DEFAULT 'D', PRIMARY KEY(b)) %WR%;
   }
   do_test $tn.3.2 {
-    do_then_apply_sql {
+    do_then_apply_sql -ignorenoop {
       INSERT INTO t3 VALUES(1, 2);
       INSERT INTO t3 VALUES(3, 4);
       INSERT INTO t3 VALUES(5, 6);
@@ -118,7 +118,7 @@ eval [string map [list %WR% $trailing] {
     db2 eval {SELECT * FROM t3}
   } {1 2 D 3 4 D 5 6 D}
   do_test $tn.3.3 {
-    do_then_apply_sql {
+    do_then_apply_sql -ignorenoop {
       UPDATE t3 SET a=45 WHERE b=4;
       DELETE FROM t3 WHERE a=5;
     };
@@ -253,7 +253,7 @@ eval [string map [list %WR% $trailing] {
     CREATE TABLE t8(a PRIMARY KEY, b, c, d DEFAULT 'D', e DEFAULT 'E');
   }
 
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     INSERT INTO t8 VALUES(1, 2, 3);
     INSERT INTO t8 VALUES(4, 5, 6);
   }
@@ -264,7 +264,7 @@ eval [string map [list %WR% $trailing] {
     SELECT * FROM t8
   } {1 2 3 D E   4 5 6 D E}
 
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     UPDATE t8 SET c=45 WHERE a=4;
   }
   do_execsql_test $tn.7.3.1 {
@@ -282,7 +282,7 @@ eval [string map [list %WR% $trailing] {
   do_execsql_test -db db2 $tn.8.1 {
     CREATE TABLE t9(a PRIMARY KEY, b, c, d, e, f, g, h, i, j, k, l);
   }
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     INSERT INTO t9 VALUES(1, 2, 3, 4, 5, 6, 7, 8);
   }
   do_then_apply_sql {
@@ -291,7 +291,7 @@ eval [string map [list %WR% $trailing] {
   do_execsql_test -db db2 $tn.8.2 {
     SELECT * FROM t9
   } {1 2 3 4 5 6 7 450 {} {} {} {}}
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     UPDATE t9 SET h=NULL
   }
   do_execsql_test -db db2 $tn.8.2 {
index 80ce00a0f7983a751090a6ad31f7fdec7a46af12..462e21f61fca5d043f1c449fcb247435abc9055d 100644 (file)
@@ -43,7 +43,7 @@ do_execsql_test -db db2 1.1 {
 }
 
 do_test 1.2 {
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
     INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
     INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
@@ -71,7 +71,7 @@ do_test 1.3 {
 
 do_test 1.4 {
   set rc [catch {
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
     INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
     INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) );
index be6c4568ce6584bc6da7f221c2fcbcfa05d5aca8..96e966b41dc2d01857cb8d0e785198ecce3a9e4a 100644 (file)
@@ -44,7 +44,7 @@ do_faultsim_test 1.1 -faults oom-* -prep {
   faultsim_restore_and_reopen
   sqlite3 db2 test.db2
 } -body {
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     INSERT INTO t1 VALUES('a string value', 8, 9);
     UPDATE t1 SET c = 10 WHERE a = 1;
     DELETE FROM t1 WHERE a = 4;
index dd00eaa1c83c2f14a288c4bd5030197322dd6272..a2dc39e437f93ffe94d2bf3ccb0b560c7e972b24 100644 (file)
@@ -132,7 +132,7 @@ do_faultsim_test 1.1 -faults oom-* -prep {
   faultsim_restore_and_reopen
   sqlite3 db2 test.db2
 } -body {
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     INSERT INTO sqlite_stat1 VALUES('x', 'y', 45);
     UPDATE sqlite_stat1 SET stat = 123 WHERE tbl='t1' AND idx='i1';
     UPDATE sqlite_stat1 SET stat = 456 WHERE tbl='t2';
index 16c60b7abff36436f3694e5ee3b3f5f2544664b3..5549773440069d847c0fa5f1836ce6678cd8281f 100644 (file)
@@ -1,4 +1,4 @@
-# 2021 Februar 20
+# 2011 March 07
 #
 # The author disclaims copyright to this source code.  In place of
 # a legal notice, here is a blessing:
@@ -20,166 +20,159 @@ ifcapable !session {finish_test; return}
 
 set testprefix sessionnoop
 
-#-------------------------------------------------------------------------
-# Test plan:
-#
-#   1.*: Test that concatenating changesets cannot produce a noop UPDATE.
-#   2.*: Test that rebasing changesets cannot produce a noop UPDATE.
-#   3.*: Test that sqlite3changeset_apply() ignores noop UPDATE changes.
-#
+foreach {tn wo} {
+  1 ""
+  2 " WITHOUT ROWID "
+} {
+  reset_db
+  eval [string map [list %WO% $wo] {
+do_execsql_test $tn.1.0 {
+  CREATE TABLE t1(a PRIMARY KEY, b, c) %WO%;
+  INSERT INTO t1 VALUES('a', 'A', 'AAA');
+  INSERT INTO t1 VALUES('b', 'B', 'BBB');
+  INSERT INTO t1 VALUES('c', 'C', 'CCC');
+  INSERT INTO t1 VALUES('d', 'D', 'DDD');
+  INSERT INTO t1 VALUES('e', 'E', 'EEE');
+}
 
-do_execsql_test 1.0 {
-  CREATE TABLE t1(a PRIMARY KEY, b, c, d);
-  INSERT INTO t1 VALUES(1, 1, 1, 1);
-  INSERT INTO t1 VALUES(2, 2, 2, 2);
-  INSERT INTO t1 VALUES(3, 3, 3, 3);
+forcedelete test.db2
+sqlite3 db2 test.db2
+
+do_execsql_test -db db2 $tn.1.1 {
+  CREATE TABLE t1(a PRIMARY KEY, b, c) %WO%;
+  INSERT INTO t1 VALUES('a', 'A', 'AAA');
+  INSERT INTO t1 VALUES('b', 'B', '123');
+  INSERT INTO t1 VALUES('c', 'C', 'CCC');
+  INSERT INTO t1 VALUES('e', 'E', 'EEE');
+  INSERT INTO t1 VALUES('f', 'F', 'FFF');
 }
 
-proc do_concat_test {tn sql1 sql2 res} {
-  uplevel [list do_test $tn [subst -nocommands {
-    set C1 [changeset_from_sql {$sql1}]
-    set C2 [changeset_from_sql {$sql2}]
-    set C3 [sqlite3changeset_concat [set C1] [set C2]]
-    set got [list]
-    sqlite3session_foreach elem [set C3] { lappend got [set elem] }
-    set got
-  }] [list {*}$res]]
+set C [changeset_from_sql {
+  UPDATE t1 SET c='123' WHERE a='b';
+  DELETE FROM t1 WHERE a='d';
+  INSERT INTO t1 VALUES('f', 'F', 'FFF');
+}]
+
+
+set ::conflict_list [list]
+proc xConflict {args} {
+  lappend ::conflict_list $args
+  return "OMIT"
 }
+do_test $tn.1.2 {
+  sqlite3changeset_apply_v2 db2 $C xConflict
+  set ::conflict_list
+} [list {*}{
+  {UPDATE t1 DATA {t b {} {} t BBB} {{} {} {} {} t 123} {t b t B t 123}}
+  {INSERT t1 CONFLICT {t f t F t FFF} {t f t F t FFF}}
+  {DELETE t1 NOTFOUND {t d t D t DDD}}
+}]
+do_test $tn.1.3 {
+  set ::conflict_list [list]
+  sqlite3changeset_apply_v2 db2 $C xConflict
+  set ::conflict_list
+} [list {*}{
+  {UPDATE t1 DATA {t b {} {} t BBB} {{} {} {} {} t 123} {t b t B t 123}}
+  {INSERT t1 CONFLICT {t f t F t FFF} {t f t F t FFF}}
+  {DELETE t1 NOTFOUND {t d t D t DDD}}
+}]
+
+do_test $tn.1.4 {
+  set ::conflict_list [list]
+  sqlite3changeset_apply_v2 -ignorenoop db2 $C xConflict
+  set ::conflict_list
+} {}
 
-do_concat_test 1.1 {
-  UPDATE t1 SET c=c+1;
-} {
-  UPDATE t1 SET c=c-1;
-} {
+do_execsql_test -db db2 1.5 {
+  UPDATE t1 SET b='G' WHERE a='f';
+  UPDATE t1 SET c='456' WHERE a='b';
 }
 
-#-------------------------------------------------------------------------
+do_test $tn.1.6 {
+  set ::conflict_list [list]
+  sqlite3changeset_apply_v2 -ignorenoop db2 $C xConflict
+  set ::conflict_list
+} [list {*}{
+  {UPDATE t1 DATA {t b {} {} t BBB} {{} {} {} {} t 123} {t b t B t 456}}
+  {INSERT t1 CONFLICT {t f t F t FFF} {t f t G t FFF}}
+}]
+
+db2 close
+
+#--------------------------------------------------------------------------
+
 reset_db
-do_execsql_test 2.0 {
-  CREATE TABLE t1(a PRIMARY KEY, b, c);
-  INSERT INTO t1 VALUES(1, 1, 1);
-  INSERT INTO t1 VALUES(2, 2, 2);
-  INSERT INTO t1 VALUES(3, 3, 3);
+forcedelete test.db2
+sqlite3 db2 test.db2
+do_execsql_test $tn.2.0 {
+  CREATE TABLE t1(a PRIMARY KEY, b) %WO%;
 }
-
-proc do_rebase_test {tn sql_local sql_remote conflict_res expected} {
-  proc xConflict {args} [list return $conflict_res]
-
-  uplevel [list \
-    do_test $tn [subst -nocommands {
-      execsql BEGIN
-        set c_remote [changeset_from_sql {$sql_remote}]
-      execsql ROLLBACK
-
-      execsql BEGIN
-        set c_local [changeset_from_sql {$sql_local}]
-        set base [sqlite3changeset_apply_v2 db [set c_remote] xConflict]
-      execsql ROLLBACK
-
-      sqlite3rebaser_create R
-      R config [set base]
-      set res [list]
-      sqlite3session_foreach elem [R rebase [set c_local]] { 
-        lappend res [set elem] 
-      }
-      R delete
-      set res
-    }] [list {*}$expected]
-  ]
+do_execsql_test -db db2 $tn.2.1 {
+  CREATE TABLE t1(a PRIMARY KEY, b, c DEFAULT 'val') %WO%;
 }
 
-do_rebase_test 2.1 {
-  UPDATE t1 SET c=2 WHERE a=1;              -- local
-} {
-  UPDATE t1 SET c=3 WHERE a=1;              -- remote
-} OMIT {
-  {UPDATE t1 0 X.. {i 1 {} {} i 3} {{} {} {} {} i 2}}
-}
+do_test $tn.2.2 {
+  do_then_apply_sql -ignorenoop {
+    INSERT INTO t1 VALUES(1, 2);
+  }
+  do_then_apply_sql -ignorenoop {
+    UPDATE t1 SET b=2 WHERE a=1
+  }
+} {}
 
-do_rebase_test 2.2 {
-  UPDATE t1 SET c=2 WHERE a=1;              -- local
-} {
-  UPDATE t1 SET c=3 WHERE a=1;              -- remote
-} REPLACE {
-}
 
-do_rebase_test 2.3.1 {
-  UPDATE t1 SET c=4 WHERE a=1;              -- local
-} {
-  UPDATE t1 SET c=4 WHERE a=1               -- remote
-} OMIT {
-  {UPDATE t1 0 X.. {i 1 {} {} i 4} {{} {} {} {} i 4}}
+}]
 }
 
-do_rebase_test 2.3.2 {
-  UPDATE t1 SET c=5 WHERE a=1;              -- local
-} {
-  UPDATE t1 SET c=5 WHERE a=1               -- remote
-} REPLACE {
-}
+db2 close
 
 #-------------------------------------------------------------------------
-#
 reset_db
+forcedelete test.db2
 do_execsql_test 3.0 {
-  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
-  INSERT INTO t1 VALUES(1, 1, 1);
-  INSERT INTO t1 VALUES(2, 2, 2);
-  INSERT INTO t1 VALUES(3, 3, 3);
-  INSERT INTO t1 VALUES(4, 4, 4);
-}
-
-# Arg $pkstr contains one character for each column in the table. An
-# "X" for PK column, or a "." for a non-PK.
-#
-proc mk_tbl_header {name pkstr} {
-  set ret [binary format H2c 54 [string length $pkstr]]
-  foreach i [split $pkstr {}] {
-    if {$i=="X"} {
-      append ret [binary format H2 01]
-    } else {
-      if {$i!="."} {error "bad pkstr: $pkstr ($i)"}
-      append ret [binary format H2 00]
-    }
-  }
-  append ret $name
-  append ret [binary format H2 00]
-  set ret
+  CREATE TABLE xyz(a, b, c, PRIMARY KEY(a, b), UNIQUE(c));
+  ANALYZE;
+  WITH s(i) AS (
+    VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100
+  )
+  INSERT INTO xyz SELECT i, i, i FROM s;
+  VACUUM INTO 'test.db2';
 }
 
-proc mk_update_change {args} {
-  set ret [binary format H2H2 17 00]
-  foreach a $args {
-    if {$a==""} {
-      append ret [binary format H2 00]
-    } else {
-      append ret [binary format H2W 01 $a]
-    }
-  }
-  set ret
-}
+set C [changeset_from_sql { ANALYZE }]
+sqlite3 db2 test.db2
 
-proc xConflict {args} { return "ABORT" }
+set ::conflict_list [list]
+proc xConflict {args} { lappend ::conflict_list $args ; return "OMIT" }
 do_test 3.1 {
-  set    C [mk_tbl_header t1 X..]
-  append C [mk_update_change    1 {} 1   {} {}  500]
-  append C [mk_update_change    2 {} {}  {} {}  {}]
-  append C [mk_update_change    3 3  {}  {} 600 {}]
-  append C [mk_update_change    4 {} {}  {} {}  {}]
+  sqlite3changeset_apply_v2 db2 $C xConflict
+  set ::conflict_list
+} {}
 
-  sqlite3changeset_apply_v2 db $C xConflict
+do_test 3.2 {
+  sqlite3changeset_apply_v2 -ignorenoop db2 $C xConflict
+  set ::conflict_list
 } {}
-do_execsql_test 3.2 {
-  SELECT * FROM t1
-} {
-  1 1 500
-  2 2 2
-  3 600 3
-  4 4 4
-}
 
+do_test 3.3 {
+  sqlite3changeset_apply_v2 db2 $C xConflict
+  set ::conflict_list
+} [list {*}{
+  {INSERT sqlite_stat1 CONFLICT {t xyz t sqlite_autoindex_xyz_1 t {100 1 1}} {t xyz t sqlite_autoindex_xyz_1 t {100 1 1}}} 
+  {INSERT sqlite_stat1 CONFLICT {t xyz t sqlite_autoindex_xyz_2 t {100 1}} {t xyz t sqlite_autoindex_xyz_2 t {100 1}}}
+}]
 
+do_execsql_test -db db2 3.4 {
+  UPDATE sqlite_stat1 SET stat='200 1 1' WHERE idx='sqlite_autoindex_xyz_1';
+}
 
+do_test 3.5 {
+  set ::conflict_list [list]
+  sqlite3changeset_apply_v2 -ignorenoop db2 $C xConflict
+  set ::conflict_list
+} [list {*}{
+  {INSERT sqlite_stat1 CONFLICT {t xyz t sqlite_autoindex_xyz_1 t {100 1 1}} {t xyz t sqlite_autoindex_xyz_1 t {200 1 1}}} 
+}]
 
 
 
index 774899d96b6c03f73991cc603c3844ec1636079a..2757d60440dc1e7de5cb202273402a8fa5ef881b 100644 (file)
@@ -82,7 +82,7 @@ do_test 2.0 {
 } {}
 
 do_test 2.1 {
-  do_then_apply_sql {
+  do_then_apply_sql -ignorenoop {
     WITH s(i) AS (
         SELECT 0 UNION ALL SELECT i+1 FROM s WHERE (i+1)<32
     )
@@ -100,7 +100,7 @@ do_execsql_test -db db2 2.2 {
 }
 
 do_test 2.3 {
-  do_then_apply_sql { DROP INDEX t1c }
+  do_then_apply_sql -ignorenoop { DROP INDEX t1c }
 } {}
 
 do_execsql_test -db db2 2.4 {
@@ -111,7 +111,7 @@ do_execsql_test -db db2 2.4 {
 }
 
 do_test 2.3 {
-  do_then_apply_sql { DROP TABLE t1 }
+  do_then_apply_sql -ignorenoop { DROP TABLE t1 }
 } {}
 
 do_execsql_test -db db2 2.4 {
@@ -153,16 +153,16 @@ do_execsql_test 3.2 {
 } {t1 null 4}
 do_test 3.3 {
   execsql { DELETE FROM sqlite_stat1 }
-  do_then_apply_sql { ANALYZE }
+  do_then_apply_sql -ignorenoop { ANALYZE }
   execsql { SELECT * FROM sqlite_stat1 } db2
 } {t1 null 4}
 do_test 3.4 {
   execsql { INSERT INTO t1 VALUES(5,5,5) }
-  do_then_apply_sql { ANALYZE }
+  do_then_apply_sql -ignorenoop { ANALYZE }
   execsql { SELECT * FROM sqlite_stat1 } db2
 } {t1 null 5}
 do_test 3.5 {
-  do_then_apply_sql { DROP TABLE t1 }
+  do_then_apply_sql -ignorenoop { DROP TABLE t1 }
   execsql { SELECT * FROM sqlite_stat1 } db2
 } {}
 
index a3f28abe9ec8df184b33c0b62142a217a782070c..225d0316a8f17de9fd5ae75c2d53e2f82935fda3 100644 (file)
@@ -2113,9 +2113,10 @@ static void sessionAppendStr(
   int *pRc
 ){
   int nStr = sqlite3Strlen30(zStr);
-  if( 0==sessionBufferGrow(p, nStr, pRc) ){
+  if( 0==sessionBufferGrow(p, nStr+1, pRc) ){
     memcpy(&p->aBuf[p->nBuf], zStr, nStr);
     p->nBuf += nStr;
+    p->aBuf[p->nBuf] = 0x00;
   }
 }
 
@@ -2137,6 +2138,27 @@ static void sessionAppendInteger(
   sessionAppendStr(p, aBuf, pRc);
 }
 
+static void sessionAppendPrintf(
+  SessionBuffer *p,               /* Buffer to append to */
+  int *pRc, 
+  const char *zFmt,
+  ...
+){
+  if( *pRc==SQLITE_OK ){
+    char *zApp = 0;
+    va_list ap;
+    va_start(ap, zFmt);
+    zApp = sqlite3_vmprintf(zFmt, ap);
+    if( zApp==0 ){
+      *pRc = SQLITE_NOMEM;
+    }else{
+      sessionAppendStr(p, zApp, pRc);
+    }
+    va_end(ap);
+    sqlite3_free(zApp);
+  }
+}
+
 /*
 ** This function is a no-op if *pRc is other than SQLITE_OK when it is 
 ** called. Otherwise, append the string zStr enclosed in quotes (") and
@@ -2151,7 +2173,7 @@ static void sessionAppendIdent(
   const char *zStr,               /* String to quote, escape and append */
   int *pRc                        /* IN/OUT: Error code */
 ){
-  int nStr = sqlite3Strlen30(zStr)*2 + 2 + 1;
+  int nStr = sqlite3Strlen30(zStr)*2 + 2 + 2;
   if( 0==sessionBufferGrow(p, nStr, pRc) ){
     char *zOut = (char *)&p->aBuf[p->nBuf];
     const char *zIn = zStr;
@@ -2162,6 +2184,7 @@ static void sessionAppendIdent(
     }
     *zOut++ = '"';
     p->nBuf = (int)((u8 *)zOut - p->aBuf);
+    p->aBuf[p->nBuf] = 0x00;
   }
 }
 
@@ -2386,10 +2409,17 @@ static int sessionAppendDelete(
 ** Formulate and prepare a SELECT statement to retrieve a row from table
 ** zTab in database zDb based on its primary key. i.e.
 **
-**   SELECT * FROM zDb.zTab WHERE pk1 = ? AND pk2 = ? AND ...
+**   SELECT *, <noop-test> FROM zDb.zTab WHERE (pk1, pk2,...) IS (?1, ?2,...)
+**
+** where <noop-test> is: 
+**
+**   1 AND (?A OR ?1 IS <column>) AND ...
+**
+** for each non-pk <column>.
 */
 static int sessionSelectStmt(
   sqlite3 *db,                    /* Database handle */
+  int bIgnoreNoop,
   const char *zDb,                /* Database name */
   const char *zTab,               /* Table name */
   int nCol,                       /* Number of columns in table */
@@ -2399,8 +2429,51 @@ static int sessionSelectStmt(
 ){
   int rc = SQLITE_OK;
   char *zSql = 0;
+  const char *zSep = "";
+  const char *zCols = "*";
   int nSql = -1;
+  int i;
+
+  SessionBuffer nooptest = {0, 0, 0};
+  SessionBuffer pkfield = {0, 0, 0};
+  SessionBuffer pkvar = {0, 0, 0};
+
+  sessionAppendStr(&nooptest, ", 1", &rc);
+
+  if( 0==sqlite3_stricmp("sqlite_stat1", zTab) ){
+    sessionAppendStr(&nooptest, " AND (?6 OR ?3 IS stat)", &rc);
+    sessionAppendStr(&pkfield, "tbl, idx", &rc);
+    sessionAppendStr(&pkvar, 
+        "?1, (CASE WHEN ?2=X'' THEN NULL ELSE ?2 END)", &rc
+    );
+    zCols = "tbl, ?2, stat";
+  }else{
+    for(i=0; i<nCol; i++){
+
+      if( abPK[i] ){
+        sessionAppendStr(&pkfield, zSep, &rc);
+        sessionAppendStr(&pkvar, zSep, &rc);
+        zSep = ", ";
+        sessionAppendIdent(&pkfield, azCol[i], &rc);
+        sessionAppendPrintf(&pkvar, &rc, "?%d", i+1);
+      }else{
+        sessionAppendPrintf(&nooptest, &rc, 
+            " AND (?%d OR ?%d IS %w.%w)", i+1+nCol, i+1, zTab, azCol[i]
+        );
+      }
+    }
+  }
+
+  if( rc==SQLITE_OK ){
+    zSql = sqlite3_mprintf(
+        "SELECT %s%s FROM %Q.%Q WHERE (%s) IS (%s)",
+        zCols, (bIgnoreNoop ? (char*)nooptest.aBuf : ""), 
+        zDb, zTab, (char*)pkfield.aBuf, (char*)pkvar.aBuf
+    );
+    if( zSql==0 ) rc = SQLITE_NOMEM;
+  }
 
+#if 0
   if( 0==sqlite3_stricmp("sqlite_stat1", zTab) ){
     zSql = sqlite3_mprintf(
         "SELECT tbl, ?2, stat FROM %Q.sqlite_stat1 WHERE tbl IS ?1 AND "
@@ -2408,7 +2481,6 @@ static int sessionSelectStmt(
     );
     if( zSql==0 ) rc = SQLITE_NOMEM;
   }else{
-    int i;
     const char *zSep = "";
     SessionBuffer buf = {0, 0, 0};
 
@@ -2429,11 +2501,15 @@ static int sessionSelectStmt(
     zSql = (char*)buf.aBuf;
     nSql = buf.nBuf;
   }
+#endif
 
   if( rc==SQLITE_OK ){
     rc = sqlite3_prepare_v2(db, zSql, nSql, ppStmt, 0);
   }
   sqlite3_free(zSql);
+  sqlite3_free(nooptest.aBuf);
+  sqlite3_free(pkfield.aBuf);
+  sqlite3_free(pkvar.aBuf);
   return rc;
 }
 
@@ -2593,7 +2669,8 @@ static int sessionGenerateChangeset(
       /* Build and compile a statement to execute: */
       if( rc==SQLITE_OK ){
         rc = sessionSelectStmt(
-            db, pSession->zDb, zName, nCol, azCol, abPK, &pSel);
+            db, 0, pSession->zDb, zName, nCol, azCol, abPK, &pSel
+        );
       }
 
       nNoop = buf.nBuf;
@@ -3782,6 +3859,7 @@ struct SessionApplyCtx {
   SessionBuffer rebase;           /* Rebase information (if any) here */
   u8 bRebaseStarted;              /* If table header is already in rebase */
   u8 bRebase;                     /* True to collect rebase information */
+  u8 bIgnoreNoop;                 /* True to ignore no-op conflicts */
 };
 
 /* Number of prepared UPDATE statements to cache. */
@@ -4032,8 +4110,9 @@ static int sessionSelectRow(
   const char *zTab,               /* Table name */
   SessionApplyCtx *p              /* Session changeset-apply context */
 ){
-  return sessionSelectStmt(
-      db, "main", zTab, p->nCol, p->azCol, p->abPK, &p->pSelect);
+  return sessionSelectStmt(db, p->bIgnoreNoop,
+      "main", zTab, p->nCol, p->azCol, p->abPK, &p->pSelect
+  );
 }
 
 /*
@@ -4192,20 +4271,33 @@ static int sessionBindRow(
 */
 static int sessionSeekToRow(
   sqlite3_changeset_iter *pIter,  /* Changeset iterator */
-  u8 *abPK,                       /* Primary key flags array */
-  sqlite3_stmt *pSelect           /* SELECT statement from sessionSelectRow() */
+  SessionApplyCtx *p
 ){
+  sqlite3_stmt *pSelect = p->pSelect;
   int rc;                         /* Return code */
   int nCol;                       /* Number of columns in table */
   int op;                         /* Changset operation (SQLITE_UPDATE etc.) */
   const char *zDummy;             /* Unused */
 
+  sqlite3_clear_bindings(pSelect);
   sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0);
   rc = sessionBindRow(pIter, 
       op==SQLITE_INSERT ? sqlite3changeset_new : sqlite3changeset_old,
-      nCol, abPK, pSelect
+      nCol, p->abPK, pSelect
   );
 
+  if( op!=SQLITE_DELETE && p->bIgnoreNoop ){
+    int ii;
+    for(ii=0; rc==SQLITE_OK && ii<nCol; ii++){
+      if( p->abPK[ii]==0 ){
+        sqlite3_value *pVal = 0;
+        sqlite3changeset_new(pIter, ii, &pVal);
+        sqlite3_bind_int(pSelect, ii+1+nCol, (pVal==0));
+        if( pVal ) rc = sessionBindValue(pSelect, ii+1, pVal);
+      }
+    }
+  }
+
   if( rc==SQLITE_OK ){
     rc = sqlite3_step(pSelect);
     if( rc!=SQLITE_ROW ) rc = sqlite3_reset(pSelect);
@@ -4320,16 +4412,22 @@ static int sessionConflictHandler(
 
   /* Bind the new.* PRIMARY KEY values to the SELECT statement. */
   if( pbReplace ){
-    rc = sessionSeekToRow(pIter, p->abPK, p->pSelect);
+    rc = sessionSeekToRow(pIter, p);
   }else{
     rc = SQLITE_OK;
   }
 
   if( rc==SQLITE_ROW ){
     /* There exists another row with the new.* primary key. */
-    pIter->pConflict = p->pSelect;
-    res = xConflict(pCtx, eType, pIter);
-    pIter->pConflict = 0;
+    if( p->bIgnoreNoop 
+     && sqlite3_column_int(p->pSelect, sqlite3_column_count(p->pSelect)-1)
+    ){
+      res = SQLITE_CHANGESET_OMIT;
+    }else{
+      pIter->pConflict = p->pSelect;
+      res = xConflict(pCtx, eType, pIter);
+      pIter->pConflict = 0;
+    }
     rc = sqlite3_reset(p->pSelect);
   }else if( rc==SQLITE_OK ){
     if( p->bDeferConstraints && eType==SQLITE_CHANGESET_CONFLICT ){
@@ -4437,7 +4535,7 @@ static int sessionApplyOneOp(
 
     sqlite3_step(p->pDelete);
     rc = sqlite3_reset(p->pDelete);
-    if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){
+    if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 && p->bIgnoreNoop==0 ){
       rc = sessionConflictHandler(
           SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry
       );
@@ -4494,7 +4592,7 @@ static int sessionApplyOneOp(
       /* Check if there is a conflicting row. For sqlite_stat1, this needs
       ** to be done using a SELECT, as there is no PRIMARY KEY in the 
       ** database schema to throw an exception if a duplicate is inserted.  */
-      rc = sessionSeekToRow(pIter, p->abPK, p->pSelect);
+      rc = sessionSeekToRow(pIter, p);
       if( rc==SQLITE_ROW ){
         rc = SQLITE_CONSTRAINT;
         sqlite3_reset(p->pSelect);
@@ -4671,6 +4769,7 @@ static int sessionChangesetApply(
   memset(&sApply, 0, sizeof(sApply));
   sApply.bRebase = (ppRebase && pnRebase);
   sApply.bInvertConstraints = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
+  sApply.bIgnoreNoop = !!(flags & SQLITE_CHANGESETAPPLY_IGNORENOOP);
   sqlite3_mutex_enter(sqlite3_db_mutex(db));
   if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
     rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
index 10d0133901622d690dd2312111116dd418ba9704..f3a98d2ecd6c5cde0d7a8f02b5e8e10170b304f9 100644 (file)
@@ -1243,9 +1243,23 @@ int sqlite3changeset_apply_v2(
 **   Invert the changeset before applying it. This is equivalent to inverting
 **   a changeset using sqlite3changeset_invert() before applying it. It is
 **   an error to specify this flag with a patchset.
+**
+** <dt>SQLITE_CHANGESETAPPLY_IGNORENOOP <dd>
+**   Do not invoke the conflict handler callback for any changes that
+**   would not actually modify the database even if they were applied.
+**   Specifically, this means that the conflict handler is not invoked
+**   for:
+**    <ul>
+**    <li>a delete change if the row being deleted cannot be found, 
+**    <li>an update change if the modified fields are already set to 
+**        their new values in the conflicting row, or
+**    <li>an insert change if all fields of the conflicting row match
+**        the row being inserted.
+**    </ul>
 */
 #define SQLITE_CHANGESETAPPLY_NOSAVEPOINT   0x0001
 #define SQLITE_CHANGESETAPPLY_INVERT        0x0002
+#define SQLITE_CHANGESETAPPLY_IGNORENOOP    0x0004
 
 /* 
 ** CAPI3REF: Constants Passed To The Conflict Handler
index 242e0fb0fbc42e801199ad23970bb3a3714988fd..f10afe03f657a288a6e53ec2ba5fb9b1e60d4dbd 100644 (file)
@@ -793,32 +793,31 @@ static int SQLITE_TCLAPI testSqlite3changesetApply(
   memset(&sStr, 0, sizeof(sStr));
   sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR);
 
-  /* Check for the -nosavepoint flag */
+  /* Check for the -nosavepoint, -invert or -ignorenoop switches */
   if( bV2 ){
-    if( objc>1 ){
+    while( objc>1 ){
       const char *z1 = Tcl_GetString(objv[1]);
       int n = strlen(z1);
       if( n>1 && n<=12 && 0==sqlite3_strnicmp("-nosavepoint", z1, n) ){
         flags |= SQLITE_CHANGESETAPPLY_NOSAVEPOINT;
-        objc--;
-        objv++;
       }
-    }
-    if( objc>1 ){
-      const char *z1 = Tcl_GetString(objv[1]);
-      int n = strlen(z1);
-      if( n>1 && n<=7 && 0==sqlite3_strnicmp("-invert", z1, n) ){
+      else if( n>2 && n<=7 && 0==sqlite3_strnicmp("-invert", z1, n) ){
         flags |= SQLITE_CHANGESETAPPLY_INVERT;
-        objc--;
-        objv++;
       }
+      else if( n>2 && n<=11 && 0==sqlite3_strnicmp("-ignorenoop", z1, n) ){
+        flags |= SQLITE_CHANGESETAPPLY_IGNORENOOP;
+      }else{
+        break;
+      }
+      objc--;
+      objv++;
     }
   }
 
   if( objc!=4 && objc!=5 ){
     const char *zMsg;
     if( bV2 ){
-      zMsg = "?-nosavepoint? ?-inverse? "
+      zMsg = "?-nosavepoint? ?-inverse? ?-ignorenoop? "
         "DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?";
     }else{
       zMsg = "DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?";
index acf807f0bfdfda52398573f93c6a98f43986f1b6..57192a45d746ebccbbc177b7ebeedf8ccb09965f 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Small\sperformance\simprovement\sin\sthe\sOP_MakeRecord\sopcode.
-D 2023-03-08T17:09:32.272
+C Add\sthe\sSQLITE_CHANGESETAPPLY_IGNORENOOP\sflag,\swhich\smay\sbe\spassed\sto\ssqlite3changeset_apply_v2()\sto\shave\sit\signore\schanges\sthat\swould\sbe\sno-ops\sif\sapplied\sto\sthe\sdatabase\s(e.g.\sdeleting\sa\srow\sthat\shas\salready\sbeen\sdeleted),\sinstead\sof\sconsidering\sthem\sconflicts.
+D 2023-03-08T18:03:04.122
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -432,7 +432,7 @@ F ext/session/changeset.c 7a1e6a14c7e92d36ca177e92e88b5281acd709f3b726298dc34ec0
 F ext/session/changesetfuzz.c 227076ab0ae4447d742c01ee88a564da6478bbf26b65108bf8fac9cd8b0b24aa
 F ext/session/changesetfuzz1.test 2e1b90d888fbf0eea5e1bd2f1e527a48cc85f8e0ff75df1ec4e320b21f580b3a
 F ext/session/session1.test e94f764fbfb672147c0ef7026b195988133b371dc8cf9e52423eba6cad69717e
-F ext/session/session2.test 7f53d755d921e0baf815c4258348e0ed460dfd8a772351bca5ad3ccbb1dc786e
+F ext/session/session2.test ee83bb973b9ce17ccce4db931cdcdae65eb40bbb22089b2fe6aa4f6be3b9303f
 F ext/session/session3.test ce9ce3dfa489473987f899e9f6a0f2db9bde3479
 F ext/session/session4.test 6778997065b44d99c51ff9cece047ff9244a32856b328735ae27ddef68979c40
 F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169
@@ -445,25 +445,25 @@ F ext/session/sessionC.test f8a5508bc059ae646e5ec9bdbca66ad24bc92fe99fda5790ac57
 F ext/session/sessionD.test 4f91d0ca8afc4c3969c72c9f0b5ea9527e21de29039937d0d973f821e8470724
 F ext/session/sessionE.test b2010949c9d7415306f64e3c2072ddabc4b8250c98478d3c0c4d064bce83111d
 F ext/session/sessionF.test d37ed800881e742c208df443537bf29aa49fd56eac520d0f0c6df3e6320f3401
-F ext/session/sessionG.test 3828b944cd1285f4379340fd36f8b64c464fc84df6ff3ccbc95578fd87140b9c
-F ext/session/sessionH.test b17afdbd3b8f17e9bab91e235acf167cf35485db2ab2df0ea8893fbb914741a4
-F ext/session/session_common.tcl f613174665456b2d916ae8df3e5735092a1c1712f36f46840172e9a01e8cc53e
+F ext/session/sessionG.test 3efe388282d641b65485b5462e67851002cd91a282dc95b685d085eb8efdad0a
+F ext/session/sessionH.test 71bbff6b1abb2c4ac62b84dee53273c37e0b21e5fde3aed80929403e091ef859
+F ext/session/session_common.tcl db0dda567c75950604072251744e9a6ad5795a3009963c44eb8510f23a8cda64
 F ext/session/session_speed_test.c dcf0ef58d76b70c8fbd9eab3be77cf9deb8bc1638fed8be518b62d6cbdef88b3
-F ext/session/sessionat.test 46fd847f6ed194ebb7ebef9fe68b2e2ec88d9c2383a6846cddc5604b35f1d4ae
-F ext/session/sessionbig.test 890ade19e3f80f3d3a3e83821ff79c5e2af906a67ecb5450879f0015cadf101e
+F ext/session/sessionat.test 00c8badb35e43a2f12a716d2734a44d614ff62361979b6b85419035bc04b45ee
+F ext/session/sessionbig.test 47c381e7acfabeef17d98519a3080d69151723354d220afa2053852182ca7adf
 F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec
-F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
-F ext/session/sessionfault2.test dd593f80b6b4786f7adfe83c5939620bc505559770cc181332da26f29cddd7bb
+F ext/session/sessionfault.test 573bf027fb870d57bd4e7cf50822a3e4b17b2b923407438747aaa918dec57a09
+F ext/session/sessionfault2.test b0d6a7c1d7398a7e800d84657404909c7d385965ea8576dc79ed344c46fbf41c
 F ext/session/sessioninvert.test 04075517a9497a80d39c495ba6b44f3982c7371129b89e2c52219819bc105a25
 F ext/session/sessionmem.test f2a735db84a3e9e19f571033b725b0b2daf847f3f28b1da55a0c1a4e74f1de09
-F ext/session/sessionnoop.test a9366a36a95ef85f8a3687856ebef46983df399541174cb1ede2ee53b8011bc7
+F ext/session/sessionnoop.test 5c9a882219e54711c98dccd2fd81392f189a59325e4fb5d8ed25e33a0c2f0ba2
 F ext/session/sessionrebase.test ccfa716b23bd1d3b03217ee58cfd90c78d4b99f53e6a9a2f05e82363b9142810
 F ext/session/sessionsize.test 6f644aff31c7f1e4871e9ff3542766e18da68fc7e587b83a347ea9820a002dd8
-F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c2666091b54450a68fb5
+F ext/session/sessionstat1.test b039e38e2ba83767b464baf39b297cc0b1cc6f3292255cb467ea7e12d0d0280c
 F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
-F ext/session/sqlite3session.c 13bdc093416cd284d4075328dd8599eb59bcedc23a21d561a15d78805c5866bf
-F ext/session/sqlite3session.h 0907de79bc13a2e3af30a6dc29acc60792a3eaf7d33d44cf52500d0f3c2b2171
-F ext/session/test_session.c 2de472b4d7e62e85ca1992094612725e2450a77dbf7523db64de94197812462e
+F ext/session/sqlite3session.c 1795263b72c1a17e48e95a131a69543af3fa31aa8e81271c7c5cb0911f063604
+F ext/session/sqlite3session.h c367c3043dbb57f69cca35258ebbeadb24e8738980b1a1ae1e281c1b0fac3989
+F ext/session/test_session.c b55a669a2150eb7c491b8b42c69a3eed9bc895cf5fea371a2c813b9618f72163
 F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
 F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
@@ -2049,8 +2049,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 6d5b5896261c62a7e130b47416ee8c25793859a2afcb1646c257600537a5b71b
-R 1b5d34199b6078f6cf9502fa50e8d5f3
-U drh
-Z 1c424b0c5c8b9aa32605259b67546e86
+P ca89daef0fcf6cb04aa6fa90dd333d6f2474bf3f458c833d9cd5bd8e59f2a04a
+R b858992430ed0de53c8f23b82b0d78e8
+U dan
+Z efdd331472cbc1f3fc97c7776e84ccdd
 # Remove this line to create a well-formed Fossil manifest.
index da2cfe9570d09140ac026e85d16ebc41b085716d..e6427110e8ee694628b779b90534a324e31539ef 100644 (file)
@@ -1 +1 @@
-ca89daef0fcf6cb04aa6fa90dd333d6f2474bf3f458c833d9cd5bd8e59f2a04a
\ No newline at end of file
+cb023fe28560ce0f8c2fd48042553fcdb9db81eba9552be75165de0d46a2645c
\ No newline at end of file