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
This commit is contained in:
parent
9c18ef09a5
commit
46de072880
@ -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
|
||||
} {}
|
||||
|
@ -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
|
||||
|
@ -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 <b>experimental</b>
|
||||
** 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]:
|
||||
**
|
||||
** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
|
||||
** 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),
|
||||
|
@ -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);
|
||||
|
18
manifest
18
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
|
||||
|
@ -1 +1 @@
|
||||
f7affa2e708d1b4c7c47157bcb18e9f79611ca45a93ebc88de6dc96f84a677e7
|
||||
cbedcb9aaefdfe00453efbdf0eac6c15e1f53bbe8fff2e7d534a5adf23be04f5
|
Loading…
Reference in New Issue
Block a user