diff --git a/core/lib.rs b/core/lib.rs index 9d661e8e4..f1411d37a 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -531,7 +531,7 @@ impl Connection { } pub fn checkpoint(&self) -> Result { - let checkpoint_result = self.pager.clear_page_cache(); + let checkpoint_result = self.pager.wal_checkpoint(); Ok(checkpoint_result) } diff --git a/core/storage/page_cache.rs b/core/storage/page_cache.rs index 3dffd27bc..743832d12 100644 --- a/core/storage/page_cache.rs +++ b/core/storage/page_cache.rs @@ -474,8 +474,6 @@ impl DumbLruPageCache { ); } - #[cfg(test)] - /// For testing purposes, in case we use cursor api directly, we might want to unmark pages as dirty because we bypass the WAL transaction layer pub fn unset_dirty_all_pages(&mut self) { for node in self.map.borrow_mut().iter_mut() { unsafe { @@ -572,7 +570,6 @@ impl PageHashMap { self.buckets.iter().flat_map(|bucket| bucket.iter()) } - #[cfg(test)] pub fn iter_mut(&mut self) -> impl Iterator { self.buckets.iter_mut().flat_map(|bucket| bucket.iter_mut()) } diff --git a/core/storage/pager.rs b/core/storage/pager.rs index 204d99d17..43af87f89 100644 --- a/core/storage/pager.rs +++ b/core/storage/pager.rs @@ -547,8 +547,19 @@ impl Pager { } } - // WARN: used for testing purposes - pub fn clear_page_cache(&self) -> CheckpointResult { + /// Invalidates entire page cache by removing all dirty and clean pages. Usually used in case + /// of a rollback or in case we want to invalidate page cache after starting a read transaction + /// right after new writes happened which would invalidate current page cache. + pub fn clear_page_cache(&self) { + self.dirty_pages.borrow_mut().clear(); + self.page_cache.write().unset_dirty_all_pages(); + self.page_cache + .write() + .clear() + .expect("Failed to clear page cache"); + } + + pub fn wal_checkpoint(&self) -> CheckpointResult { let checkpoint_result: CheckpointResult; loop { match self.wal.borrow_mut().checkpoint( diff --git a/core/vdbe/execute.rs b/core/vdbe/execute.rs index f4123004a..84b9d7562 100644 --- a/core/vdbe/execute.rs +++ b/core/vdbe/execute.rs @@ -1641,6 +1641,10 @@ pub fn op_halt( else { unreachable!("unexpected Insn {:?}", insn) }; + if *err_code > 0 { + // invalidate page cache in case of error + pager.clear_page_cache(); + } match *err_code { 0 => {} SQLITE_CONSTRAINT_PRIMARYKEY => { diff --git a/tests/integration/query_processing/test_write_path.rs b/tests/integration/query_processing/test_write_path.rs index 3205ab466..624fcca55 100644 --- a/tests/integration/query_processing/test_write_path.rs +++ b/tests/integration/query_processing/test_write_path.rs @@ -269,7 +269,6 @@ fn test_wal_checkpoint() -> anyhow::Result<()> { } do_flush(&conn, &tmp_db)?; - conn.clear_page_cache()?; let list_query = "SELECT * FROM test LIMIT 1"; let mut current_index = 0; run_query_on_row(&tmp_db, &conn, list_query, |row: &Row| {