1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Add a function to the session extension invert a changeset.

FossilOrigin-Name: 75d5dff725dbb66d67d56ad042926f1daae56dbe
This commit is contained in:
dan
2011-03-09 11:17:05 +00:00
parent 4fccf43aae
commit 91ddd5595b
6 changed files with 195 additions and 38 deletions

View File

@@ -839,21 +839,25 @@ static int sessionReadRecord(
for(i=0; i<nCol; i++){ for(i=0; i<nCol; i++){
int eType = *aRec++; int eType = *aRec++;
assert( apOut[i]==0 ); assert( !apOut || apOut[i]==0 );
if( eType ){ if( eType ){
if( apOut ){
apOut[i] = sqlite3ValueNew(0); apOut[i] = sqlite3ValueNew(0);
if( !apOut[i] ) return SQLITE_NOMEM; if( !apOut[i] ) return SQLITE_NOMEM;
}
if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
int nByte; int nByte;
int enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); int enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0);
aRec += sessionVarintGet(aRec, &nByte); aRec += sessionVarintGet(aRec, &nByte);
if( apOut ){
sqlite3ValueSetStr(apOut[i], nByte, aRec, enc, SQLITE_STATIC); sqlite3ValueSetStr(apOut[i], nByte, aRec, enc, SQLITE_STATIC);
}
aRec += nByte; aRec += nByte;
} }
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
if( apOut ){
sqlite3_int64 v = sessionGetI64(aRec); sqlite3_int64 v = sessionGetI64(aRec);
aRec += 8;
if( eType==SQLITE_INTEGER ){ if( eType==SQLITE_INTEGER ){
sqlite3VdbeMemSetInt64(apOut[i], v); sqlite3VdbeMemSetInt64(apOut[i], v);
}else{ }else{
@@ -862,6 +866,8 @@ static int sessionReadRecord(
sqlite3VdbeMemSetDouble(apOut[i], d); sqlite3VdbeMemSetDouble(apOut[i], d);
} }
} }
aRec += 8;
}
} }
} }
@@ -990,4 +996,82 @@ int sqlite3changeset_finalize(sqlite3_changeset_iter *p){
return rc; return rc;
} }
/*
** Invert a changeset object.
*/
int sqlite3changeset_invert(
int nChangeset, /* Number of bytes in input */
void *pChangeset, /* Input changeset */
int *pnInverted, /* OUT: Number of bytes in output changeset */
void **ppInverted /* OUT: Inverse of pChangeset */
){
u8 *aOut;
u8 *aIn;
int i;
int nCol = 0;
/* Zero the output variables in case an error occurs. */
*ppInverted = 0;
*pnInverted = 0;
if( nChangeset==0 ) return SQLITE_OK;
aOut = (u8 *)sqlite3_malloc(nChangeset);
if( !aOut ) return SQLITE_NOMEM;
aIn = (u8 *)pChangeset;
i = 0;
while( i<nChangeset ){
u8 eType = aIn[i];
switch( eType ){
case 'T': {
int nByte = 1 + sessionVarintGet(&aIn[i+1], &nCol);
nByte += 1 + strlen((char *)&aIn[i+nByte]);
memcpy(&aOut[i], &aIn[i], nByte);
i += nByte;
break;
}
case SQLITE_INSERT:
case SQLITE_DELETE: {
int nByte;
u8 *aEnd = &aIn[i+1];
sessionReadRecord(&aEnd, nCol, 0);
aOut[i] = (eType==SQLITE_DELETE ? SQLITE_INSERT : SQLITE_DELETE);
nByte = aEnd - &aIn[i+1];
memcpy(&aOut[i+1], &aIn[i+1], nByte);
i += 1 + nByte;
break;
}
case SQLITE_UPDATE: {
int nByte1; /* Size of old.* record in bytes */
int nByte2; /* Size of new.* record in bytes */
u8 *aEnd = &aIn[i+1];
sessionReadRecord(&aEnd, nCol, 0);
nByte1 = aEnd - &aIn[i+1];
sessionReadRecord(&aEnd, nCol, 0);
nByte2 = aEnd - &aIn[i+1] - nByte1;
aOut[i] = SQLITE_UPDATE;
memcpy(&aOut[i+1], &aIn[i+1+nByte1], nByte2);
memcpy(&aOut[i+1+nByte2], &aIn[i+1], nByte1);
i += 1 + nByte1 + nByte2;
break;
}
default:
sqlite3_free(aOut);
return SQLITE_CORRUPT;
}
}
*pnInverted = nChangeset;
*ppInverted = (void *)aOut;
return SQLITE_OK;
}
#endif /* #ifdef SQLITE_ENABLE_SESSION */ #endif /* #ifdef SQLITE_ENABLE_SESSION */

View File

@@ -121,5 +121,14 @@ int sqlite3changeset_new(
*/ */
int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter);
/*
** Invert a changeset object.
*/
int sqlite3changeset_invert(
int nIn, void *pIn, /* Input changeset */
int *pnOut, void **ppOut /* OUT: Inverse of input */
);
#endif #endif

View File

@@ -168,6 +168,35 @@ static void test_append_value(Tcl_Obj *pList, sqlite3_value *pVal){
} }
} }
/*
** sqlite3changeset_invert CHANGESET
*/
static int test_sqlite3changeset_invert(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
int rc; /* Return code from changeset_invert() */
void *aChangeset; /* Input changeset */
int nChangeSet; /* Size of buffer aChangeset in bytes */
void *aOut; /* Output changeset */
int nOut; /* Size of buffer aOut in bytes */
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "CHANGESET");
}
aChangeset = (void *)Tcl_GetByteArrayFromObj(objv[1], &nChangeSet);
rc = sqlite3changeset_invert(nChangeSet, aChangeset, &nOut, &aOut);
if( rc!=SQLITE_OK ){
return test_session_error(interp, rc);
}
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj((unsigned char *)aOut, nOut));
sqlite3_free(aOut);
return TCL_OK;
}
/* /*
** sqlite3session_foreach VARNAME CHANGESET SCRIPT ** sqlite3session_foreach VARNAME CHANGESET SCRIPT
*/ */
@@ -251,6 +280,9 @@ int TestSession_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand( Tcl_CreateObjCommand(
interp, "sqlite3session_foreach", test_sqlite3session_foreach, 0, 0 interp, "sqlite3session_foreach", test_sqlite3session_foreach, 0, 0
); );
Tcl_CreateObjCommand(
interp, "sqlite3changeset_invert", test_sqlite3changeset_invert, 0, 0
);
return TCL_OK; return TCL_OK;
} }

View File

@@ -1,5 +1,5 @@
C Add\sstart\sof\ssessions\sfeature. C Add\sa\sfunction\sto\sthe\ssession\sextension\sinvert\sa\schangeset.
D 2011-03-08T19:22:51 D 2011-03-09T11:17:05
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -98,9 +98,9 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F ext/session/sqlite3session.c 88d87c48fde70fb03ae61b462527b82af561dda1 F ext/session/sqlite3session.c 82d86bbdfb0e0b731c4e7f9ab9a418340205abe1
F ext/session/sqlite3session.h b844cae3db05d2db363fd01050efe568b4e3ebec F ext/session/sqlite3session.h d7fe09ca2e12fa6007f7df8344249111c9c78e5f
F ext/session/test_session.c 72b1af5ea65c91a14faa6524e284e101b6cee6ec F ext/session/test_session.c 7bc88e75a78248dbde3a666f7c25cb228542a60c
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F main.mk ae0868e05c76eaa8a0ae3d6927a949b1c8e810d7 F main.mk ae0868e05c76eaa8a0ae3d6927a949b1c8e810d7
@@ -639,7 +639,7 @@ F test/selectA.test 06d1032fa9009314c95394f2ca2e60d9f7ae8532
F test/selectB.test f305cc6660804cb239aab4e2f26b0e288b59958b F test/selectB.test f305cc6660804cb239aab4e2f26b0e288b59958b
F test/selectC.test f9bf1bc4581b5b8158caa6e4e4f682acb379fb25 F test/selectC.test f9bf1bc4581b5b8158caa6e4e4f682acb379fb25
F test/server1.test f5b790d4c0498179151ca8a7715a65a7802c859c F test/server1.test f5b790d4c0498179151ca8a7715a65a7802c859c
F test/session1.test eb069ae24c807089cdb42c06f156e6a4bc467e08 F test/session1.test f0b04d2840b6a2fc9893096a1e1dadcd4f241993
F test/shared.test b9114eaea7e748a3a4c8ff7b9ca806c8f95cef3e F test/shared.test b9114eaea7e748a3a4c8ff7b9ca806c8f95cef3e
F test/shared2.test 7f6ad2d857d0f4e5d6a0b9a897b5e56a6b6ea18c F test/shared2.test 7f6ad2d857d0f4e5d6a0b9a897b5e56a6b6ea18c
F test/shared3.test d69bdd5f156580876c5345652d21dc2092e85962 F test/shared3.test d69bdd5f156580876c5345652d21dc2092e85962
@@ -913,7 +913,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P 093d8cd8e2f3a6af5d40cf810e396f4919eb5cef P 269a81a37d7dbdcdec3c2322074916af0fbac91c
R d2860e2d38705a211d32d9cfd0828f6b R 06c861473767f41ba98f1b1628042bc2
U dan U dan
Z 881eaac7f67a95dfac0116385a169f79 Z 8e42230c84fa0976b233cb2ac7764b8c

View File

@@ -1 +1 @@
269a81a37d7dbdcdec3c2322074916af0fbac91c 75d5dff725dbb66d67d56ad042926f1daae56dbe

View File

@@ -15,11 +15,35 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
set ::testprefix session1 set ::testprefix session1
proc do_changeset_test {tn session res} {
set r [list]
foreach x $res {lappend r $x}
uplevel do_test $tn [list [subst -nocommands {
set x [list]
sqlite3session_foreach c [$session changeset] { lappend x [set c] }
set x
}]] [list $r]
}
proc do_changeset_invert_test {tn session res} {
set r [list]
foreach x $res {lappend r $x}
uplevel do_test $tn [list [subst -nocommands {
set x [list]
set changeset [sqlite3changeset_invert [$session changeset]]
sqlite3session_foreach c [set changeset] { lappend x [set c] }
set x
}]] [list $r]
}
do_execsql_test 1.0 { do_execsql_test 1.0 {
CREATE TABLE t1(x, y); CREATE TABLE t1(x, y);
INSERT INTO t1 VALUES('abc', 'def'); INSERT INTO t1 VALUES('abc', 'def');
} }
#-------------------------------------------------------------------------
# Test creating, attaching tables to and deleting session objects.
#
do_test 1.1 { sqlite3session S db main } {S} do_test 1.1 { sqlite3session S db main } {S}
do_test 1.2 { S delete } {} do_test 1.2 { S delete } {}
do_test 1.3 { sqlite3session S db main } {S} do_test 1.3 { sqlite3session S db main } {S}
@@ -47,16 +71,10 @@ do_test 1.13 {
S delete S delete
} {} } {}
proc do_changeset_test {tn session res} { #-------------------------------------------------------------------------
set r [list] # Simple changeset tests. Also test the sqlite3changeset_invert()
foreach x $res {lappend r $x} # function.
uplevel do_test $tn [list [subst -nocommands { #
set x [list]
sqlite3session_foreach c [$session changeset] { lappend x [set c] }
set x
}]] [list $r]
}
do_test 2.1.1 { do_test 2.1.1 {
execsql { DELETE FROM t1 } execsql { DELETE FROM t1 }
sqlite3session S db main sqlite3session S db main
@@ -70,7 +88,12 @@ do_changeset_test 2.1.2 S {
{INSERT t1 {} {i 2 t Ayutthaya}} {INSERT t1 {} {i 2 t Ayutthaya}}
{INSERT t1 {} {i 3 t Thonburi}} {INSERT t1 {} {i 3 t Thonburi}}
} }
do_test 2.1.3 { S delete } {} do_changeset_invert_test 2.1.3 S {
{DELETE t1 {i 1 t Sukhothai} {}}
{DELETE t1 {i 2 t Ayutthaya} {}}
{DELETE t1 {i 3 t Thonburi} {}}
}
do_test 2.1.4 { S delete } {}
do_test 2.2.1 { do_test 2.2.1 {
sqlite3session S db main sqlite3session S db main
@@ -82,7 +105,12 @@ do_changeset_test 2.2.2 S {
{DELETE t1 {i 2 t Ayutthaya} {}} {DELETE t1 {i 2 t Ayutthaya} {}}
{DELETE t1 {i 3 t Thonburi} {}} {DELETE t1 {i 3 t Thonburi} {}}
} }
do_test 2.2.3 { S delete } {} do_changeset_invert_test 2.2.3 S {
{INSERT t1 {} {i 1 t Sukhothai}}
{INSERT t1 {} {i 2 t Ayutthaya}}
{INSERT t1 {} {i 3 t Thonburi}}
}
do_test 2.2.4 { S delete } {}
do_test 2.3.1 { do_test 2.3.1 {
sqlite3session S db main sqlite3session S db main
@@ -102,7 +130,12 @@ do_changeset_test 2.3.2 S {
{UPDATE t1 {{} {} t Ayutthaya} {{} {} t Surin}} {UPDATE t1 {{} {} t Ayutthaya} {{} {} t Surin}}
{UPDATE t1 {i 3 t Thonburi} {i 20 t Thapae}} {UPDATE t1 {i 3 t Thonburi} {i 20 t Thapae}}
} }
do_test 2.3.3 { S delete } {} do_changeset_invert_test 2.3.3 S {
{UPDATE t1 {i 10 {} {}} {i 1 {} {}}}
{UPDATE t1 {{} {} t Surin} {{} {} t Ayutthaya}}
{UPDATE t1 {i 20 t Thapae} {i 3 t Thonburi}}
}
do_test 2.3.4 { S delete } {}
do_test 2.4.1 { do_test 2.4.1 {
sqlite3session S db main sqlite3session S db main
@@ -110,9 +143,8 @@ do_test 2.4.1 {
execsql { INSERT INTO t1 VALUES(100, 'Bangkok') } execsql { INSERT INTO t1 VALUES(100, 'Bangkok') }
execsql { DELETE FROM t1 WHERE x = 100 } execsql { DELETE FROM t1 WHERE x = 100 }
} {} } {}
breakpoint
do_changeset_test 2.4.2 S {} do_changeset_test 2.4.2 S {}
do_test 2.4.3 { S delete } {} do_changeset_invert_test 2.4.3 S {}
do_test 2.4.4 { S delete } {}
finish_test finish_test