From abae0c4f1d3b9ce7a9d6342b61ec000117df1d63 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 15 Oct 2014 20:02:21 +0000 Subject: [PATCH] Fix a problem causing sqlite3changeset_concat() to fail to detect attempts to concatenate patchsets which changesets. FossilOrigin-Name: 236704a9d1551a50a55bd6e0b6473191a7a7dd21 --- ext/session/sessionC.test | 190 +++++++++++++++++++++++++++++++++++ ext/session/sqlite3session.c | 6 ++ manifest | 13 +-- manifest.uuid | 2 +- 4 files changed, 204 insertions(+), 7 deletions(-) create mode 100644 ext/session/sessionC.test diff --git a/ext/session/sessionC.test b/ext/session/sessionC.test new file mode 100644 index 0000000000..81cc53f5a6 --- /dev/null +++ b/ext/session/sessionC.test @@ -0,0 +1,190 @@ +# 2014 August 16 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl +ifcapable !session {finish_test; return} + +set testprefix sessionC + +#------------------------------------------------------------------------- +# Test the outcome of a DELETE operation made as part of applying a +# changeset failing with SQLITE_CONSTRAINT. This may happen if an +# ON DELETE RESTRICT foreign key action is triggered, or if a trigger +# program raises a constraint somehow. +# +do_execsql_test 1.0 { + PRAGMA foreign_keys = 1; + + CREATE TABLE p(a PRIMARY KEY, b, c); + CREATE TABLE c(d PRIMARY KEY, e REFERENCES p ON DELETE RESTRICT); + + INSERT INTO p VALUES('one', 1, 1); + INSERT INTO p VALUES('two', 2, 2); + INSERT INTO p VALUES('three', 3, 3); + + INSERT INTO c VALUES(1, 'one'); + INSERT INTO c VALUES(3, 'three'); +} + +do_test 1.1 { + execsql BEGIN + set C [changeset_from_sql { + INSERT INTO c VALUES(4, 'one'); + DELETE FROM p WHERE a='two'; + }] + execsql ROLLBACK + execsql { + INSERT INTO c VALUES(2, 'two'); + } +} {} + +do_test 1.2.1 { + proc xConflict {args} { return "ABORT" } + catch { sqlite3changeset_apply db $C xConflict } msg + set msg +} {SQLITE_ABORT} +do_execsql_test 1.2.2 { SELECT * FROM c } {1 one 3 three 2 two} + +do_test 1.3.1 { + proc xConflict {args} { return "OMIT" } + catch { sqlite3changeset_apply db $C xConflict } msg + set msg +} {} +do_execsql_test 1.3.2 { SELECT * FROM c } {1 one 3 three 2 two 4 one} +do_execsql_test 1.3.3 { + SELECT * FROM p; +} {one 1 1 two 2 2 three 3 3} + + +#------------------------------------------------------------------------- +# Test that concatenating a changeset with a patchset does not work. +# Any attempt to do so returns SQLITE_ERROR. +# +reset_db +do_execsql_test 2.0 { + CREATE TABLE x1(t, v PRIMARY KEY); + INSERT INTO x1 VALUES(12, 55); + INSERT INTO x1 VALUES(55, 14); +} + +do_test 2.1 { + execsql BEGIN + + sqlite3session S1 db main + S1 attach * + execsql { + UPDATE x1 SET t=13 WHERE v=55; + INSERT INTO x1 VALUES(99, 123); + } + set patchset [S1 patchset] + S1 delete + + sqlite3session S1 db main + S1 attach * + execsql { + UPDATE x1 SET t=56 WHERE v=14; + INSERT INTO x1 VALUES(22, 998); + } + set changeset [S1 changeset] + S1 delete + + execsql ROLLBACK +} {} + +do_test 2.2 { + set rc [catch { sqlite3changeset_concat $patchset $changeset } msg] + list $rc $msg +} {1 SQLITE_ERROR} + +do_test 2.3 { + set rc [catch { sqlite3changeset_concat $changeset $patchset } msg] + list $rc $msg +} {1 SQLITE_ERROR} + +do_test 2.4 { + set rc [catch { sqlite3changeset_concat {} $patchset } msg] + list $rc $msg +} [list 0 $patchset] + +do_test 2.5 { + set rc [catch { sqlite3changeset_concat $patchset {} } msg] + list $rc $msg +} [list 0 $patchset] + +do_test 2.6 { + set rc [catch { sqlite3changeset_concat {} $changeset } msg] + list $rc $msg +} [list 0 $changeset] + +do_test 2.7 { + set rc [catch { sqlite3changeset_concat $changeset {} } msg] + list $rc $msg +} [list 0 $changeset] + +do_test 2.8 { + set rc [catch { sqlite3changeset_concat {} {} } msg] + list $rc $msg +} [list 0 {}] + + +#------------------------------------------------------------------------- +# Test that the xFilter argument to sqlite3changeset_apply() works. +# +reset_db +do_execsql_test 3.0 { + CREATE TABLE t1(a PRIMARY KEY, b); + CREATE TABLE t2(a PRIMARY KEY, b); + CREATE TABLE t3(a PRIMARY KEY, b); +} +do_test 3.1 { + execsql BEGIN + set changeset [changeset_from_sql { + INSERT INTO t1 VALUES(1, 1); + INSERT INTO t2 VALUES(2, 2); + INSERT INTO t3 VALUES(3, 3); + }] + execsql ROLLBACK +} {} +do_test 3.2 { + proc xFilter {zName} { + if {$zName == "t1"} { return 1 } + return 0 + } + sqlite3changeset_apply db $changeset noop xFilter + execsql { + SELECT * FROM t1; + SELECT * FROM t2; + SELECT * FROM t3; + } +} {1 1} +do_test 3.3 { + proc xFilter {zName} { + if {$zName == "t3"} { return 1 } + return 0 + } + sqlite3changeset_apply db $changeset noop xFilter + execsql { + SELECT * FROM t1; + SELECT * FROM t2; + SELECT * FROM t3; + } +} {1 1 3 3} + + + +finish_test + diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index fe7d6e5a21..f861bd1ec6 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -3911,12 +3911,18 @@ int sessionChangesetConcat( assert( xOutput==0 || (ppOut==0 && pnOut==0) ); + assert( pLeft->zTab==0 && pRight->zTab==0 ); rc = sessionChangesetToHash(pLeft, &pList); + assert( pLeft->zTab || pList==0 ); if( rc==SQLITE_OK ){ rc = sessionChangesetToHash(pRight, &pList); } bPatch = pLeft->bPatchset || pRight->bPatchset; + if( pLeft->zTab && pRight->zTab && pLeft->bPatchset!=pRight->bPatchset ){ + rc = SQLITE_ERROR; + } + /* Create the serialized output changeset based on the contents of the ** hash tables attached to the SessionTable objects in list pList. */ diff --git a/manifest b/manifest index 9b98ed7c5f..193e5f6c38 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\slatest\strunk\schanges\swith\sthis\sbranch. -D 2014-10-15T19:37:13.299 +C Fix\sa\sproblem\scausing\ssqlite3changeset_concat()\sto\sfail\sto\sdetect\sattempts\sto\sconcatenate\spatchsets\swhich\schangesets. +D 2014-10-15T20:02:21.265 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -156,9 +156,10 @@ F ext/session/session8.test 8e194b3f655d861ca36de5d4de53f702751bab3b F ext/session/session9.test 5409d90d8141881d08285ed1c2c0d8d10fb92069 F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f F ext/session/sessionB.test 06961b7c3641151f5d23088250ecad132501113c +F ext/session/sessionC.test 3982f8577b0744c5ce3aaef7cfeb5bd903f17fe4 F ext/session/session_common.tcl 9de0451b6a47218fc16b9ed8876b6238a0a3d88d F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc -F ext/session/sqlite3session.c 67b8aee718cf34e267f4040d9b945a7a6407b0b2 +F ext/session/sqlite3session.c 838050c4c217d2843e4705b14be25d8f0457f155 F ext/session/sqlite3session.h 16608d29879a0ed3c6be6b7fb18dcdb5c707aaef F ext/session/test_session.c a28352e99bc6a83b94e4cce99a7bf25c73d6d489 F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 @@ -1221,7 +1222,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 83d4114f2aa404e670ced33511183baacd813a01 3c1e70f4d55bc009ed9ed4cf6d756d7061985851 -R 573bb7e03bcfc05e0f889e571f4f3aa7 +P 1b2824f1d11ac336779372e322aecfb36fb2a31d +R fa664b8794125d09d3da5d2babd6e792 U dan -Z d7531a3919881ed86fbddd665aff411c +Z 8d94920cff847cf3f9fcffe7f6436f08 diff --git a/manifest.uuid b/manifest.uuid index 1d5dadfa49..4a7ff9ad2f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1b2824f1d11ac336779372e322aecfb36fb2a31d \ No newline at end of file +236704a9d1551a50a55bd6e0b6473191a7a7dd21 \ No newline at end of file