--- /dev/null
+# 2015 August 14
+#
+# 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 $testdir/tester.tcl
+set ::testprefix rbusave
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID;
+ CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c);
+ CREATE INDEX i1 ON t1(b);
+ CREATE INDEX i2 ON t2(c, b);
+
+ INSERT INTO t1 VALUES(1, 1, 1);
+ INSERT INTO t1 VALUES(2, 2, 2);
+ INSERT INTO t1 VALUES(3, 3, 3);
+
+ INSERT INTO t2 VALUES(1, 1, 1);
+ INSERT INTO t2 VALUES(2, 2, 2);
+ INSERT INTO t2 VALUES(3, 3, 3);
+}
+
+do_test 1.1 {
+ forcedelete test.db2
+ sqlite3 db2 test.db2
+ db2 eval {
+ CREATE TABLE data_t1(a, b, c, rbu_control);
+ INSERT INTO data_t1 VALUES(4, 4, 4, 0);
+ INSERT INTO data_t1 VALUES(2, NULL, NULL, 1);
+ INSERT INTO data_t1 VALUES(1, 'one', NULL, '.x.');
+
+ CREATE TABLE data_t2(a, b, c, rbu_control);
+ INSERT INTO data_t2 VALUES(4, 4, 4, 0);
+ INSERT INTO data_t2 VALUES(2, NULL, NULL, 1);
+ INSERT INTO data_t2 VALUES(1, 'one', NULL, '.x.');
+ }
+} {}
+
+proc test_to_bak {} {
+ foreach f {
+ test.db test.db-wal test.db-oal test.db-journal
+ test.db2 test.db2-wal test.db2-oal test.db2-journal
+ } {
+ set t [string map {test bak} $f]
+ forcedelete $t
+ if {[file exists $f]} { forcecopy $f $t }
+ }
+}
+
+do_test 1.2 {
+ test_to_bak
+ sqlite3rbu rrr bak.db bak.db2
+ set nStep 0
+ while {[rrr step]=="SQLITE_OK"} {incr nStep}
+ set res2 [rrr close]
+} {SQLITE_DONE}
+
+
+sqlite3rbu rbu test.db test.db2
+set res "SQLITE_OK"
+for {set i 1} {$res=="SQLITE_OK"} {incr i} {
+ set res [rbu step]
+
+ do_test 1.3.$i.1 {
+ rbu savestate
+ test_to_bak
+ sqlite3rbu rrr bak.db bak.db2
+ set nRem 0
+ while {[rrr step]=="SQLITE_OK"} {incr nRem}
+ set res2 [rrr close]
+ } {SQLITE_DONE}
+
+ do_test 1.3.$i.3 { expr $nRem+$i } [expr {$nStep + ($res=="SQLITE_DONE")}]
+
+ do_test 1.3.$i.3 {
+ sqlite3 bak bak.db
+ bak eval {
+ SELECT * FROM t1;
+ SELECT * FROM t2;
+ }
+ } {1 one 1 3 3 3 4 4 4 1 one 1 3 3 3 4 4 4}
+
+ bak close
+}
+
+do_test 1.4 { rbu close } {SQLITE_DONE}
+
+do_execsql_test 1.5 {
+ SELECT * FROM t1;
+ SELECT * FROM t2;
+} {1 one 1 3 3 3 4 4 4 1 one 1 3 3 3 4 4 4}
+
+finish_test
+
return pRbu->nProgress;
}
+int sqlite3rbu_savestate(sqlite3rbu *p){
+ int rc = p->rc;
+
+ if( rc==SQLITE_DONE ) return SQLITE_OK;
+
+ assert( p->eStage>=RBU_STAGE_OAL && p->eStage<=RBU_STAGE_DONE );
+ if( p->eStage==RBU_STAGE_OAL ){
+ assert( rc!=SQLITE_DONE );
+ if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, 0);
+ }
+
+ p->rc = rc;
+ rbuSaveState(p, p->eStage);
+ rc = p->rc;
+
+ if( p->eStage==RBU_STAGE_OAL ){
+ assert( rc!=SQLITE_DONE );
+ if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, 0);
+ if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbRbu, "BEGIN IMMEDIATE", 0, 0, 0);
+ if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "BEGIN IMMEDIATE", 0, 0,0);
+ }
+
+ p->rc = rc;
+ return rc;
+}
+
/**************************************************************************
** Beginning of RBU VFS shim methods. The VFS shim modifies the behaviour
** of a standard VFS in the following ways:
*/
int sqlite3rbu_step(sqlite3rbu *pRbu);
+/*
+** Force RBU to save its state to disk.
+**
+** If a power failure or application crash occurs during an update, following
+** system recovery RBU may resume the update from the point at which the state
+** was last saved. In other words, from the most recent successful call to
+** sqlite3rbu_close() or this function.
+**
+** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
+*/
+int sqlite3rbu_savestate(sqlite3rbu *pRbu);
+
/*
** Close an RBU handle.
**
){
int ret = TCL_OK;
sqlite3rbu *pRbu = (sqlite3rbu*)clientData;
- const char *azMethod[] = { "step", "close", "create_rbu_delta", 0 };
+ const char *azMethod[] = {
+ "step", "close", "create_rbu_delta", "savestate", 0
+ };
int iMethod;
if( objc!=2 ){
break;
}
+ case 3: /* savestate */ {
+ int rc = sqlite3rbu_savestate(pRbu);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
+ ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
+ break;
+ }
+
default: /* seems unlikely */
assert( !"cannot happen" );
break;
-C Avoid\sinvoking\ssystem\scall\sunlink()\sdirectly\sfrom\sRBU\scode.\sUse\sthe\sxDelete\smethod\sof\sthe\sdefault\sVFS\sinstead.
-D 2015-08-13T11:46:21.944
+C Add\sthe\ssqlite3rbu_savestate()\sfunction\sto\sthe\srbu\sextension.\sTo\sforce\srbu\sto\ssave\sits\sstate\sto\sdisk\swithout\sclosing\sthe\ssqlite3rbu*\shandle.
+D 2015-08-13T18:26:09.242
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2fc9ca6bf5949d415801c007ed3004a4bdb7c380
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89
F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06
F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda
-F ext/rbu/sqlite3rbu.c e2ebcebfd0c363b8f90aba5a91cba0b3e93044ea
-F ext/rbu/sqlite3rbu.h f0754a19fcc155f6d39d72b38bdbeb1d7623f02e
-F ext/rbu/test_rbu.c f99698956cc9158d6bf865e461e2d15876538ac1
+F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
+F ext/rbu/sqlite3rbu.c 08fddeae6b89aeb1e960f9330a2228968210170a
+F ext/rbu/sqlite3rbu.h 5357f070cd8c0bcad459b620651ec1656859e4d0
+F ext/rbu/test_rbu.c 2a3652241fa45d5eaa141775e4ae68c1d3582c03
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 0f9b595bd0debcbedf1d7a63d0e0678d619e6c9c
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P efb7c9c5d0015c8c966f8d6742c05cda82fc146a
-R 574927013afdd5b82f7f2aa79787da64
+P ee966af8ff79189f8b90f3557dea21059517dfe2
+R 5dcd61cef4d3f59a3e6f61e4cf60159a
U dan
-Z c9a8f55e34994965e95a262cdf26fc13
+Z bdea05956aba407287af182409a84a65
-ee966af8ff79189f8b90f3557dea21059517dfe2
\ No newline at end of file
+851a875ad6b81f90960caf4d03b116afc911858d
\ No newline at end of file