Add tests. Deal issues surrounding aborting recovery from within the SQL callback, and avoiding the pending-byte page.
FossilOrigin-Name: 4e97dd31f5240d9231167ae172a5116426c42177a1ed3c5422b9d51b762d5a87
This commit is contained in:
parent
5ca0b38605
commit
7985e05a97
@ -45,7 +45,7 @@ proc do_recover_test {tn} {
|
||||
uplevel [list do_test $tn.1 {
|
||||
set R [sqlite3_recover_init db main test.db2]
|
||||
$R config testdb rstate.db
|
||||
$R step
|
||||
$R run
|
||||
$R finish
|
||||
} {}]
|
||||
|
||||
@ -61,7 +61,7 @@ proc do_recover_test {tn} {
|
||||
set R [sqlite3_recover_init_sql db main my_sql_hook]
|
||||
$R config testdb rstate.db
|
||||
$R config rowids 1
|
||||
$R step
|
||||
$R run
|
||||
$R finish
|
||||
} {}]
|
||||
|
||||
@ -75,6 +75,7 @@ proc do_recover_test {tn} {
|
||||
|
||||
proc my_sql_hook {sql} {
|
||||
lappend ::sqlhook $sql
|
||||
return 0
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
|
@ -25,7 +25,7 @@ ifcapable !vtab {
|
||||
|
||||
proc recover {db output} {
|
||||
set R [sqlite3_recover_init db main test.db2]
|
||||
$R step
|
||||
$R run
|
||||
$R finish
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ for {set ii 200} {$ii < 10000} {incr ii} {
|
||||
do_test 1.2.$ii {
|
||||
set R [sqlite3_recover_init db main test.db2]
|
||||
$R config lostandfound lost_and_found
|
||||
$R step
|
||||
$R run
|
||||
$R finish
|
||||
} {}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ do_faultsim_test 1 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
set R [sqlite3_recover_init db main test.db2]
|
||||
$R step
|
||||
$R run
|
||||
$R finish
|
||||
} -test {
|
||||
faultsim_test_result {0 {}} {1 {}}
|
||||
@ -77,7 +77,7 @@ do_faultsim_test 2 -faults oom* -prep {
|
||||
} -body {
|
||||
set R [sqlite3_recover_init db main test.db2]
|
||||
$R config lostandfound lost_and_found
|
||||
$R step
|
||||
$R run
|
||||
$R finish
|
||||
} -test {
|
||||
faultsim_test_result {0 {}} {1 {}}
|
||||
|
@ -47,7 +47,7 @@ proc do_recover_test {tn {tsql {}} {res {}}} {
|
||||
|
||||
set R [sqlite3_recover_init db main test.db2]
|
||||
$R config lostandfound lost_and_found
|
||||
$R step
|
||||
$R run
|
||||
$R finish
|
||||
|
||||
sqlite3 db2 test.db2
|
||||
@ -65,7 +65,7 @@ proc do_recover_test {tn {tsql {}} {res {}}} {
|
||||
set ::sqlhook [list]
|
||||
set R [sqlite3_recover_init_sql db main my_sql_hook]
|
||||
$R config lostandfound lost_and_found
|
||||
$R step
|
||||
$R run
|
||||
$R finish
|
||||
|
||||
sqlite3 db2 test.db2
|
||||
@ -81,6 +81,7 @@ proc do_recover_test {tn {tsql {}} {res {}}} {
|
||||
|
||||
proc my_sql_hook {sql} {
|
||||
lappend ::sqlhook $sql
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
@ -154,6 +155,7 @@ do_recover_test 2.4.1 {
|
||||
2 2 3 {} 8 9 7
|
||||
}
|
||||
|
||||
breakpoint
|
||||
do_execsql_test 2.5 {
|
||||
CREATE TABLE x1(a, b, c);
|
||||
WITH s(i) AS (
|
||||
@ -176,7 +178,7 @@ do_test 2.6 {
|
||||
set R [sqlite3_recover_init db main test.db2]
|
||||
$R config lostandfound lost_and_found
|
||||
$R config freelistcorrupt 1
|
||||
$R step
|
||||
$R run
|
||||
$R finish
|
||||
sqlite3 db2 test.db2
|
||||
execsql { SELECT count(*) FROM lost_and_found_1; } db2
|
||||
|
@ -28,7 +28,7 @@ proc recover {db bRowids output} {
|
||||
|
||||
set R [sqlite3_recover_init db main test.db2]
|
||||
$R config rowids $bRowids
|
||||
$R step
|
||||
$R run
|
||||
$R finish
|
||||
}
|
||||
|
||||
|
60
ext/recover/recoversql.test
Normal file
60
ext/recover/recoversql.test
Normal file
@ -0,0 +1,60 @@
|
||||
# 2022 September 13
|
||||
#
|
||||
# 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]] recover_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix recoversql
|
||||
|
||||
ifcapable !vtab {
|
||||
finish_test; return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE "x.1" (x, y);
|
||||
INSERT INTO "x.1" VALUES(1, 1), (2, 2), (3, 3);
|
||||
CREATE INDEX "i.1" ON "x.1"(y, x);
|
||||
}
|
||||
|
||||
proc sql_hook {sql} {
|
||||
incr ::iSqlHook
|
||||
if {$::iSqlHook==$::sql_hook_cnt} { return 4 }
|
||||
return 0
|
||||
}
|
||||
|
||||
do_test 1.1 {
|
||||
set ::sql_hook_cnt -1
|
||||
set ::iSqlHook 0
|
||||
set R [sqlite3_recover_init_sql db main sql_hook]
|
||||
$R run
|
||||
$R finish
|
||||
} {}
|
||||
|
||||
set nSqlCall $iSqlHook
|
||||
|
||||
for {set ii 1} {$ii<$nSqlCall} {incr ii} {
|
||||
set iSqlHook 0
|
||||
set sql_hook_cnt $ii
|
||||
do_test 1.$ii.a {
|
||||
set R [sqlite3_recover_init_sql db main sql_hook]
|
||||
$R run
|
||||
} {1}
|
||||
do_test 1.$ii.b {
|
||||
list [catch { $R finish } msg] $msg
|
||||
} {1 {callback returned an error - 4}}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
@ -406,6 +406,11 @@ static int recoverExec(sqlite3_recover *p, sqlite3 *db, const char *zSql){
|
||||
return p->errCode;
|
||||
}
|
||||
|
||||
/*
|
||||
** Bind the value pVal to parameter iBind of statement pStmt. Leave an
|
||||
** error in the recover handle passed as the first argument if an error
|
||||
** (e.g. an OOM) occurs.
|
||||
*/
|
||||
static void recoverBindValue(
|
||||
sqlite3_recover *p,
|
||||
sqlite3_stmt *pStmt,
|
||||
@ -559,7 +564,7 @@ static void recoverGetPage(
|
||||
return;
|
||||
}else{
|
||||
if( p->pGetPage==0 ){
|
||||
pStmt = recoverPreparePrintf(
|
||||
pStmt = p->pGetPage = recoverPreparePrintf(
|
||||
p, p->dbIn, "SELECT data FROM sqlite_dbpage(%Q) WHERE pgno=?", p->zDb
|
||||
);
|
||||
}else{
|
||||
@ -567,11 +572,12 @@ static void recoverGetPage(
|
||||
}
|
||||
|
||||
if( pStmt ){
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_bind_int64(pStmt, 1, pgno);
|
||||
if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
sqlite3_result_value(pCtx, sqlite3_column_value(pStmt, 0));
|
||||
}
|
||||
p->pGetPage = recoverReset(p, pStmt);
|
||||
recoverReset(p, pStmt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,8 +42,16 @@ static int xSqlCallback(void *pSqlArg, const char *zSql){
|
||||
if( res ){
|
||||
Tcl_BackgroundError(p->interp);
|
||||
return TCL_ERROR;
|
||||
}else{
|
||||
Tcl_Obj *pObj = Tcl_GetObjResult(p->interp);
|
||||
if( Tcl_GetCharLength(pObj)==0 ){
|
||||
res = 0;
|
||||
}else if( Tcl_GetIntFromObj(p->interp, pObj, &res) ){
|
||||
Tcl_BackgroundError(p->interp);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int getDbPointer(Tcl_Interp *interp, Tcl_Obj *pObj, sqlite3 **pDb){
|
||||
@ -60,7 +68,7 @@ static int getDbPointer(Tcl_Interp *interp, Tcl_Obj *pObj, sqlite3 **pDb){
|
||||
** Implementation of the command created by [sqlite3_recover_init]:
|
||||
**
|
||||
** $cmd config OP ARG
|
||||
** $cmd step
|
||||
** $cmd run
|
||||
** $cmd errmsg
|
||||
** $cmd errcode
|
||||
** $cmd finalize
|
||||
@ -77,7 +85,7 @@ static int testRecoverCmd(
|
||||
const char *zMsg;
|
||||
} aSub[] = {
|
||||
{ "config", 2, "REBASE-BLOB" }, /* 0 */
|
||||
{ "step", 0, "" }, /* 1 */
|
||||
{ "run", 0, "" }, /* 1 */
|
||||
{ "errmsg", 0, "" }, /* 2 */
|
||||
{ "errcode", 0, "" }, /* 3 */
|
||||
{ "finish", 0, "" }, /* 4 */
|
||||
@ -145,7 +153,7 @@ static int testRecoverCmd(
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
|
||||
break;
|
||||
}
|
||||
case 1: assert( sqlite3_stricmp("step", aSub[iSub].zSub)==0 ); {
|
||||
case 1: assert( sqlite3_stricmp("run", aSub[iSub].zSub)==0 ); {
|
||||
int res = sqlite3_recover_run(pTest->p);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
|
||||
break;
|
||||
|
29
manifest
29
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\ssome\sproblems\swith\shandling\scorrupt\sdatabase\sin\sthe\srecovery\sextension.
|
||||
D 2022-09-12T20:02:33.923
|
||||
C Add\stests.\sDeal\sissues\ssurrounding\saborting\srecovery\sfrom\swithin\sthe\sSQL\scallback,\sand\savoiding\sthe\spending-byte\spage.
|
||||
D 2022-09-13T18:08:24.770
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -387,16 +387,17 @@ F ext/rbu/rbuvacuum4.test a78898e438a44803eb2bc897ba3323373c9f277418e2d6d76e90f2
|
||||
F ext/rbu/sqlite3rbu.c 8737cabdfbee84bb25a7851ecef8b1312be332761238da9be6ddb10c62ad4291
|
||||
F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812
|
||||
F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
|
||||
F ext/recover/recover1.test 942016356f9098ca36933536b194b5878827a3a749e0bf41a83d83530c0d0ea8
|
||||
F ext/recover/recover1.test d0fa2f945aac4754e0abb802941b9b80efd4828a775a090f9d2253f5a0ee1d0e
|
||||
F ext/recover/recover_common.tcl 6679af7dffc858e345053a91c9b0a897595b4a13007aceffafca75304ccb137c
|
||||
F ext/recover/recoverclobber.test e6537ebf99f57bfff6cca59550b5f4278319b57a89865abb98d755a8fd561d84
|
||||
F ext/recover/recovercorrupt.test 115cdb67ac29b4e8ec786cee9190ced674f62388f126b20deea22fa5fd11b814
|
||||
F ext/recover/recoverfault.test db6b0ba5a993c38ec885867a12556fa7c5d73948b168b0b59e7d3053c0787f29
|
||||
F ext/recover/recoverold.test f368a6ae2db12b6017257b332a19ab5df527f4061e43f12f5c85d8e2b236f074
|
||||
F ext/recover/recoverrowid.test ec4436cd69e6cdacb48dd2963ff6dd9dbd5fe648376de5e7c0c2f4f6cbacb417
|
||||
F ext/recover/sqlite3recover.c 0154617e73430b594f3d8b94eb2847bd5dc3dc3cd6ff6f0511dc6db5d116621d
|
||||
F ext/recover/recoverclobber.test 294dcc894124ab4ca3a7b35766630742a3d25810fceac22220beb64f70a33a60
|
||||
F ext/recover/recovercorrupt.test e3f3cbe0162ba681518aac9ea0ae8119f32ac93fb0900b5f09b6318966108e54
|
||||
F ext/recover/recoverfault.test 862ab02bd503922281a5ee9f81a3a92312561bb7a39e2fdb06e6afd60c3a167e
|
||||
F ext/recover/recoverold.test 46e9d99b595fac583d4c67f74d7d89c20a435c752ef6eeb3e918b599940c88e0
|
||||
F ext/recover/recoverrowid.test 1694a1a5526d825f71279f3d02ab02a1ee4c5265de18858bf54cb8ec54487ac8
|
||||
F ext/recover/recoversql.test f9872ff2114e13ffd8ee31e1de06919f62b9b48bc080191b5bd076d10becb60f
|
||||
F ext/recover/sqlite3recover.c ed5ab827433823ebf3ad7ada192ecefdc8ef9327af68fd4db9ae463a11bbc476
|
||||
F ext/recover/sqlite3recover.h 81108efb8c4618d3d9c6da4df785212b0e4501aa0d25edfc463405fe839a6640
|
||||
F ext/recover/test_recover.c 8f5ef0c9b7523c41a393f65e44d727c23cda8f44d5180fff5b698ee068ba538d
|
||||
F ext/recover/test_recover.c 5941ecf484b6158be26e34c6f7b6c7f03967c72a63db0c08e7fd0fa43023eafa
|
||||
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
|
||||
F ext/repair/checkfreelist.c e21f06995ff4efdc1622dcceaea4dcba2caa83ca2f31a1607b98a8509168a996
|
||||
F ext/repair/checkindex.c 4383e4469c21e5b9ae321d0d63cec53e981af9d7a6564be6374f0eeb93dfc890
|
||||
@ -546,7 +547,7 @@ F src/callback.c 4cd7225b26a97f7de5fee5ae10464bed5a78f2adefe19534cc2095b3a8ca484
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 93e4b5f4faf6d3f688988a116773259a4fbfb4ddac0e9bf9d0ae0429390c2543
|
||||
F src/date.c 94ce83b4cd848a387680a5f920c9018c16655db778c4d36525af0a0f34679ac5
|
||||
F src/dbpage.c dc1e8e7ba880009986b2f2050213157d2328b6d8cd4df6cf0f48883734510558
|
||||
F src/dbpage.c 433f13b34f1e5a84cbb5f10214c12471c6f0197f276389634a1cc393ec821c3d
|
||||
F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d
|
||||
F src/delete.c 86573edae75e3d3e9a8b590d87db8e47222103029df4f3e11fa56044459b514e
|
||||
F src/expr.c 24e828db6b2fab8aabfb5d2c0d83dbdfc5a1972b1147fa893350e317ab7e282f
|
||||
@ -2009,8 +2010,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 37fb093b95c6b7d7ad07a275697df73b69f9fb5c5549aea8544b26e38f24833f
|
||||
R 4bca180a2c79c76d0affba5c0d731d37
|
||||
P ed318be8241981ef96334ba13d3201a717cc812a59aed64e3dc67f7e7e71854b
|
||||
R 11a8fecaa81e021bbb20605615a33134
|
||||
U dan
|
||||
Z 8bfc7241f27e2d2e9de40f4a070a3e2c
|
||||
Z 28892e8b77cb290f00759179724671d9
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@ -1 +1 @@
|
||||
ed318be8241981ef96334ba13d3201a717cc812a59aed64e3dc67f7e7e71854b
|
||||
4e97dd31f5240d9231167ae172a5116426c42177a1ed3c5422b9d51b762d5a87
|
16
src/dbpage.c
16
src/dbpage.c
@ -274,12 +274,18 @@ static int dbpageColumn(
|
||||
}
|
||||
case 1: { /* data */
|
||||
DbPage *pDbPage = 0;
|
||||
rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage,
|
||||
SQLITE_TRANSIENT);
|
||||
if( pCsr->pgno==((PENDING_BYTE/pCsr->szPage)+1) ){
|
||||
/* The pending byte page. Assume it is zeroed out. Attempting to
|
||||
** request this page from the page is an SQLITE_CORRUPT error. */
|
||||
sqlite3_result_zeroblob(ctx, pCsr->szPage);
|
||||
}else{
|
||||
rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage,
|
||||
SQLITE_TRANSIENT);
|
||||
}
|
||||
sqlite3PagerUnref(pDbPage);
|
||||
}
|
||||
sqlite3PagerUnref(pDbPage);
|
||||
break;
|
||||
}
|
||||
default: { /* schema */
|
||||
|
Loading…
x
Reference in New Issue
Block a user