]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Avoid some performance problems in the recover extension when recovering strategicall...
authordan <Dan Kennedy>
Tue, 9 Apr 2024 15:09:54 +0000 (15:09 +0000)
committerdan <Dan Kennedy>
Tue, 9 Apr 2024 15:09:54 +0000 (15:09 +0000)
FossilOrigin-Name: e66a834bbab9d71e02b70588ad4c71eae2e13b50e299b0269d488402bc4a7fc5

ext/recover/dbdata.c
ext/recover/recovercorrupt2.test
ext/recover/sqlite3recover.c
manifest
manifest.uuid

index b6cb26ecd38054f8dd7b1e74443df93e580fc5b1..ca6371026e571f7c0f678d6daf96e27223c8acaf 100644 (file)
@@ -494,6 +494,15 @@ static void dbdataValue(
   }
 }
 
+/* This macro is a copy of the MX_CELL() macro in the SQLite core. Given
+** a page-size, it returns the maximum number of cells that may be present
+** on the page.  */
+#define DBDATA_MX_CELL(pgsz) ((pgsz-8)/6)
+
+/* Maximum number of fields that may appear in a single record. This is
+** the "hard-limit", according to comments in sqliteLimit.h. */
+#define DBDATA_MX_FIELD 32676
+
 /*
 ** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
 */
@@ -522,6 +531,9 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
       assert( iOff+3+2<=pCsr->nPage );
       pCsr->iCell = pTab->bPtr ? -2 : 0;
       pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
+      if( pCsr->nCell>DBDATA_MX_CELL(pCsr->nPage) ){
+        pCsr->nCell = DBDATA_MX_CELL(pCsr->nPage);
+      }
     }
 
     if( pTab->bPtr ){
@@ -566,19 +578,19 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
         if( pCsr->iCell>=pCsr->nCell ){
           bNextPage = 1;
         }else{
+          int iCellPtr = iOff + 8 + nPointer + pCsr->iCell*2;
   
-          iOff += 8 + nPointer + pCsr->iCell*2;
-          if( iOff>pCsr->nPage ){
+          if( iCellPtr>pCsr->nPage ){
             bNextPage = 1;
           }else{
-            iOff = get_uint16(&pCsr->aPage[iOff]);
+            iOff = get_uint16(&pCsr->aPage[iCellPtr]);
           }
     
           /* For an interior node cell, skip past the child-page number */
           iOff += nPointer;
     
           /* Load the "byte of payload including overflow" field */
-          if( bNextPage || iOff>pCsr->nPage ){
+          if( bNextPage || iOff>pCsr->nPage || iOff<=iCellPtr ){
             bNextPage = 1;
           }else{
             iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
@@ -661,7 +673,9 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
         pCsr->iField++;
         if( pCsr->iField>0 ){
           sqlite3_int64 iType;
-          if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
+          if( pCsr->pHdrPtr>=&pCsr->pRec[pCsr->nRec] 
+           || pCsr->iField>=DBDATA_MX_FIELD
+          ){
             bNextPage = 1;
           }else{
             int szField = 0;
index 29acc27a352a7229e2b3b7985376cf40f4eac9e1..6c216308f0902ed9319978d24b3daa17ec328138 100644 (file)
@@ -524,5 +524,33 @@ do_test 7.1 {
   list [catch { $R finish } msg] $msg
 } {1 {file is not a database}}
 
+reset_db
+breakpoint
+do_test 8.0 {
+  sqlite3 db {}
+  db deserialize [decode_hexdb {
+| size 8192 pagesize 4096 filename db.sqlite
+| page 1 offset 0
+|      0: ac ae b3 76 74 65 20 66 6f 72 6d 61 74 20 33 00   ...vte format 3.
+|     16: 10 00 01 01 00 40 20 20 00 00 00 01 00 00 00 02   .....@  ........
+|     32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04   ................
+|     48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
+|     80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01   ................
+|     96: 00 2e 76 8a 0d ff ff ff 1e 0f cb 00 0f cb 00 00   ..v.............
+|   4032: 00 00 00 00 00 00 00 00 00 00 00 33 01 06 17 19   ...........3....
+|   4048: 19 01 43 74 61 62 6c 65 54 61 62 6c 65 30 54 61   ..CtableTable0Ta
+|   4064: 62 6c 65 30 02 43 52 45 41 54 45 20 54 41 42 4c   ble0.CREATE TABL
+|   4080: 45 20 54 61 62 6c 65 30 20 28 43 6f 6c 30 20 29   E Table0 (Col0 )
+| page 2 offset 4096
+|      0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
+| end db.sqlite
+}]} {}
+
+do_test 8.1 {
+  set R [sqlite3_recover_init db main test.db2]
+  catch { $R run }
+  list [catch { $R finish } msg] $msg
+} {0 {}}
+
 finish_test
 
index c445c51793b13272281317dffbc2da24e545e700..1d858c0ab914f5c39be00f3bd9cc86ca68185e31 100644 (file)
@@ -1189,7 +1189,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){
         if( bTable && !bVirtual ){
           if( SQLITE_ROW==sqlite3_step(pTblname) ){
             const char *zTbl = (const char*)sqlite3_column_text(pTblname, 0);
-            recoverAddTable(p, zTbl, iRoot);
+            if( zTbl ) recoverAddTable(p, zTbl, iRoot);
           }
           recoverReset(p, pTblname);
         }
index 8197099293079c699bc9b8f2c5e5d812f2742074..0fa7d973a968a6bf84baa889744971d65a32693e 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C The\sread-only\sCHECK-constraint\soptimization\sof\s[34ddf02d3d21151b]\sinhibits\sthe\nxfer\soptimization\sfor\stables\swith\sCHECK\sconstraints.\s\sHowever,\sthe\sxfer\noptimization\sis\srequired\sfor\scorrect\soperation\sof\sVACUUM\sINTO\son\stables\sthat\ncontain\sgenerated\scolumns.\sFix\sthis\sby\signoring\sCHECK\sconstraints\swhen\nqualifying\sthe\sxfer\soptimization\swhile\srunning\sVACUUM.\s\sProblem\sreported\sby\n[forum:/forumpost/3ec177d68fe7fa2c|forum\spost\s3ec177d68fe7fa2c].
-D 2024-04-09T13:57:27.143
+C Avoid\ssome\sperformance\sproblems\sin\sthe\srecover\sextension\swhen\srecovering\sstrategically\scorrupted\sdatabases.
+D 2024-04-09T15:09:54.458
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -478,13 +478,13 @@ F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69
 F ext/rbu/sqlite3rbu.c 4a3376c0fb9a844a799ac529fb81260523f6b13c9f629bc270c632dbae5fc1f8
 F ext/rbu/sqlite3rbu.h 9d923eb135c5d04aa6afd7c39ca47b0d1d0707c100e02f19fdde6a494e414304
 F ext/rbu/test_rbu.c ee6ede75147bc081fe9bc3931e6b206277418d14d3fbceea6fdc6216d9b47055
-F ext/recover/dbdata.c b7746c2ec801b453840831311be4b31f8c8f9dd97791060a69bbf12392c78949
+F ext/recover/dbdata.c d2e00d3cac74319c9c6def2e56ab2146b4f4ba5d820ab275e8da24e9766c247e
 F ext/recover/recover1.test c484d01502239f11b61f23c1cee9f5dd19fa17617f8974e42e74d64639c524cf
 F ext/recover/recover_common.tcl a61306c1eb45c0c3fc45652c35b2d4ec19729e340bdf65a272ce4c229cefd85a
 F ext/recover/recoverbuild.test c74170e0f7b02456af41838afeb5353fdb985a48cc2331d661bbabbca7c6b8e3
 F ext/recover/recoverclobber.test 3ba6c0c373c5c63d17e82eced64c05c57ccaf26c1abe1ca7141334022a79f32e
 F ext/recover/recovercorrupt.test 64c081ad1200ae77b447da99eb724785d6bf71715f394543dc7689642e92bf49
-F ext/recover/recovercorrupt2.test b9b974f006340a1300b5a7e687bd6097c5238498181c6f92d87406a77ece430b
+F ext/recover/recovercorrupt2.test 1418f1710debc24ff38276cedfcea234beb37a34205708e7e3e6d76cc4a979db
 F ext/recover/recoverfault.test 9d9f88eeb222615a25e7514f234c950d46bee20d24cd8db49d8fff8d650dcfe1
 F ext/recover/recoverfault2.test 730e7371bcda769554d15460cb23126abba1be8eca9539ccabf63623e7bb7e09
 F ext/recover/recoverold.test 68db3d6f85dd2b98e785b6c4da4f5eea4bbe52ccf6674d9a94c7506dc92596aa
@@ -492,7 +492,7 @@ F ext/recover/recoverpgsz.test 3658ab8e68475b1bb87d6af88baa04551c84b73280a566a1b
 F ext/recover/recoverrowid.test f948bf4024a5f41b0e21b8af80c60564c5b5d78c05a8d64fc00787715ff9f45f
 F ext/recover/recoverslowidx.test 5205a9742dd9490ee99950dabb622307355ef1662dea6a3a21030057bfd81411
 F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486
-F ext/recover/sqlite3recover.c e6eb20c469bcdb96f297f2241860bccabf9f036bfa7f3d47bcc6ca1191b108dc
+F ext/recover/sqlite3recover.c 65ef0f56301a16c0536c9839fb7e23540c9c4f75da0afe3b7b4d163c8f624404
 F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
 F ext/recover/test_recover.c fd871a40f2238022bedcbdf3cb493b91225edaa94d6ae8892af97a10e7ccc4ba
 F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -2184,8 +2184,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 c02956cd5cbf87027ba201b5d273e0efd429836ee6cabdc2f6d5b8096c876b7b
-R 14ee2c4095f13f5f59e64d6dfae705ab
-U drh
-Z 40f988c61dc13a84e5a7ab5ecd628e6c
+P a6e26e778812c8409fca77183e24d3b70189c4d02fce10c7e74cd4ccc8c8ea97
+R b9c21ffc9d4065568ea5ca672bfa94a1
+U dan
+Z a2100870dc1c15edbdbfdff1cdb0d2d0
 # Remove this line to create a well-formed Fossil manifest.
index 3f94593291156a76b8060b73758e752af1eb8201..e73f4c80e254fa9f1304956ce9b8b7220efb4d14 100644 (file)
@@ -1 +1 @@
-a6e26e778812c8409fca77183e24d3b70189c4d02fce10c7e74cd4ccc8c8ea97
\ No newline at end of file
+e66a834bbab9d71e02b70588ad4c71eae2e13b50e299b0269d488402bc4a7fc5
\ No newline at end of file