]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix problems with recovering the sqlite_sequence table.
authordan <Dan Kennedy>
Thu, 8 Sep 2022 17:42:33 +0000 (17:42 +0000)
committerdan <Dan Kennedy>
Thu, 8 Sep 2022 17:42:33 +0000 (17:42 +0000)
FossilOrigin-Name: 356d2209ea5f6b69ce15b62027c63419c2d039e52f01c74a3810a6317abf4fb0

ext/recover/recover1.test
ext/recover/sqlite3recover.c
manifest
manifest.uuid

index 167b2796bd8af2c791c2667340804768a583816d..26e7c60d264de8a015170c1258a34dea79b30dee 100644 (file)
@@ -45,6 +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 config rowids 1
     $R step
     $R finish
   } {}]
@@ -60,12 +61,14 @@ proc do_recover_test {tn} {
     set ::sqlhook [list]
     set R [sqlite3_recover_init_sql db main my_sql_hook]
     $R config testdb rstate.db
+    $R config rowids 1
     $R step
     $R finish
   } {}]
 
   sqlite3 db2 test.db2
   execsql [join $::sqlhook ";"] db2
+  # puts [join $::sqlhook ";\n"]
   uplevel [list do_test $tn.4 [list compare_dbs db db2] {}]
   db2 close
 }
@@ -82,6 +85,7 @@ do_execsql_test 1.0 {
   )
   INSERT INTO t1 SELECT i*2, hex(randomblob(250)) FROM s;
   INSERT INTO t2 SELECT * FROM t1;
+
 }
 
 do_recover_test 1
@@ -131,8 +135,28 @@ do_execsql_test 7.1 {
   SELECT * FROM t2
 } {10 11 ten}
 
-breakpoint
 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
 
index de3dc6ea1a3f5e33c1a0d156e84baf764ab935a7..1ab4f5d6d5a0fa9fb8d52f912b1eff83e8e61b32 100644 (file)
@@ -60,17 +60,6 @@ struct RecoverBitmap {
   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 {
   sqlite3 *dbIn;
@@ -1123,6 +1112,8 @@ static int recoverWriteData(sqlite3_recover *p){
   RecoverTable *pTbl;
   int nMax = 0;
   sqlite3_value **apVal = 0;
+
+  sqlite3_stmt *pTbls = 0;
   sqlite3_stmt *pSel = 0;
 
   /* Figure out the maximum number of columns for any table in the schema */
@@ -1133,114 +1124,130 @@ static int recoverWriteData(sqlite3_recover *p){
   apVal = (sqlite3_value**)recoverMalloc(p, sizeof(sqlite3_value*) * (nMax+1));
   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, 
-      "WITH RECURSIVE pages(root, page) AS ("
-      "  SELECT rootpage, rootpage FROM recovery.schema"
+      "WITH RECURSIVE pages(page) AS ("
+      "  SELECT ?1"
       "    UNION"
-      "   SELECT root, child FROM sqlite_dbptr('getpage()'), pages "
+      "  SELECT child FROM sqlite_dbptr('getpage()'), pages "
       "    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 "
       "UNION ALL "
-      "SELECT 0, 0, 0, 0, 0"
+      "SELECT 0, 0, 0, 0"
   );
   if( pSel ){
-    RecoverTable *pTab = 0;
-    sqlite3_stmt *pInsert = 0;
-    int nInsert = -1;
-    i64 iPrevRoot = -1;
-    i64 iPrevPage = -1;
-    int iPrevCell = -1;
-    int bHaveRowid = 0;           /* True if iRowid is valid */
-    i64 iRowid = 0;
-    int nVal = -1;
-
-    while( p->errCode==SQLITE_OK && sqlite3_step(pSel)==SQLITE_ROW ){
-      i64 iRoot = sqlite3_column_int64(pSel, 0);
-      i64 iPage = sqlite3_column_int64(pSel, 1);
-      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);
-      assert( bNewCell==0 || (iField==-1 || iField==0) );
-      assert( bNewCell || iField==nVal );
-
-      if( bNewCell ){
-        if( nVal>=0 ){
-          int ii;
-
-          if( pTab ){
-            int iVal = 0;
-            int iBind = 1;
-
-            if( pInsert==0 || nVal!=nInsert ){
-              recoverFinalize(p, pInsert);
-              pInsert = recoverInsertStmt(p, pTab, nVal);
-              nInsert = nVal;
-            }
 
-            for(ii=0; ii<pTab->nCol; ii++){
-              RecoverColumn *pCol = &pTab->aCol[ii];
+    /* 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;
+        int nInsert = -1;
+        i64 iPrevPage = -1;
+        int iPrevCell = -1;
+        int bHaveRowid = 0;           /* True if iRowid is valid */
+        i64 iRowid = 0;
+        int nVal = -1;
+
+        if( sqlite3_stricmp("sqlite_sequence", pTab->zTab)==0 ){
+          recoverExec(p, p->dbOut, "DELETE FROM sqlite_sequence");
+          recoverSqlCallback(p, "DELETE FROM sqlite_sequence");
+        }
 
-              if( pCol->iBind>0 ){
-                if( pCol->bIPK ){
-                  sqlite3_bind_int64(pInsert, pCol->iBind, iRowid);
-                }else if( pCol->iField<nVal ){
-                  sqlite3_bind_value(pInsert, pCol->iBind, apVal[pCol->iField]);
+        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 || iField==nVal );
+
+          if( bNewCell ){
+            if( nVal>=0 ){
+              int ii;
+              int iVal = 0;
+              int iBind = 1;
+
+              if( pInsert==0 || nVal!=nInsert ){
+                recoverFinalize(p, pInsert);
+                pInsert = recoverInsertStmt(p, pTab, nVal);
+                nInsert = nVal;
+              }
+
+              for(ii=0; ii<pTab->nCol; ii++){
+                RecoverColumn *pCol = &pTab->aCol[ii];
+
+                if( pCol->iBind>0 ){
+                  if( pCol->bIPK ){
+                    sqlite3_bind_int64(pInsert, pCol->iBind, iRowid);
+                  }else if( pCol->iField<nVal ){
+                    sqlite3_bind_value(pInsert,pCol->iBind,apVal[pCol->iField]);
+                  }
                 }
               }
-            }
-            if( p->bRecoverRowid && pTab->iRowidBind>0 && bHaveRowid ){
-              sqlite3_bind_int64(pInsert, pTab->iRowidBind, iRowid);
+              if( p->bRecoverRowid && pTab->iRowidBind>0 && bHaveRowid ){
+                sqlite3_bind_int64(pInsert, pTab->iRowidBind, iRowid);
+              }
+
+              if( SQLITE_ROW==sqlite3_step(pInsert) && p->xSql ){
+                const char *zSql = (const char*)sqlite3_column_text(pInsert, 0);
+                recoverSqlCallback(p, zSql);
+              }
+              recoverReset(p, pInsert);
+              assert( p->errCode || pInsert );
+              if( pInsert ) sqlite3_clear_bindings(pInsert);
             }
 
-            if( SQLITE_ROW==sqlite3_step(pInsert) && p->xSql ){
-              const char *zSql = (const char*)sqlite3_column_text(pInsert, 0);
-              recoverSqlCallback(p, zSql);
+            for(ii=0; ii<nVal; ii++){
+              sqlite3_value_free(apVal[ii]);
+              apVal[ii] = 0;
             }
-            recoverReset(p, pInsert);
-            assert( p->errCode || pInsert );
-            if( pInsert ) sqlite3_clear_bindings(pInsert);
+            nVal = -1;
+            bHaveRowid = 0;
           }
 
-          for(ii=0; ii<nVal; ii++){
-            sqlite3_value_free(apVal[ii]);
-            apVal[ii] = 0;
+          if( iPage!=0 ){
+            if( iField<0 ){
+              iRowid = sqlite3_column_int64(pSel, 3);
+              assert( nVal==-1 );
+              nVal = 0;
+              bHaveRowid = 1;
+            }else if( iField<nMax ){
+              assert( apVal[iField]==0 );
+              apVal[iField] = sqlite3_value_dup( pVal );
+              nVal = iField+1;
+            }
+            iPrevCell = iCell;
+            iPrevPage = iPage;
           }
-          nVal = -1;
-          bHaveRowid = 0;
         }
 
-        if( iRoot==0 ) continue;
-
-        if( iRoot!=iPrevRoot ){
-          pTab = recoverFindTable(p, iRoot);
-          recoverFinalize(p, pInsert);
-          pInsert = 0;
+        recoverReset(p, pSel);
+        recoverFinalize(p, pInsert);
+        pInsert = 0;
+        for(ii=0; ii<nVal; ii++){
+          sqlite3_value_free(apVal[ii]);
+          apVal[ii] = 0;
         }
       }
-
-      if( iField<0 ){
-        iRowid = sqlite3_column_int64(pSel, 4);
-        assert( nVal==-1 );
-        nVal = 0;
-        bHaveRowid = 1;
-      }else if( iField<nMax ){
-        assert( apVal[iField]==0 );
-        apVal[iField] = sqlite3_value_dup( pVal );
-        nVal = iField+1;
-      }
-      iPrevRoot = iRoot;
-      iPrevCell = iCell;
-      iPrevPage = iPage;
     }
 
-    recoverFinalize(p, pInsert);
-    recoverFinalize(p, pSel);
   }
 
+  recoverFinalize(p, pTbls);
+  recoverFinalize(p, pSel);
+
   sqlite3_free(apVal);
   return p->errCode;
 }
index 421372fcab2a06e95ef24fc1f1496b7c648c973d..f5344ad585b3c1b1e44b46a6d2faf21d16da2b38 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\snew\stest\sfile\srecoverclobber.test.
-D 2022-09-08T11:04:23.161
+C Fix\sproblems\swith\srecovering\sthe\ssqlite_sequence\stable.
+D 2022-09-08T17:42:33.679
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -387,12 +387,12 @@ 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 ae8ce9828210aa6c466bf88e23b0933849d5bb43091abe48cf2e56d636e51e93
+F ext/recover/recover1.test ddc322148170eafe1dabbea91ac175a72f7e7d2777619a6434696a310beff9a3
 F ext/recover/recover_common.tcl 6679af7dffc858e345053a91c9b0a897595b4a13007aceffafca75304ccb137c
 F ext/recover/recoverclobber.test e6537ebf99f57bfff6cca59550b5f4278319b57a89865abb98d755a8fd561d84
 F ext/recover/recoverold.test f368a6ae2db12b6017257b332a19ab5df527f4061e43f12f5c85d8e2b236f074
 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/test_recover.c 7aa268d3431d630eaa82ce14974ae04be50fe7feba660ffaea009cd581916d27
 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.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 6cca8913e703635ad89415a60fc84000ac188d9df43f45594b8ad87facb91d54
-R 102ea2ce4694a6be6ee34f8e72c4fbd9
+P cb4e950c472bd24a79a8505a7f8e4c3a0f7821648297d05cc760738b777d5149
+R e45081ba4805e1d831caf7a65d0c00b9
 U dan
-Z e86817dfd35f39cea8c450fbde6bc553
+Z 8c44bc5cd3a46bb8aa19fae7f571d64e
 # Remove this line to create a well-formed Fossil manifest.
index 2f048091956d7d3fcc80b103aba386522fdd7d0c..34b201c3c51897d0bc8390e361edfd3adcc336bd 100644 (file)
@@ -1 +1 @@
-cb4e950c472bd24a79a8505a7f8e4c3a0f7821648297d05cc760738b777d5149
\ No newline at end of file
+356d2209ea5f6b69ce15b62027c63419c2d039e52f01c74a3810a6317abf4fb0
\ No newline at end of file