From bafad06139a14a7deefc836af52e22605abc6f25 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 12 Oct 2018 15:01:56 +0000 Subject: [PATCH 1/7] Test case modifications to support SEE. FossilOrigin-Name: 02b6f8f2778c371130c512e980c3db07c7e76dcf7dd92a878b86e4b6a47ca307 --- manifest | 17 ++++++------- manifest.uuid | 2 +- test/dbstatus.test | 4 +-- test/pragma3.test | 6 ++++- test/shared.test | 62 ++++++++++++++++++++++++---------------------- 5 files changed, 48 insertions(+), 43 deletions(-) diff --git a/manifest b/manifest index ac92d94aaf..2ee3c8fa1d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\stextkey\sand\stextrekey\spragmas. -D 2018-10-11T18:41:50.384 +C Test\scase\smodifications\sto\ssupport\sSEE. +D 2018-10-12T15:01:56.030 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -770,7 +770,7 @@ F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373 F test/date2.test 74c234bece1b016e94dd4ef9c8cc7a199a8806c0e2291cab7ba64bace6350b10 F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e F test/dbpage.test dbf50a4d361f9e45a979432c727506065113124478a7d2db12074fa655e65d6c -F test/dbstatus.test c15fa97f743dac7ce996814c84b56317e138895ee15ce27f15b608aa6924c90a +F test/dbstatus.test cd83aa623b8aab477269bc94cf8aa90c1e195a144561dd04a1620770aaa8524e F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d F test/delete.test 31832b0c45ecb51a54348c68db173be462985901e6ed7f403d6d7a8f70ab4ef0 @@ -1175,7 +1175,7 @@ F test/permutations.test 8749e292c8f7e98072049543da8c0fe60e1625f0a9f490686230609 F test/pg_common.tcl 301ac19c1a52fd55166d26db929b3b89165c634d52b5f8ad76ea8cb06960db30 F test/pragma.test 7c8cfc328a1717a95663cf8edb06c52ddfeaf97bb0aee69ae7457132e8d39e7d F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f -F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed +F test/pragma3.test 8300aa9c63cff1027006ca34bf413a148abbd6dcd471fa9a1ded322fe18c0df9 F test/pragma4.test 3046501bee2f652dc2a4f9c87781e2741361d6864439c8381aba6c3b774b335c F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983 F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8 @@ -1255,7 +1255,7 @@ F test/server1.test c2b00864514a68a0e6fd518659dc95d0050307a357a08969872bef027d78 F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb F test/sessionfuzz.c b0fcdcf757451957e17396a3af5171f1fdf9b2babc81da9fa35675df46c4729a -F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746 +F test/shared.test 1826673eb5eb745fb91a3bdac99a7737057742ae38dcb0fe076a384d6727578b F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879 F test/shared3.test ab693f9b6e156b8bfb2a0ad94f29fe69602a5d38 F test/shared4.test c75f476804e76e26bf6fa0e7b421fb0ca7d07558 @@ -1771,8 +1771,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1916d2912a4ef5c251853de3c9d66417e20f0c0fc8ddfbc84c131dfd798439f6 -Q +f829099d2558011d2f19ed3e91778b97e4ce0bdaa4a7cd6b0009f705554398ca -R 63af1cda40897d849945c1a22dbd668a +P f03164d45450cd7ff2162999aa9e51eec7fb5e7cab1fa83d876b544f8f841097 +R b06a0e84dfe3f0b011ce56cc2f8b5cd1 U drh -Z 865f15d326c847ade3537f91a0382191 +Z f26fa73bb00e67aa8b5d34053794de3a diff --git a/manifest.uuid b/manifest.uuid index 54e36d8a4f..2ce3280c9c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f03164d45450cd7ff2162999aa9e51eec7fb5e7cab1fa83d876b544f8f841097 \ No newline at end of file +02b6f8f2778c371130c512e980c3db07c7e76dcf7dd92a878b86e4b6a47ca307 \ No newline at end of file diff --git a/test/dbstatus.test b/test/dbstatus.test index 57b91cda1a..564b9c5966 100644 --- a/test/dbstatus.test +++ b/test/dbstatus.test @@ -379,9 +379,9 @@ foreach ::lookaside_buffer_size {0 64 120} { # The following tests focus on DBSTATUS_CACHE_USED_SHARED # ifcapable shared_cache { - if {[permutation]=="memsys3" + if {([permutation]=="memsys3" || [permutation]=="memsys5" - || $::tcl_platform(os)=="Linux"} { + || $::tcl_platform(os)=="Linux") && ![sqlite3 -has-codec]} { proc do_cacheused_test {tn db res} { set cu [sqlite3_db_status $db SQLITE_DBSTATUS_CACHE_USED 0] set pcu [sqlite3_db_status $db SQLITE_DBSTATUS_CACHE_USED_SHARED 0] diff --git a/test/pragma3.test b/test/pragma3.test index 8a4f4f9d84..eebbcbb9c6 100644 --- a/test/pragma3.test +++ b/test/pragma3.test @@ -15,7 +15,11 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -do_not_use_codec + +if {[sqlite3 -has-codec]} { + finish_test + return +} do_execsql_test pragma3-100 { PRAGMA data_version; diff --git a/test/shared.test b/test/shared.test index 4eab476582..589df4d631 100644 --- a/test/shared.test +++ b/test/shared.test @@ -1145,38 +1145,40 @@ do_test shared-$av-16.8 { # Shared cache on named memory databases attached to readonly connections. # -do_test shared-$av-16.8.1 { +if {![sqlite3 -has-codec]} { + do_test shared-$av-16.8.1 { + db1 close + db2 close + + sqlite3 db test1.db + db eval { + CREATE TABLE yy(a, b); + INSERT INTO yy VALUES(77, 88); + } + db close + + sqlite3 db1 test1.db -uri 1 -readonly 1 + sqlite3 db2 test2.db -uri 1 + + db1 eval { + ATTACH 'file:mem?mode=memory&cache=shared' AS shared; + CREATE TABLE shared.xx(a, b); + INSERT INTO xx VALUES(55, 66); + } + db2 eval { + ATTACH 'file:mem?mode=memory&cache=shared' AS shared; + SELECT * FROM xx; + } + } {55 66} + + do_test shared-$av-16.8.2 { db1 eval { SELECT * FROM yy } } {77 88} + do_test shared-$av-16.8.3 { + list [catch {db1 eval { INSERT INTO yy VALUES(1, 2) }} msg] $msg + } {1 {attempt to write a readonly database}} + db1 close db2 close - - sqlite3 db test1.db - db eval { - CREATE TABLE yy(a, b); - INSERT INTO yy VALUES(77, 88); - } - db close - - sqlite3 db1 test1.db -uri 1 -readonly 1 - sqlite3 db2 test2.db -uri 1 - - db1 eval { - ATTACH 'file:mem?mode=memory&cache=shared' AS shared; - CREATE TABLE shared.xx(a, b); - INSERT INTO xx VALUES(55, 66); - } - db2 eval { - ATTACH 'file:mem?mode=memory&cache=shared' AS shared; - SELECT * FROM xx; - } -} {55 66} - -do_test shared-$av-16.8.2 { db1 eval { SELECT * FROM yy } } {77 88} -do_test shared-$av-16.8.3 { - list [catch {db1 eval { INSERT INTO yy VALUES(1, 2) }} msg] $msg -} {1 {attempt to write a readonly database}} - -db1 close -db2 close +} } ;# end of autovacuum on/off loop From 44748f27a6c966b7ceef693e1fbc4bd089e73866 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 18 Oct 2018 14:59:21 +0000 Subject: [PATCH 2/7] Add the SQLITE_CHANGESETAPPLY_INVERT flag to sessions. For inverting and applying a changeset in a single step. FossilOrigin-Name: d4b6406e7f5ba06ac73ab9fdef57232b2459e0af12420ed946ebed6aef46f0b1 --- ext/session/session_common.tcl | 17 +++++ ext/session/sessioninvert.test | 120 +++++++++++++++++++++++++++++++++ ext/session/sqlite3session.c | 35 ++++++---- ext/session/sqlite3session.h | 6 ++ ext/session/test_session.c | 28 +++++--- manifest | 21 +++--- manifest.uuid | 2 +- 7 files changed, 198 insertions(+), 31 deletions(-) create mode 100644 ext/session/sessioninvert.test diff --git a/ext/session/session_common.tcl b/ext/session/session_common.tcl index 543b970327..ceffdad4ba 100644 --- a/ext/session/session_common.tcl +++ b/ext/session/session_common.tcl @@ -95,6 +95,23 @@ proc changeset_from_sql {sql {dbname main}} { return $changeset } +proc patchset_from_sql {sql {dbname main}} { + set rc [catch { + sqlite3session S db $dbname + db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" { + S attach $name + } + db eval $sql + S patchset + } patchset] + catch { S delete } + + if {$rc} { + error $patchset + } + return $patchset +} + proc do_then_apply_sql {sql {dbname main}} { proc xConflict args { return "OMIT" } set rc [catch { diff --git a/ext/session/sessioninvert.test b/ext/session/sessioninvert.test new file mode 100644 index 0000000000..52260af215 --- /dev/null +++ b/ext/session/sessioninvert.test @@ -0,0 +1,120 @@ +# 2018 October 18 +# +# 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. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. +# + +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 sessioninvert + +proc do_invert_test {tn sql} { + + forcecopy test.db test.db2 + sqlite3 db2 test.db2 + + set C [changeset_from_sql $sql] + + forcecopy test.db test.db3 + sqlite3 db3 test.db3 + uplevel [list do_test $tn.1 [list compare_db db db3] {}] + + set I [sqlite3changeset_invert $C] + sqlite3changeset_apply db $I {} + uplevel [list do_test $tn.2 [list compare_db db db2] {}] + + sqlite3changeset_apply_v2 -invert db3 $C {} + uplevel [list do_test $tn.3 [list compare_db db db3] {}] + + catch { db2 close } + catch { db3 close } +} + +do_execsql_test 1.0 { + CREATE TABLE t1(a PRIMARY KEY, b, c); + CREATE TABLE t2(d, e, f, PRIMARY KEY(e, f)); + + INSERT INTO t1 VALUES(1, 'one', 'i'); + INSERT INTO t1 VALUES(2, 'two', 'ii'); + INSERT INTO t1 VALUES(3, 'three', 'iii'); + INSERT INTO t1 VALUES(4, 'four', 'iv'); + INSERT INTO t1 VALUES(5, 'five', 'v'); + INSERT INTO t1 VALUES(6, 'six', 'vi'); + + INSERT INTO t2 SELECT * FROM t1; +} + +do_invert_test 1.1 { + INSERT INTO t1 VALUES(7, 'seven', 'vii'); +} + +do_invert_test 1.2 { + DELETE FROM t1 WHERE a<4; +} + +do_invert_test 1.2 { + UPDATE t1 SET c=5; +} + +do_invert_test 1.3 { + UPDATE t1 SET b = a+1 WHERE a%2; + DELETE FROM t2; + INSERT INTO t1 VALUES(10, 'ten', NULL); +} + +do_invert_test 1.4 { + UPDATE t2 SET d = d-1; +} + +do_execsql_test 2.0 { + ANALYZE; + PRAGMA writable_schema = 1; + DROP TABLE IF EXISTS sqlite_stat4; + SELECT * FROM sqlite_stat1; +} { + t2 sqlite_autoindex_t2_1 {6 1 1} + t1 sqlite_autoindex_t1_1 {6 1} +} + +do_invert_test 2.1 { + INSERT INTO sqlite_stat1 VALUES('t3', 'idx2', '1 2 3'); +} + +do_invert_test 2.2 { + DELETE FROM sqlite_stat1; +} + +do_invert_test 2.3 { + UPDATE sqlite_stat1 SET stat = 'hello world'; +} + +do_test 3.0 { + forcecopy test.db test.db2 + sqlite3 db2 test.db2 + set P [patchset_from_sql { + INSERT INTO t2 VALUES(1, 2, 3); + DELETE FROM t2 WHERE d = 3; + }] + + list [catch { sqlite3changeset_apply_v2 -invert db2 $P {} } msg] $msg +} {1 SQLITE_CORRUPT} + +do_test 3.1 { + sqlite3changeset_apply_v2 db2 $P {} + compare_db db db2 +} {} + + +finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index abbf16dc75..20810ee4f1 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -87,6 +87,7 @@ struct sqlite3_changeset_iter { SessionInput in; /* Input buffer or stream */ SessionBuffer tblhdr; /* Buffer to hold apValue/zTab/abPK/ */ int bPatchset; /* True if this is a patchset */ + int bInvert; /* True to invert changeset */ int rc; /* Iterator error code */ sqlite3_stmt *pConflict; /* Points to conflicting row, if any */ char *zTab; /* Current table */ @@ -2540,7 +2541,8 @@ static int sessionChangesetStart( int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn, int nChangeset, /* Size of buffer pChangeset in bytes */ - void *pChangeset /* Pointer to buffer containing changeset */ + void *pChangeset, /* Pointer to buffer containing changeset */ + int bInvert /* True to invert changeset */ ){ sqlite3_changeset_iter *pRet; /* Iterator to return */ int nByte; /* Number of bytes to allocate for iterator */ @@ -2560,6 +2562,7 @@ static int sessionChangesetStart( pRet->in.xInput = xInput; pRet->in.pIn = pIn; pRet->in.bEof = (xInput ? 0 : 1); + pRet->bInvert = bInvert; /* Populate the output variable and return success. */ *pp = pRet; @@ -2574,7 +2577,7 @@ int sqlite3changeset_start( int nChangeset, /* Size of buffer pChangeset in bytes */ void *pChangeset /* Pointer to buffer containing changeset */ ){ - return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset); + return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0); } /* @@ -2585,7 +2588,7 @@ int sqlite3changeset_start_strm( int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ){ - return sessionChangesetStart(pp, xInput, pIn, 0, 0); + return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0); } /* @@ -2964,10 +2967,10 @@ static int sessionChangesetNext( op = p->in.aData[p->in.iNext++]; } - if( p->zTab==0 ){ + if( p->zTab==0 || (p->bPatchset && p->bInvert) ){ /* The first record in the changeset is not a table header. Must be a ** corrupt changeset. */ - assert( p->in.iNext==1 ); + assert( p->in.iNext==1 || p->zTab ); return (p->rc = SQLITE_CORRUPT_BKPT); } @@ -2992,33 +2995,39 @@ static int sessionChangesetNext( *paRec = &p->in.aData[p->in.iNext]; p->in.iNext += *pnRec; }else{ + sqlite3_value **apOld = (p->bInvert ? &p->apValue[p->nCol] : p->apValue); + sqlite3_value **apNew = (p->bInvert ? p->apValue : &p->apValue[p->nCol]); /* If this is an UPDATE or DELETE, read the old.* record. */ if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){ u8 *abPK = p->bPatchset ? p->abPK : 0; - p->rc = sessionReadRecord(&p->in, p->nCol, abPK, p->apValue); + p->rc = sessionReadRecord(&p->in, p->nCol, abPK, apOld); if( p->rc!=SQLITE_OK ) return p->rc; } /* If this is an INSERT or UPDATE, read the new.* record. */ if( p->op!=SQLITE_DELETE ){ - p->rc = sessionReadRecord(&p->in, p->nCol, 0, &p->apValue[p->nCol]); + p->rc = sessionReadRecord(&p->in, p->nCol, 0, apNew); if( p->rc!=SQLITE_OK ) return p->rc; } - if( p->bPatchset && p->op==SQLITE_UPDATE ){ + if( (p->bPatchset || p->bInvert) && p->op==SQLITE_UPDATE ){ /* If this is an UPDATE that is part of a patchset, then all PK and ** modified fields are present in the new.* record. The old.* record ** is currently completely empty. This block shifts the PK fields from ** new.* to old.*, to accommodate the code that reads these arrays. */ for(i=0; inCol; i++){ - assert( p->apValue[i]==0 ); + assert( p->bPatchset==0 || p->apValue[i]==0 ); if( p->abPK[i] ){ + assert( p->apValue[i]==0 ); p->apValue[i] = p->apValue[i+p->nCol]; if( p->apValue[i]==0 ) return (p->rc = SQLITE_CORRUPT_BKPT); p->apValue[i+p->nCol] = 0; } } + }else if( p->bInvert ){ + if( p->op==SQLITE_INSERT ) p->op = SQLITE_DELETE; + else if( p->op==SQLITE_DELETE ) p->op = SQLITE_INSERT; } } @@ -4182,7 +4191,7 @@ static int sessionRetryConstraints( SessionBuffer cons = pApply->constraints; memset(&pApply->constraints, 0, sizeof(SessionBuffer)); - rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf); + rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf, 0); if( rc==SQLITE_OK ){ int nByte = 2*pApply->nCol*sizeof(sqlite3_value*); int rc2; @@ -4436,7 +4445,8 @@ int sqlite3changeset_apply_v2( int flags ){ sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ - int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); + int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); + int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset,bInverse); if( rc==SQLITE_OK ){ rc = sessionChangesetApply( db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags @@ -4493,7 +4503,8 @@ int sqlite3changeset_apply_v2_strm( int flags ){ sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ - int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); + int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); + int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse); if( rc==SQLITE_OK ){ rc = sessionChangesetApply( db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index a3def5f1df..a9fbed94ef 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -1151,8 +1151,14 @@ int sqlite3changeset_apply_v2( ** causes the sessions module to omit this savepoint. In this case, if the ** caller has an open transaction or savepoint when apply_v2() is called, ** it may revert the partially applied changeset by rolling it back. +** +**
SQLITE_CHANGESETAPPLY_INVERT
+** 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. */ #define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 +#define SQLITE_CHANGESETAPPLY_INVERT 0x0002 /* ** CAPI3REF: Constants Passed To The Conflict Handler diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 3b6c24fd11..6eba2114c7 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -737,20 +737,32 @@ static int SQLITE_TCLAPI testSqlite3changesetApply( sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR); /* Check for the -nosavepoint flag */ - if( bV2 && 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( bV2 ){ + if( 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) ){ + flags |= SQLITE_CHANGESETAPPLY_INVERT; + objc--; + objv++; + } } } if( objc!=4 && objc!=5 ){ const char *zMsg; if( bV2 ){ - zMsg = "?-nosavepoint? DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?"; + zMsg = "?-nosavepoint? ?-inverse? " + "DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?"; }else{ zMsg = "DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?"; } diff --git a/manifest b/manifest index 2ee3c8fa1d..5231fee516 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Test\scase\smodifications\sto\ssupport\sSEE. -D 2018-10-12T15:01:56.030 +C Add\sthe\sSQLITE_CHANGESETAPPLY_INVERT\sflag\sto\ssessions.\sFor\sinverting\sand\sapplying\sa\schangeset\sin\sa\ssingle\sstep. +D 2018-10-18T14:59:21.849 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -407,18 +407,19 @@ F ext/session/sessionE.test 0a616c4ad8fd2c05f23217ebb6212ef80b7fef30f5f086a6633a F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce F ext/session/sessionG.test 3edde849c4071078d92bd682c836186f6e4e5a3fb6bcf3fc1de1a7caa5e4427d F ext/session/sessionH.test 332b60e4c2e0a680105e11936201cabe378216f307e2747803cea56fa7d9ebae -F ext/session/session_common.tcl ee925e0d233677e45e395fb1f559b84068ce7baa8aa1034441739d3e87ee249c +F ext/session/session_common.tcl 29ec9910aca1e996ca1c8531b8cecabf96eb576aa53de65a8ff03d848b9a2a8b F ext/session/session_speed_test.c edc1f96fd5e0e4b16eb03e2a73041013d59e8723 F ext/session/sessionat.test efe88965e74ff1bc2af9c310b28358c02d420c1fb2705cc7a28f0c1cc142c3ec F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7 F ext/session/sessionfault2.test 555a8504de03d59b369ef20209585da5aeb2671dedabc4584e9ffe6269689185 +F ext/session/sessioninvert.test d4d8a89990de35e8e56d4d14d14bc7f191aa6f4c2b3731c7ce0fe64b640d29d3 F ext/session/sessionrebase.test 4e1bcfd26fd8ed8ac571746f56cceeb45184f4d65490ea0d405227cfc8a9cba8 F ext/session/sessionstat1.test 41cd97c2e48619a41cdf8ae749e1b25f34719de638689221aa43971be693bf4e F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc -F ext/session/sqlite3session.c ba76c7f01d4c71ab4d134cfda0ba43faae04bff01b8e81d1279a6101c706e3b5 -F ext/session/sqlite3session.h c01820d5b6e73e86d88008f4d1c1c7dfb83422963018292b864028a0400ceccf -F ext/session/test_session.c dba36c6c0153b22501112d3e8882b5c946cf617c955153b6712bd2f8ba1428c0 +F ext/session/sqlite3session.c db0eb1bdadedf9905076fbff66ab7979d92a5d8649f09f39d9268c0d035aeeba +F ext/session/sqlite3session.h 1b0b2bd69ae4cba5fd5fee050ef79707d45a1a3eed41077a92d14556fdcc1f6e +F ext/session/test_session.c 9447482597c7569e49b3db152a300920a4b634d5de86508a94e4338df99b3fda F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e629edbe2648 @@ -1771,7 +1772,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f03164d45450cd7ff2162999aa9e51eec7fb5e7cab1fa83d876b544f8f841097 -R b06a0e84dfe3f0b011ce56cc2f8b5cd1 -U drh -Z f26fa73bb00e67aa8b5d34053794de3a +P 02b6f8f2778c371130c512e980c3db07c7e76dcf7dd92a878b86e4b6a47ca307 +R af6e82cd2e535125553a7eab8caf31bb +U dan +Z 5cdef990913d6faf4879f9cb06bcd872 diff --git a/manifest.uuid b/manifest.uuid index 2ce3280c9c..7f89b9f2dc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -02b6f8f2778c371130c512e980c3db07c7e76dcf7dd92a878b86e4b6a47ca307 \ No newline at end of file +d4b6406e7f5ba06ac73ab9fdef57232b2459e0af12420ed946ebed6aef46f0b1 \ No newline at end of file From 9c18ef09a57a4c0244cd41942e088c73526f03bb Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 18 Oct 2018 15:17:18 +0000 Subject: [PATCH 3/7] Take steps to avoid a potential integer overflow in sessionBufferGrow(). FossilOrigin-Name: f7affa2e708d1b4c7c47157bcb18e9f79611ca45a93ebc88de6dc96f84a677e7 --- ext/session/sqlite3session.c | 6 +++--- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 20810ee4f1..a1ca9a78b1 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1794,12 +1794,12 @@ int sqlite3session_attach( static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){ if( *pRc==SQLITE_OK && p->nAlloc-p->nBufnAlloc ? p->nAlloc : 128; + i64 nNew = p->nAlloc ? p->nAlloc : 128; do { nNew = nNew*2; - }while( nNew<(p->nBuf+nByte) ); + }while( (nNew-p->nBuf)aBuf, nNew); + aNew = (u8 *)sqlite3_realloc64(p->aBuf, nNew); if( 0==aNew ){ *pRc = SQLITE_NOMEM; }else{ diff --git a/manifest b/manifest index 5231fee516..748230c555 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_CHANGESETAPPLY_INVERT\sflag\sto\ssessions.\sFor\sinverting\sand\sapplying\sa\schangeset\sin\sa\ssingle\sstep. -D 2018-10-18T14:59:21.849 +C Take\ssteps\sto\savoid\sa\spotential\sinteger\soverflow\sin\ssessionBufferGrow(). +D 2018-10-18T15:17:18.844 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -417,7 +417,7 @@ F ext/session/sessioninvert.test d4d8a89990de35e8e56d4d14d14bc7f191aa6f4c2b3731c F ext/session/sessionrebase.test 4e1bcfd26fd8ed8ac571746f56cceeb45184f4d65490ea0d405227cfc8a9cba8 F ext/session/sessionstat1.test 41cd97c2e48619a41cdf8ae749e1b25f34719de638689221aa43971be693bf4e F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc -F ext/session/sqlite3session.c db0eb1bdadedf9905076fbff66ab7979d92a5d8649f09f39d9268c0d035aeeba +F ext/session/sqlite3session.c 7c1875f0c124a1bd18beb95ef0fd7ce288e553c883d2f258b921d4612995a258 F ext/session/sqlite3session.h 1b0b2bd69ae4cba5fd5fee050ef79707d45a1a3eed41077a92d14556fdcc1f6e F ext/session/test_session.c 9447482597c7569e49b3db152a300920a4b634d5de86508a94e4338df99b3fda F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3 @@ -1772,7 +1772,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 02b6f8f2778c371130c512e980c3db07c7e76dcf7dd92a878b86e4b6a47ca307 -R af6e82cd2e535125553a7eab8caf31bb +P d4b6406e7f5ba06ac73ab9fdef57232b2459e0af12420ed946ebed6aef46f0b1 +R e7a7201238f957af096a10fc5c94b75d U dan -Z 5cdef990913d6faf4879f9cb06bcd872 +Z 58cb59871e256ea172e37001653f6319 diff --git a/manifest.uuid b/manifest.uuid index 7f89b9f2dc..f1588fde60 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d4b6406e7f5ba06ac73ab9fdef57232b2459e0af12420ed946ebed6aef46f0b1 \ No newline at end of file +f7affa2e708d1b4c7c47157bcb18e9f79611ca45a93ebc88de6dc96f84a677e7 \ No newline at end of file From 46de0728802703082967d4c563d12a2b5d154e57 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 20 Oct 2018 13:48:09 +0000 Subject: [PATCH 4/7] Add the sqlite3changeset_start_v2() - a new version of _start() that accepts a flags parameter - and a streaming equivalent to the sessions module. Also add the SQLITE_CHANGESETSTART_INVERT flag, used with start_v2() to invert a changeset while iterating through it. FossilOrigin-Name: cbedcb9aaefdfe00453efbdf0eac6c15e1f53bbe8fff2e7d534a5adf23be04f5 --- ext/session/sessioninvert.test | 51 ++++++++++++++++++++++++++++++---- ext/session/sqlite3session.c | 18 ++++++++++++ ext/session/sqlite3session.h | 34 ++++++++++++++++++++++- ext/session/test_session.c | 49 ++++++++++++++++++++++++-------- manifest | 18 ++++++------ manifest.uuid | 2 +- 6 files changed, 143 insertions(+), 29 deletions(-) diff --git a/ext/session/sessioninvert.test b/ext/session/sessioninvert.test index 52260af215..49205f6b26 100644 --- a/ext/session/sessioninvert.test +++ b/ext/session/sessioninvert.test @@ -20,7 +20,13 @@ ifcapable !session {finish_test; return} set testprefix sessioninvert -proc do_invert_test {tn sql} { +proc iter_invert {C} { + set x [list] + sqlite3session_foreach -invert c $C { lappend x $c } + set x +} + +proc do_invert_test {tn sql {iter {}}} { forcecopy test.db test.db2 sqlite3 db2 test.db2 @@ -38,6 +44,10 @@ proc do_invert_test {tn sql} { sqlite3changeset_apply_v2 -invert db3 $C {} uplevel [list do_test $tn.3 [list compare_db db db3] {}] + if {$iter!=""} { + uplevel [list do_test $tn.4 [list iter_invert $C] [list {*}$iter]] + } + catch { db2 close } catch { db3 close } } @@ -58,24 +68,44 @@ do_execsql_test 1.0 { do_invert_test 1.1 { INSERT INTO t1 VALUES(7, 'seven', 'vii'); +} { + {DELETE t1 0 X.. {i 7 t seven t vii} {}} } do_invert_test 1.2 { DELETE FROM t1 WHERE a<4; -} - -do_invert_test 1.2 { - UPDATE t1 SET c=5; +} { + {INSERT t1 0 X.. {} {i 1 t one t i}} + {INSERT t1 0 X.. {} {i 2 t two t ii}} + {INSERT t1 0 X.. {} {i 3 t three t iii}} } do_invert_test 1.3 { + UPDATE t1 SET c=5; +} { + {UPDATE t1 0 X.. {i 1 {} {} i 5} {{} {} {} {} t i}} + {UPDATE t1 0 X.. {i 2 {} {} i 5} {{} {} {} {} t ii}} + {UPDATE t1 0 X.. {i 3 {} {} i 5} {{} {} {} {} t iii}} + {UPDATE t1 0 X.. {i 4 {} {} i 5} {{} {} {} {} t iv}} + {UPDATE t1 0 X.. {i 5 {} {} i 5} {{} {} {} {} t v}} + {UPDATE t1 0 X.. {i 6 {} {} i 5} {{} {} {} {} t vi}} +} + +do_invert_test 1.4 { UPDATE t1 SET b = a+1 WHERE a%2; DELETE FROM t2; INSERT INTO t1 VALUES(10, 'ten', NULL); } -do_invert_test 1.4 { +do_invert_test 1.5 { UPDATE t2 SET d = d-1; +} { + {UPDATE t2 0 .XX {i 2 t three t iii} {i 3 {} {} {} {}}} + {UPDATE t2 0 .XX {i 1 t two t ii} {i 2 {} {} {} {}}} + {UPDATE t2 0 .XX {i 5 t six t vi} {i 6 {} {} {} {}}} + {UPDATE t2 0 .XX {i 3 t four t iv} {i 4 {} {} {} {}}} + {UPDATE t2 0 .XX {i 0 t one t i} {i 1 {} {} {} {}}} + {UPDATE t2 0 .XX {i 4 t five t v} {i 5 {} {} {} {}}} } do_execsql_test 2.0 { @@ -90,10 +120,15 @@ do_execsql_test 2.0 { do_invert_test 2.1 { INSERT INTO sqlite_stat1 VALUES('t3', 'idx2', '1 2 3'); +} { + {DELETE sqlite_stat1 0 XX. {t t3 t idx2 t {1 2 3}} {}} } do_invert_test 2.2 { DELETE FROM sqlite_stat1; +} { + {INSERT sqlite_stat1 0 XX. {} {t t1 t sqlite_autoindex_t1_1 t {6 1}}} + {INSERT sqlite_stat1 0 XX. {} {t t2 t sqlite_autoindex_t2_1 t {6 1 1}}} } do_invert_test 2.3 { @@ -112,6 +147,10 @@ do_test 3.0 { } {1 SQLITE_CORRUPT} do_test 3.1 { + list [catch { sqlite3session_foreach -invert db2 $P {} } msg] $msg +} {1 SQLITE_CORRUPT} + +do_test 3.2 { sqlite3changeset_apply_v2 db2 $P {} compare_db db db2 } {} diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index a1ca9a78b1..1a7f003eb6 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -2579,6 +2579,15 @@ int sqlite3changeset_start( ){ return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0); } +int sqlite3changeset_start_v2( + sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ + int nChangeset, /* Size of buffer pChangeset in bytes */ + void *pChangeset, /* Pointer to buffer containing changeset */ + int flags +){ + int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT); + return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, bInvert); +} /* ** Streaming version of sqlite3changeset_start(). @@ -2590,6 +2599,15 @@ int sqlite3changeset_start_strm( ){ return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0); } +int sqlite3changeset_start_v2_strm( + sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int flags +){ + int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT); + return sessionChangesetStart(pp, xInput, pIn, 0, 0, bInvert); +} /* ** If the SessionInput object passed as the only argument is a streaming diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index a9fbed94ef..b9303635e7 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -473,12 +473,38 @@ int sqlite3session_isempty(sqlite3_session *pSession); ** consecutively. There is no chance that the iterator will visit a change ** the applies to table X, then one for table Y, and then later on visit ** another change for table X. +** +** The behavior of sqlite3changeset_start_v2() and its streaming equivalent +** may be modified by passing a combination of +** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter. +** +** Note that the sqlite3changeset_start_v2() API is still experimental +** and therefore subject to change. */ int sqlite3changeset_start( sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ int nChangeset, /* Size of changeset blob in bytes */ void *pChangeset /* Pointer to blob containing changeset */ ); +int sqlite3changeset_start_v2( + sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ + int nChangeset, /* Size of changeset blob in bytes */ + void *pChangeset, /* Pointer to blob containing changeset */ + int flags /* SESSION_CHANGESETSTART_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3changeset_start_v2 +** +** The following flags may passed via the 4th parameter to +** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]: +** +**
SQLITE_CHANGESETAPPLY_INVERT
+** Invert the changeset while iterating through 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. +*/ +#define SQLITE_CHANGESETSTART_INVERT 0x0002 /* @@ -1133,7 +1159,7 @@ int sqlite3changeset_apply_v2( ), void *pCtx, /* First argument passed to xConflict */ void **ppRebase, int *pnRebase, /* OUT: Rebase data */ - int flags /* Combination of SESSION_APPLY_* flags */ + int flags /* SESSION_CHANGESETAPPLY_* flags */ ); /* @@ -1552,6 +1578,12 @@ int sqlite3changeset_start_strm( int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); +int sqlite3changeset_start_v2_strm( + sqlite3_changeset_iter **pp, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int flags +); int sqlite3session_changeset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 6eba2114c7..016050fdba 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -981,31 +981,56 @@ static int SQLITE_TCLAPI test_sqlite3session_foreach( Tcl_Obj *pCS; Tcl_Obj *pScript; int isCheckNext = 0; + int isInvert = 0; TestStreamInput sStr; memset(&sStr, 0, sizeof(sStr)); - if( objc>1 ){ + while( objc>1 ){ char *zOpt = Tcl_GetString(objv[1]); - isCheckNext = (strcmp(zOpt, "-next")==0); + int nOpt = strlen(zOpt); + if( zOpt[0]!='-' ) break; + if( nOpt<=7 && 0==sqlite3_strnicmp(zOpt, "-invert", nOpt) ){ + isInvert = 1; + }else + if( nOpt<=5 && 0==sqlite3_strnicmp(zOpt, "-next", nOpt) ){ + isCheckNext = 1; + }else{ + break; + } + objv++; + objc--; } - if( objc!=4+isCheckNext ){ - Tcl_WrongNumArgs(interp, 1, objv, "?-next? VARNAME CHANGESET SCRIPT"); + if( objc!=4 ){ + Tcl_WrongNumArgs( + interp, 1, objv, "?-next? ?-invert? VARNAME CHANGESET SCRIPT"); return TCL_ERROR; } - pVarname = objv[1+isCheckNext]; - pCS = objv[2+isCheckNext]; - pScript = objv[3+isCheckNext]; + pVarname = objv[1]; + pCS = objv[2]; + pScript = objv[3]; pChangeset = (void *)Tcl_GetByteArrayFromObj(pCS, &nChangeset); sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR); - if( sStr.nStream==0 ){ - rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); + if( isInvert ){ + int f = SQLITE_CHANGESETSTART_INVERT; + if( sStr.nStream==0 ){ + rc = sqlite3changeset_start_v2(&pIter, nChangeset, pChangeset, f); + }else{ + void *pCtx = (void*)&sStr; + sStr.aData = (unsigned char*)pChangeset; + sStr.nData = nChangeset; + rc = sqlite3changeset_start_v2_strm(&pIter, testStreamInput, pCtx, f); + } }else{ - sStr.aData = (unsigned char*)pChangeset; - sStr.nData = nChangeset; - rc = sqlite3changeset_start_strm(&pIter, testStreamInput, (void*)&sStr); + if( sStr.nStream==0 ){ + rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); + }else{ + sStr.aData = (unsigned char*)pChangeset; + sStr.nData = nChangeset; + rc = sqlite3changeset_start_strm(&pIter, testStreamInput, (void*)&sStr); + } } if( rc!=SQLITE_OK ){ return test_session_error(interp, rc, 0); diff --git a/manifest b/manifest index 748230c555..2cea732c3d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Take\ssteps\sto\savoid\sa\spotential\sinteger\soverflow\sin\ssessionBufferGrow(). -D 2018-10-18T15:17:18.844 +C Add\sthe\ssqlite3changeset_start_v2()\s-\sa\snew\sversion\sof\s_start()\sthat\saccepts\sa\sflags\sparameter\s-\sand\sa\sstreaming\sequivalent\sto\sthe\ssessions\smodule.\sAlso\sadd\sthe\sSQLITE_CHANGESETSTART_INVERT\sflag,\sused\swith\sstart_v2()\sto\sinvert\sa\schangeset\swhile\siterating\sthrough\sit. +D 2018-10-20T13:48:09.884 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -413,13 +413,13 @@ F ext/session/sessionat.test efe88965e74ff1bc2af9c310b28358c02d420c1fb2705cc7a28 F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7 F ext/session/sessionfault2.test 555a8504de03d59b369ef20209585da5aeb2671dedabc4584e9ffe6269689185 -F ext/session/sessioninvert.test d4d8a89990de35e8e56d4d14d14bc7f191aa6f4c2b3731c7ce0fe64b640d29d3 +F ext/session/sessioninvert.test ae1a003a9ab1f8d64227dbb5c3a4c97e65b561b01e7b2953cf48683fb2724169 F ext/session/sessionrebase.test 4e1bcfd26fd8ed8ac571746f56cceeb45184f4d65490ea0d405227cfc8a9cba8 F ext/session/sessionstat1.test 41cd97c2e48619a41cdf8ae749e1b25f34719de638689221aa43971be693bf4e F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc -F ext/session/sqlite3session.c 7c1875f0c124a1bd18beb95ef0fd7ce288e553c883d2f258b921d4612995a258 -F ext/session/sqlite3session.h 1b0b2bd69ae4cba5fd5fee050ef79707d45a1a3eed41077a92d14556fdcc1f6e -F ext/session/test_session.c 9447482597c7569e49b3db152a300920a4b634d5de86508a94e4338df99b3fda +F ext/session/sqlite3session.c 7b9ae0d7f3f89551c893ad5beafe831df1c097623f6abc983dad7b6dbca726cb +F ext/session/sqlite3session.h 11f229ec3f123da40c31500b01a2f6807185293d9173a5e0aa5be42ad70ab85d +F ext/session/test_session.c 4699405b2afcf6833c11358cdb9da50f8f5d2b7123f44b3e2cef1cfb88c9fa39 F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e629edbe2648 @@ -1772,7 +1772,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d4b6406e7f5ba06ac73ab9fdef57232b2459e0af12420ed946ebed6aef46f0b1 -R e7a7201238f957af096a10fc5c94b75d +P f7affa2e708d1b4c7c47157bcb18e9f79611ca45a93ebc88de6dc96f84a677e7 +R 3605ff60956926e38b591288ff5e2c64 U dan -Z 58cb59871e256ea172e37001653f6319 +Z 32299de6da54da0b9ad3507fdc1f1f73 diff --git a/manifest.uuid b/manifest.uuid index f1588fde60..a6502f7411 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f7affa2e708d1b4c7c47157bcb18e9f79611ca45a93ebc88de6dc96f84a677e7 \ No newline at end of file +cbedcb9aaefdfe00453efbdf0eac6c15e1f53bbe8fff2e7d534a5adf23be04f5 \ No newline at end of file From 0f5f54062cf943b0506018761b3ee5c6d0e842da Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 23 Oct 2018 13:48:19 +0000 Subject: [PATCH 5/7] Fix a problem with using window functions in compound (UNION, INTERSECT etc.) queries. FossilOrigin-Name: 059ff53a46c7f1e4bf3e7dc558312beef67826c2753e2ab7e4e7df498b37b617 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/window.c | 2 +- test/window1.test | 45 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 2cea732c3d..fb76c66c2b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\ssqlite3changeset_start_v2()\s-\sa\snew\sversion\sof\s_start()\sthat\saccepts\sa\sflags\sparameter\s-\sand\sa\sstreaming\sequivalent\sto\sthe\ssessions\smodule.\sAlso\sadd\sthe\sSQLITE_CHANGESETSTART_INVERT\sflag,\sused\swith\sstart_v2()\sto\sinvert\sa\schangeset\swhile\siterating\sthrough\sit. -D 2018-10-20T13:48:09.884 +C Fix\sa\sproblem\swith\susing\swindow\sfunctions\sin\scompound\s(UNION,\sINTERSECT\setc.)\nqueries. +D 2018-10-23T13:48:19.879 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -593,7 +593,7 @@ F src/where.c a54a3d639bcd751d1474deff58e239b2e475a96e1b8f9178aa7864df8782a4e3 F src/whereInt.h f125f29fca80890768e0b2caa14f95db74b2dacd3a122a168f97aa7b64d6968f F src/wherecode.c 3df0a541373d5f999684d761e4bd700d57adb46c7d39da4e77b767b5adcd5893 F src/whereexpr.c 1b5a5a7876997f65232bbf19c5c1eeb47eb328b8fa5b28c865543052904cde00 -F src/window.c a28d8d42c51c7e31136a42f3e245282049d4a9466b36d7bd765772991472df41 +F src/window.c 6550e2850ebced51100ef83d49b00a1cf03f81a482dafedafb0320df647ed8fc F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d @@ -1646,7 +1646,7 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2 F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc -F test/window1.test 474bef1a6ac291755e51d1f9458dc11117c1870ac5e08b4d3938649b215f8334 +F test/window1.test 02e481ac48c445b43bab7b3cf1e4115165b5127a1aa29e14f5372922c836f1a4 F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143 F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e F test/window3.tcl 577a3b1ff913208e5248c04dab9df17fd760ce159a752789e26d0cb4a5f91823 @@ -1772,7 +1772,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f7affa2e708d1b4c7c47157bcb18e9f79611ca45a93ebc88de6dc96f84a677e7 -R 3605ff60956926e38b591288ff5e2c64 +P cbedcb9aaefdfe00453efbdf0eac6c15e1f53bbe8fff2e7d534a5adf23be04f5 +R d52bd090bd9fd502659683e6d6b4324b U dan -Z 32299de6da54da0b9ad3507fdc1f1f73 +Z 24c25ee2516ea8b59659cd5b9047d478 diff --git a/manifest.uuid b/manifest.uuid index a6502f7411..0f238787cf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cbedcb9aaefdfe00453efbdf0eac6c15e1f53bbe8fff2e7d534a5adf23be04f5 \ No newline at end of file +059ff53a46c7f1e4bf3e7dc558312beef67826c2753e2ab7e4e7df498b37b617 \ No newline at end of file diff --git a/src/window.c b/src/window.c index 36cfc1c280..f5deae9a6e 100644 --- a/src/window.c +++ b/src/window.c @@ -746,7 +746,7 @@ static ExprList *exprListAppendList( */ int sqlite3WindowRewrite(Parse *pParse, Select *p){ int rc = SQLITE_OK; - if( p->pWin ){ + if( p->pWin && p->pPrior==0 ){ Vdbe *v = sqlite3GetVdbe(pParse); sqlite3 *db = pParse->db; Select *pSub = 0; /* The subquery */ diff --git a/test/window1.test b/test/window1.test index 4980305449..a8399a8606 100644 --- a/test/window1.test +++ b/test/window1.test @@ -549,4 +549,49 @@ do_execsql_test 12.110 { ORDER BY b LIMIT 2; } {2 B two 3 C three} +#------------------------------------------------------------------------- + +do_execsql_test 13.1 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a int, b int); + INSERT INTO t1 VALUES(1,11); + INSERT INTO t1 VALUES(2,12); +} + +do_execsql_test 13.2.1 { + SELECT a, rank() OVER(ORDER BY b) FROM t1; + SELECT a, rank() OVER(ORDER BY b DESC) FROM t1; +} { + 1 1 2 2 2 1 1 2 +} +do_execsql_test 13.2.2 { + SELECT a, rank() OVER(ORDER BY b) FROM t1 + UNION ALL + SELECT a, rank() OVER(ORDER BY b DESC) FROM t1; +} { + 1 1 2 2 2 1 1 2 +} +do_execsql_test 13.3 { + SELECT a, rank() OVER(ORDER BY b) FROM t1 + UNION + SELECT a, rank() OVER(ORDER BY b DESC) FROM t1; +} { + 1 1 1 2 2 1 2 2 +} + +do_execsql_test 13.4 { + SELECT a, rank() OVER(ORDER BY b) FROM t1 + EXCEPT + SELECT a, rank() OVER(ORDER BY b DESC) FROM t1; +} { + 1 1 2 2 +} + +do_execsql_test 13.5 { + SELECT a, rank() OVER(ORDER BY b) FROM t1 + INTERSECT + SELECT a, rank() OVER(ORDER BY b DESC) FROM t1; +} { +} + finish_test From e23d05e807ccc3a9ef7605eb6aed1089e31208c5 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 24 Oct 2018 23:55:41 +0000 Subject: [PATCH 6/7] Add the ENABLE_GEOPOLY case to the compile_options pragma. FossilOrigin-Name: de940296d227c96db4d0cf913fc5c0e5138729eda7cda0a0ac6b704cce1e1e1e --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/ctime.c | 3 +++ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index fb76c66c2b..7cbd3c5a2b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\swith\susing\swindow\sfunctions\sin\scompound\s(UNION,\sINTERSECT\setc.)\nqueries. -D 2018-10-23T13:48:19.879 +C Add\sthe\sENABLE_GEOPOLY\scase\sto\sthe\scompile_options\spragma. +D 2018-10-24T23:55:41.740 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -451,7 +451,7 @@ F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd9 F src/build.c 0b3d422770877d74ee6d54f4c122d82c48f7d04ee3bfb91702e402de7f5c45ac F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e -F src/ctime.c b157b01081f92442f8b0218ddb93ddce8ebddad36dbddeecfdd771561dd4f387 +F src/ctime.c 56e2f32d2e5491c152352bd53cffc9979ee1e1b70df39ec97a90920ae420a950 F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 @@ -1772,7 +1772,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P cbedcb9aaefdfe00453efbdf0eac6c15e1f53bbe8fff2e7d534a5adf23be04f5 -R d52bd090bd9fd502659683e6d6b4324b -U dan -Z 24c25ee2516ea8b59659cd5b9047d478 +P 059ff53a46c7f1e4bf3e7dc558312beef67826c2753e2ab7e4e7df498b37b617 +R 88b06779070fae47149f041be44e3466 +U drh +Z d7bdc9586bb70ec6171514ee74a2ea6d diff --git a/manifest.uuid b/manifest.uuid index 0f238787cf..cf0b4d4ba2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -059ff53a46c7f1e4bf3e7dc558312beef67826c2753e2ab7e4e7df498b37b617 \ No newline at end of file +de940296d227c96db4d0cf913fc5c0e5138729eda7cda0a0ac6b704cce1e1e1e \ No newline at end of file diff --git a/src/ctime.c b/src/ctime.c index f408a3b5f0..5bc1e5c74f 100644 --- a/src/ctime.c +++ b/src/ctime.c @@ -235,6 +235,9 @@ static const char * const sqlite3azCompileOpt[] = { #if SQLITE_ENABLE_FTS5 "ENABLE_FTS5", #endif +#if SQLITE_ENABLE_GEOPOLY + "ENABLE_GEOPOLY", +#endif #if SQLITE_ENABLE_HIDDEN_COLUMNS "ENABLE_HIDDEN_COLUMNS", #endif From 8e5bfedd22019b0fc14d75a9b3bff2c23cd7f2b1 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 25 Oct 2018 14:15:37 +0000 Subject: [PATCH 7/7] In the WHERE-constraint propagation optimization, if there are duplicate constraint, make sure only one of them propagates. Proposed fix for ticket [cf5ed20fc8621b165]. FossilOrigin-Name: 5d5b596f152bb2781011a05f75f9e200774d4f69d648ef68de577b4ace973e07 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/select.c | 25 ++++++++++++++++++++----- test/whereL.test | 11 +++++++++++ 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 7cbd3c5a2b..8332621247 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sENABLE_GEOPOLY\scase\sto\sthe\scompile_options\spragma. -D 2018-10-24T23:55:41.740 +C In\sthe\sWHERE-constraint\spropagation\soptimization,\sif\sthere\sare\sduplicate\nconstraint,\smake\ssure\sonly\sone\sof\sthem\spropagates.\s\sProposed\sfix\sfor\nticket\s[cf5ed20fc8621b165]. +D 2018-10-25T14:15:37.103 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334 @@ -504,7 +504,7 @@ F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c bc8c79e56439b111e7d9415e44940951f7087e9466c3a9d664558ef0faf31073 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 -F src/select.c 33aacf1c17c64a00788c779b23d0875dd0d90eb4c08f867ebc31139ef3a67c95 +F src/select.c 61e867a906f140b73baf4ce7a201ad6dcba30820969f5618ee40e9a0d32c6f5f F src/shell.c.in 248af8c0d785c98268353e58c96715313f3b091bf220d35366affc9a9c0d4e1d F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -1636,7 +1636,7 @@ F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 F test/whereI.test b7769ee8dbefd987fb266715fee887f05f9ff180016b06fca7fa402df739193b F test/whereJ.test 88287550f6ee604422403b053455b1ad894eeaa5c35d348532dfa1439286cb9a F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b -F test/whereL.test 84de61afe4b8e5a3ff7d741c990d85cb44b3ce798cd8412d5603930f3f75014f +F test/whereL.test 0a19fc44cd1122040f56c934f1b14d0ca85bde28f270268a428dd9796ea0634c F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864 F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3 F test/wherelimit.test 592081800806d297dd7449b1030c863d2883d6d42901837ccd2e5a9bd962edb0 @@ -1772,7 +1772,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 059ff53a46c7f1e4bf3e7dc558312beef67826c2753e2ab7e4e7df498b37b617 -R 88b06779070fae47149f041be44e3466 +P de940296d227c96db4d0cf913fc5c0e5138729eda7cda0a0ac6b704cce1e1e1e +R d5acc9d026bd9c265f6de052be0f92d3 U drh -Z d7bdc9586bb70ec6171514ee74a2ea6d +Z 4bc6cbb9e4f3ab72bb6d01ca2996d24a diff --git a/manifest.uuid b/manifest.uuid index cf0b4d4ba2..802efe5c70 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -de940296d227c96db4d0cf913fc5c0e5138729eda7cda0a0ac6b704cce1e1e1e \ No newline at end of file +5d5b596f152bb2781011a05f75f9e200774d4f69d648ef68de577b4ace973e07 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 1d2cd1a969..c60ff27001 100644 --- a/src/select.c +++ b/src/select.c @@ -4074,7 +4074,7 @@ static int flattenSubquery( #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ /* -** A structure to keep track of all of the column values that fixed to +** A structure to keep track of all of the column values that are fixed to ** a known value due to WHERE clause constraints of the form COLUMN=VALUE. */ typedef struct WhereConst WhereConst; @@ -4086,13 +4086,28 @@ struct WhereConst { }; /* -** Add a new entry to the pConst object +** Add a new entry to the pConst object. Except, do not add duplicate +** pColumn entires. */ static void constInsert( - WhereConst *pConst, - Expr *pColumn, - Expr *pValue + WhereConst *pConst, /* The WhereConst into which we are inserting */ + Expr *pColumn, /* The COLUMN part of the constraint */ + Expr *pValue /* The VALUE part of the constraint */ ){ + int i; + assert( pColumn->op==TK_COLUMN ); + + /* 2018-10-25 ticket [cf5ed20f] + ** Make sure the same pColumn is not inserted more than once */ + for(i=0; inConst; i++){ + const Expr *pExpr = pConst->apExpr[i*2]; + assert( pExpr->op==TK_COLUMN ); + if( pExpr->iTable==pColumn->iTable + && pExpr->iColumn==pColumn->iColumn + ){ + return; /* Already present. Return without doing anything. */ + } + } pConst->nConst++; pConst->apExpr = sqlite3DbReallocOrFree(pConst->pParse->db, pConst->apExpr, diff --git a/test/whereL.test b/test/whereL.test index 3fe725b877..d0e5f0b604 100644 --- a/test/whereL.test +++ b/test/whereL.test @@ -111,4 +111,15 @@ do_execsql_test 302 { AND B.id=subq.zz; } {1} +# 2018-10-25: Ticket [cf5ed20f] +# Incorrect join result with duplicate WHERE clause constraint. +# +do_execsql_test 400 { + CREATE TABLE x(a, b, c); + CREATE TABLE y(a, b); + INSERT INTO x VALUES (1, 0, 1); + INSERT INTO y VALUES (1, 2); + SELECT x.a FROM x JOIN y ON x.c = y.a WHERE x.b = 1 AND x.b = 1; +} {} + finish_test