diff --git a/core/lib.rs b/core/lib.rs index 637e91c92..18b721790 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -40,6 +40,7 @@ pub mod numeric; mod numeric; use crate::storage::checksum::CHECKSUM_REQUIRED_RESERVED_BYTES; +use crate::storage::pager::{AutoVacuumMode, HeaderRef}; use crate::translate::display::PlanContext; use crate::translate::pragma::TURSO_CDC_DEFAULT_TABLE_NAME; #[cfg(all(feature = "fs", feature = "conn_raw_api"))] @@ -549,6 +550,29 @@ impl Database { pager.enable_encryption(self.opts.enable_encryption); let pager = Arc::new(pager); + if self.db_state.is_initialized() { + let header_ref = pager.io.block(|| HeaderRef::from_pager(&pager))?; + + let header = header_ref.borrow(); + + let mode = if header.vacuum_mode_largest_root_page.get() > 0 { + if header.incremental_vacuum_enabled.get() > 0 { + AutoVacuumMode::Incremental + } else { + AutoVacuumMode::Full + } + } else { + AutoVacuumMode::None + }; + + pager.set_auto_vacuum_mode(mode); + + tracing::debug!( + "Opened existing database. Detected auto_vacuum_mode from header: {:?}", + mode + ); + } + let page_size = pager.get_page_size_unchecked(); let default_cache_size = pager diff --git a/core/storage/btree.rs b/core/storage/btree.rs index 31e89b01f..1a9f7bbd4 100644 --- a/core/storage/btree.rs +++ b/core/storage/btree.rs @@ -5887,6 +5887,7 @@ pub(crate) enum PageCategory { Overflow, FreeListTrunk, FreePage, + PointerMap, } #[derive(Clone)] diff --git a/core/storage/pager.rs b/core/storage/pager.rs index 2e6b50920..5b1d9c685 100644 --- a/core/storage/pager.rs +++ b/core/storage/pager.rs @@ -2591,7 +2591,7 @@ impl CreateBTreeFlags { ** identifies the parent page in the btree. */ #[cfg(not(feature = "omit_autovacuum"))] -mod ptrmap { +pub(crate) mod ptrmap { use crate::{storage::sqlite3_ondisk::PageSize, LimboError, Result}; // Constants diff --git a/core/vdbe/execute.rs b/core/vdbe/execute.rs index 962f1b3bc..a500b1f39 100644 --- a/core/vdbe/execute.rs +++ b/core/vdbe/execute.rs @@ -7974,6 +7974,31 @@ pub fn op_integrity_check( expected_count: integrity_check_state.freelist_count.expected_count, }); } + + let auto_vacuum_mode = pager.get_auto_vacuum_mode(); + if !matches!( + auto_vacuum_mode, + crate::storage::pager::AutoVacuumMode::None + ) { + tracing::debug!("Integrity check: auto-vacuum mode detected ({:?}). Scanning for pointer-map pages.", auto_vacuum_mode); + let page_size = pager.get_page_size_unchecked().get() as usize; + + for page_number in 2..=integrity_check_state.db_size { + if crate::storage::pager::ptrmap::is_ptrmap_page( + page_number as u32, + page_size, + ) { + tracing::debug!("Integrity check: Found and marking pointer-map page as visited: page_id={}", page_number); + + integrity_check_state.start( + page_number as i64, + PageCategory::PointerMap, + errors, + ); + } + } + } + for page_number in 2..=integrity_check_state.db_size { if !integrity_check_state .page_reference