Add the SQLITE_CHANGESETAPPLY_IGNORENOOP flag, which may be passed to sqlite3changeset_apply_v2() to have it ignore changes that would be no-ops if applied to the database (e.g. deleting a row that has already been deleted), instead of considering them conflicts.
FossilOrigin-Name: cb023fe28560ce0f8c2fd48042553fcdb9db81eba9552be75165de0d46a2645c
This commit is contained in:
parent
7ba63831f8
commit
975f2062da
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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} {
|
||||
|
@ -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 {
|
||||
|
@ -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) );
|
||||
|
@ -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;
|
||||
|
@ -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';
|
||||
|
@ -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.
|
||||
#
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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]]
|
||||
}
|
||||
|
||||
do_concat_test 1.1 {
|
||||
UPDATE t1 SET c=c+1;
|
||||
} {
|
||||
UPDATE t1 SET c=c-1;
|
||||
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');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
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 -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_rebase_test {tn sql_local sql_remote conflict_res expected} {
|
||||
proc xConflict {args} [list return $conflict_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');
|
||||
}]
|
||||
|
||||
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]
|
||||
]
|
||||
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_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_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 {
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
proc xConflict {args} { return "ABORT" }
|
||||
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 db $C xConflict
|
||||
do_test $tn.1.4 {
|
||||
set ::conflict_list [list]
|
||||
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_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
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
do_execsql_test $tn.2.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b) %WO%;
|
||||
}
|
||||
do_execsql_test -db db2 $tn.2.1 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c DEFAULT 'val') %WO%;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
} {}
|
||||
|
||||
|
||||
}]
|
||||
}
|
||||
|
||||
db2 close
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
do_execsql_test 3.0 {
|
||||
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';
|
||||
}
|
||||
|
||||
set C [changeset_from_sql { ANALYZE }]
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
set ::conflict_list [list]
|
||||
proc xConflict {args} { lappend ::conflict_list $args ; return "OMIT" }
|
||||
do_test 3.1 {
|
||||
sqlite3changeset_apply_v2 db2 $C xConflict
|
||||
set ::conflict_list
|
||||
} {}
|
||||
|
||||
do_test 3.2 {
|
||||
sqlite3changeset_apply_v2 -ignorenoop db2 $C xConflict
|
||||
set ::conflict_list
|
||||
} {}
|
||||
|
||||
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}}}
|
||||
}]
|
||||
|
||||
|
||||
|
||||
|
@ -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
|
||||
} {}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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?";
|
||||
|
38
manifest
38
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.
|
||||
|
@ -1 +1 @@
|
||||
ca89daef0fcf6cb04aa6fa90dd333d6f2474bf3f458c833d9cd5bd8e59f2a04a
|
||||
cb023fe28560ce0f8c2fd48042553fcdb9db81eba9552be75165de0d46a2645c
|
Loading…
Reference in New Issue
Block a user