Fix problems with recovering the sqlite_sequence table.
FossilOrigin-Name: 356d2209ea5f6b69ce15b62027c63419c2d039e52f01c74a3810a6317abf4fb0
This commit is contained in:
parent
4a08e793c6
commit
3887ffe82a
@ -45,6 +45,7 @@ proc do_recover_test {tn} {
|
|||||||
uplevel [list do_test $tn.1 {
|
uplevel [list do_test $tn.1 {
|
||||||
set R [sqlite3_recover_init db main test.db2]
|
set R [sqlite3_recover_init db main test.db2]
|
||||||
$R config testdb rstate.db
|
$R config testdb rstate.db
|
||||||
|
$R config rowids 1
|
||||||
$R step
|
$R step
|
||||||
$R finish
|
$R finish
|
||||||
} {}]
|
} {}]
|
||||||
@ -60,12 +61,14 @@ proc do_recover_test {tn} {
|
|||||||
set ::sqlhook [list]
|
set ::sqlhook [list]
|
||||||
set R [sqlite3_recover_init_sql db main my_sql_hook]
|
set R [sqlite3_recover_init_sql db main my_sql_hook]
|
||||||
$R config testdb rstate.db
|
$R config testdb rstate.db
|
||||||
|
$R config rowids 1
|
||||||
$R step
|
$R step
|
||||||
$R finish
|
$R finish
|
||||||
} {}]
|
} {}]
|
||||||
|
|
||||||
sqlite3 db2 test.db2
|
sqlite3 db2 test.db2
|
||||||
execsql [join $::sqlhook ";"] db2
|
execsql [join $::sqlhook ";"] db2
|
||||||
|
# puts [join $::sqlhook ";\n"]
|
||||||
uplevel [list do_test $tn.4 [list compare_dbs db db2] {}]
|
uplevel [list do_test $tn.4 [list compare_dbs db db2] {}]
|
||||||
db2 close
|
db2 close
|
||||||
}
|
}
|
||||||
@ -82,6 +85,7 @@ do_execsql_test 1.0 {
|
|||||||
)
|
)
|
||||||
INSERT INTO t1 SELECT i*2, hex(randomblob(250)) FROM s;
|
INSERT INTO t1 SELECT i*2, hex(randomblob(250)) FROM s;
|
||||||
INSERT INTO t2 SELECT * FROM t1;
|
INSERT INTO t2 SELECT * FROM t1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
do_recover_test 1
|
do_recover_test 1
|
||||||
@ -131,8 +135,28 @@ do_execsql_test 7.1 {
|
|||||||
SELECT * FROM t2
|
SELECT * FROM t2
|
||||||
} {10 11 ten}
|
} {10 11 ten}
|
||||||
|
|
||||||
breakpoint
|
|
||||||
do_recover_test 7.2
|
do_recover_test 7.2
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 8.0 {
|
||||||
|
CREATE TABLE x1(a INTEGER PRIMARY KEY AUTOINCREMENT, b, c);
|
||||||
|
WITH s(i) AS (
|
||||||
|
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<2
|
||||||
|
)
|
||||||
|
INSERT INTO x1(b, c) SELECT hex(randomblob(100)), hex(randomblob(100)) FROM s;
|
||||||
|
|
||||||
|
CREATE INDEX x1b ON x1(b);
|
||||||
|
CREATE INDEX x1cb ON x1(c, b);
|
||||||
|
DELETE FROM x1 WHERE a>50;
|
||||||
|
|
||||||
|
ANALYZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_recover_test 8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
@ -60,17 +60,6 @@ struct RecoverBitmap {
|
|||||||
u32 aElem[0]; /* Array of 32-bit bitmasks */
|
u32 aElem[0]; /* Array of 32-bit bitmasks */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
#define RECOVERY_SCHEMA \
|
|
||||||
" CREATE TABLE recovery.map(" \
|
|
||||||
" pgno INTEGER PRIMARY KEY, parent INT" \
|
|
||||||
" );" \
|
|
||||||
" CREATE TABLE recovery.schema(" \
|
|
||||||
" type, name, tbl_name, rootpage, sql" \
|
|
||||||
" );"
|
|
||||||
|
|
||||||
|
|
||||||
struct sqlite3_recover {
|
struct sqlite3_recover {
|
||||||
sqlite3 *dbIn;
|
sqlite3 *dbIn;
|
||||||
@ -1123,6 +1112,8 @@ static int recoverWriteData(sqlite3_recover *p){
|
|||||||
RecoverTable *pTbl;
|
RecoverTable *pTbl;
|
||||||
int nMax = 0;
|
int nMax = 0;
|
||||||
sqlite3_value **apVal = 0;
|
sqlite3_value **apVal = 0;
|
||||||
|
|
||||||
|
sqlite3_stmt *pTbls = 0;
|
||||||
sqlite3_stmt *pSel = 0;
|
sqlite3_stmt *pSel = 0;
|
||||||
|
|
||||||
/* Figure out the maximum number of columns for any table in the schema */
|
/* Figure out the maximum number of columns for any table in the schema */
|
||||||
@ -1133,45 +1124,58 @@ static int recoverWriteData(sqlite3_recover *p){
|
|||||||
apVal = (sqlite3_value**)recoverMalloc(p, sizeof(sqlite3_value*) * (nMax+1));
|
apVal = (sqlite3_value**)recoverMalloc(p, sizeof(sqlite3_value*) * (nMax+1));
|
||||||
if( apVal==0 ) return p->errCode;
|
if( apVal==0 ) return p->errCode;
|
||||||
|
|
||||||
|
pTbls = recoverPrepare(p, p->dbOut,
|
||||||
|
"SELECT rootpage FROM recovery.schema WHERE type='table'"
|
||||||
|
" ORDER BY (tbl_name='sqlite_sequence') ASC"
|
||||||
|
);
|
||||||
|
|
||||||
pSel = recoverPrepare(p, p->dbOut,
|
pSel = recoverPrepare(p, p->dbOut,
|
||||||
"WITH RECURSIVE pages(root, page) AS ("
|
"WITH RECURSIVE pages(page) AS ("
|
||||||
" SELECT rootpage, rootpage FROM recovery.schema"
|
" SELECT ?1"
|
||||||
" UNION"
|
" UNION"
|
||||||
" SELECT root, child FROM sqlite_dbptr('getpage()'), pages "
|
" SELECT child FROM sqlite_dbptr('getpage()'), pages "
|
||||||
" WHERE pgno=page"
|
" WHERE pgno=page"
|
||||||
") "
|
") "
|
||||||
"SELECT root, page, cell, field, value "
|
"SELECT page, cell, field, value "
|
||||||
"FROM sqlite_dbdata('getpage()') d, pages p WHERE p.page=d.pgno "
|
"FROM sqlite_dbdata('getpage()') d, pages p WHERE p.page=d.pgno "
|
||||||
"UNION ALL "
|
"UNION ALL "
|
||||||
"SELECT 0, 0, 0, 0, 0"
|
"SELECT 0, 0, 0, 0"
|
||||||
);
|
);
|
||||||
if( pSel ){
|
if( pSel ){
|
||||||
RecoverTable *pTab = 0;
|
|
||||||
|
/* The outer loop runs once for each table to recover. */
|
||||||
|
while( sqlite3_step(pTbls)==SQLITE_ROW ){
|
||||||
|
i64 iRoot = sqlite3_column_int64(pTbls, 0);
|
||||||
|
RecoverTable *pTab = recoverFindTable(p, iRoot);
|
||||||
|
if( pTab ){
|
||||||
|
int ii;
|
||||||
sqlite3_stmt *pInsert = 0;
|
sqlite3_stmt *pInsert = 0;
|
||||||
int nInsert = -1;
|
int nInsert = -1;
|
||||||
i64 iPrevRoot = -1;
|
|
||||||
i64 iPrevPage = -1;
|
i64 iPrevPage = -1;
|
||||||
int iPrevCell = -1;
|
int iPrevCell = -1;
|
||||||
int bHaveRowid = 0; /* True if iRowid is valid */
|
int bHaveRowid = 0; /* True if iRowid is valid */
|
||||||
i64 iRowid = 0;
|
i64 iRowid = 0;
|
||||||
int nVal = -1;
|
int nVal = -1;
|
||||||
|
|
||||||
while( p->errCode==SQLITE_OK && sqlite3_step(pSel)==SQLITE_ROW ){
|
if( sqlite3_stricmp("sqlite_sequence", pTab->zTab)==0 ){
|
||||||
i64 iRoot = sqlite3_column_int64(pSel, 0);
|
recoverExec(p, p->dbOut, "DELETE FROM sqlite_sequence");
|
||||||
i64 iPage = sqlite3_column_int64(pSel, 1);
|
recoverSqlCallback(p, "DELETE FROM sqlite_sequence");
|
||||||
int iCell = sqlite3_column_int(pSel, 2);
|
}
|
||||||
int iField = sqlite3_column_int(pSel, 3);
|
|
||||||
sqlite3_value *pVal = sqlite3_column_value(pSel, 4);
|
|
||||||
|
|
||||||
int bNewCell = (iPrevRoot!=iRoot || iPrevPage!=iPage || iPrevCell!=iCell);
|
sqlite3_bind_int64(pSel, 1, iRoot);
|
||||||
|
while( p->errCode==SQLITE_OK && sqlite3_step(pSel)==SQLITE_ROW ){
|
||||||
|
i64 iPage = sqlite3_column_int64(pSel, 0);
|
||||||
|
int iCell = sqlite3_column_int(pSel, 1);
|
||||||
|
int iField = sqlite3_column_int(pSel, 2);
|
||||||
|
sqlite3_value *pVal = sqlite3_column_value(pSel, 3);
|
||||||
|
|
||||||
|
int bNewCell = (iPrevPage!=iPage || iPrevCell!=iCell);
|
||||||
assert( bNewCell==0 || (iField==-1 || iField==0) );
|
assert( bNewCell==0 || (iField==-1 || iField==0) );
|
||||||
assert( bNewCell || iField==nVal );
|
assert( bNewCell || iField==nVal );
|
||||||
|
|
||||||
if( bNewCell ){
|
if( bNewCell ){
|
||||||
if( nVal>=0 ){
|
if( nVal>=0 ){
|
||||||
int ii;
|
int ii;
|
||||||
|
|
||||||
if( pTab ){
|
|
||||||
int iVal = 0;
|
int iVal = 0;
|
||||||
int iBind = 1;
|
int iBind = 1;
|
||||||
|
|
||||||
@ -1213,17 +1217,9 @@ static int recoverWriteData(sqlite3_recover *p){
|
|||||||
bHaveRowid = 0;
|
bHaveRowid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( iRoot==0 ) continue;
|
if( iPage!=0 ){
|
||||||
|
|
||||||
if( iRoot!=iPrevRoot ){
|
|
||||||
pTab = recoverFindTable(p, iRoot);
|
|
||||||
recoverFinalize(p, pInsert);
|
|
||||||
pInsert = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( iField<0 ){
|
if( iField<0 ){
|
||||||
iRowid = sqlite3_column_int64(pSel, 4);
|
iRowid = sqlite3_column_int64(pSel, 3);
|
||||||
assert( nVal==-1 );
|
assert( nVal==-1 );
|
||||||
nVal = 0;
|
nVal = 0;
|
||||||
bHaveRowid = 1;
|
bHaveRowid = 1;
|
||||||
@ -1232,15 +1228,26 @@ static int recoverWriteData(sqlite3_recover *p){
|
|||||||
apVal[iField] = sqlite3_value_dup( pVal );
|
apVal[iField] = sqlite3_value_dup( pVal );
|
||||||
nVal = iField+1;
|
nVal = iField+1;
|
||||||
}
|
}
|
||||||
iPrevRoot = iRoot;
|
|
||||||
iPrevCell = iCell;
|
iPrevCell = iCell;
|
||||||
iPrevPage = iPage;
|
iPrevPage = iPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
recoverFinalize(p, pInsert);
|
|
||||||
recoverFinalize(p, pSel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recoverReset(p, pSel);
|
||||||
|
recoverFinalize(p, pInsert);
|
||||||
|
pInsert = 0;
|
||||||
|
for(ii=0; ii<nVal; ii++){
|
||||||
|
sqlite3_value_free(apVal[ii]);
|
||||||
|
apVal[ii] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
recoverFinalize(p, pTbls);
|
||||||
|
recoverFinalize(p, pSel);
|
||||||
|
|
||||||
sqlite3_free(apVal);
|
sqlite3_free(apVal);
|
||||||
return p->errCode;
|
return p->errCode;
|
||||||
}
|
}
|
||||||
|
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
|||||||
C Add\snew\stest\sfile\srecoverclobber.test.
|
C Fix\sproblems\swith\srecovering\sthe\ssqlite_sequence\stable.
|
||||||
D 2022-09-08T11:04:23.161
|
D 2022-09-08T17:42:33.679
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
@ -387,12 +387,12 @@ F ext/rbu/rbuvacuum4.test a78898e438a44803eb2bc897ba3323373c9f277418e2d6d76e90f2
|
|||||||
F ext/rbu/sqlite3rbu.c 8737cabdfbee84bb25a7851ecef8b1312be332761238da9be6ddb10c62ad4291
|
F ext/rbu/sqlite3rbu.c 8737cabdfbee84bb25a7851ecef8b1312be332761238da9be6ddb10c62ad4291
|
||||||
F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812
|
F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812
|
||||||
F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
|
F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
|
||||||
F ext/recover/recover1.test ae8ce9828210aa6c466bf88e23b0933849d5bb43091abe48cf2e56d636e51e93
|
F ext/recover/recover1.test ddc322148170eafe1dabbea91ac175a72f7e7d2777619a6434696a310beff9a3
|
||||||
F ext/recover/recover_common.tcl 6679af7dffc858e345053a91c9b0a897595b4a13007aceffafca75304ccb137c
|
F ext/recover/recover_common.tcl 6679af7dffc858e345053a91c9b0a897595b4a13007aceffafca75304ccb137c
|
||||||
F ext/recover/recoverclobber.test e6537ebf99f57bfff6cca59550b5f4278319b57a89865abb98d755a8fd561d84
|
F ext/recover/recoverclobber.test e6537ebf99f57bfff6cca59550b5f4278319b57a89865abb98d755a8fd561d84
|
||||||
F ext/recover/recoverold.test f368a6ae2db12b6017257b332a19ab5df527f4061e43f12f5c85d8e2b236f074
|
F ext/recover/recoverold.test f368a6ae2db12b6017257b332a19ab5df527f4061e43f12f5c85d8e2b236f074
|
||||||
F ext/recover/recoverrowid.test ec4436cd69e6cdacb48dd2963ff6dd9dbd5fe648376de5e7c0c2f4f6cbacb417
|
F ext/recover/recoverrowid.test ec4436cd69e6cdacb48dd2963ff6dd9dbd5fe648376de5e7c0c2f4f6cbacb417
|
||||||
F ext/recover/sqlite3recover.c 9724f913fd457f655e2873552bc6600a6aaff7104b9113ccb38fea18b6a71f03
|
F ext/recover/sqlite3recover.c 2c45ab8cce41dcb578ef739652e65675d161751fe0d979b806d947a02de7fd32
|
||||||
F ext/recover/sqlite3recover.h 32f89b66f0235c0d94dfee0f1c3e9ed1ad726b3c4f3716ef0262b31cc33e8301
|
F ext/recover/sqlite3recover.h 32f89b66f0235c0d94dfee0f1c3e9ed1ad726b3c4f3716ef0262b31cc33e8301
|
||||||
F ext/recover/test_recover.c 7aa268d3431d630eaa82ce14974ae04be50fe7feba660ffaea009cd581916d27
|
F ext/recover/test_recover.c 7aa268d3431d630eaa82ce14974ae04be50fe7feba660ffaea009cd581916d27
|
||||||
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
|
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
|
||||||
@ -2007,8 +2007,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 6cca8913e703635ad89415a60fc84000ac188d9df43f45594b8ad87facb91d54
|
P cb4e950c472bd24a79a8505a7f8e4c3a0f7821648297d05cc760738b777d5149
|
||||||
R 102ea2ce4694a6be6ee34f8e72c4fbd9
|
R e45081ba4805e1d831caf7a65d0c00b9
|
||||||
U dan
|
U dan
|
||||||
Z e86817dfd35f39cea8c450fbde6bc553
|
Z 8c44bc5cd3a46bb8aa19fae7f571d64e
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@ -1 +1 @@
|
|||||||
cb4e950c472bd24a79a8505a7f8e4c3a0f7821648297d05cc760738b777d5149
|
356d2209ea5f6b69ce15b62027c63419c2d039e52f01c74a3810a6317abf4fb0
|
Loading…
x
Reference in New Issue
Block a user