From 3c0af3e389832f22844dc342c4b76b3f302a55eb Mon Sep 17 00:00:00 2001 From: Nikita Sivukhin Date: Tue, 22 Jul 2025 21:34:49 +0400 Subject: [PATCH] small adjustments --- core/error.rs | 2 ++ core/lib.rs | 6 ++++++ core/storage/wal.rs | 2 +- sqlite3/src/lib.rs | 9 ++++++++- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/core/error.rs b/core/error.rs index 15dfa4089..7dd4ccdf9 100644 --- a/core/error.rs +++ b/core/error.rs @@ -59,6 +59,8 @@ pub enum LimboError { ReadOnly, #[error("Database is busy")] Busy, + #[error("Conflict: {0}")] + Conflict(String) } #[macro_export] diff --git a/core/lib.rs b/core/lib.rs index b11083d08..f088bd95d 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -809,10 +809,14 @@ impl Connection { self.pager.borrow().wal_get_frame(frame_no, frame) } + /// Insert `frame` (header included) at the position `frame_no` in the WAL + /// If WAL already has frame at that position - turso-db will compare content of the page and either report conflict or return OK + /// If attempt to write frame at the position `frame_no` will create gap in the WAL - method will return error pub fn wal_insert_frame(&self, frame_no: u32, frame: &[u8]) -> Result<()> { self.pager.borrow().wal_insert_frame(frame_no, frame) } + /// Start WAL session by initiating read+write transaction for this connection pub fn wal_insert_begin(&self) -> Result<()> { let pager = self.pager.borrow(); match pager.io.block(|| pager.begin_read_tx())? { @@ -829,6 +833,8 @@ impl Connection { Ok(()) } + /// Finish WAL session by ending read+write transaction taken in the [Self::wal_insert_begin] method + /// All frames written after last commit frame (db_size > 0) within the session will be rolled back pub fn wal_insert_end(&self) -> Result<()> { let pager = self.pager.borrow(); let mut wal = pager.wal.borrow_mut(); diff --git a/core/storage/wal.rs b/core/storage/wal.rs index adcbfee00..63297f7c2 100644 --- a/core/storage/wal.rs +++ b/core/storage/wal.rs @@ -705,7 +705,7 @@ impl Wal for WalFile { )?; self.io.wait_for_completion(c)?; return if conflict.get() { - Err(LimboError::InvalidArgument(format!( + Err(LimboError::Conflict(format!( "frame content differs from the WAL: frame_id={frame_id}" ))) } else { diff --git a/sqlite3/src/lib.rs b/sqlite3/src/lib.rs index 8d2c2c0fe..ad2cf1c52 100644 --- a/sqlite3/src/lib.rs +++ b/sqlite3/src/lib.rs @@ -3,7 +3,7 @@ use std::ffi::{self, CStr, CString}; use tracing::trace; -use turso_core::Value; +use turso_core::{LimboError, Value}; use std::sync::{Arc, Mutex}; @@ -1218,6 +1218,7 @@ pub unsafe extern "C" fn libsql_wal_insert_frame( frame_no: u32, p_frame: *const u8, frame_len: u32, + p_conflict: *mut i32, ) -> ffi::c_int { if db.is_null() { return SQLITE_MISUSE; @@ -1227,6 +1228,12 @@ pub unsafe extern "C" fn libsql_wal_insert_frame( let frame = std::slice::from_raw_parts(p_frame, frame_len as usize); match db.conn.wal_insert_frame(frame_no, frame) { Ok(()) => SQLITE_OK, + Err(LimboError::Conflict(..)) => { + if !p_conflict.is_null() { + *p_conflict = 1; + } + SQLITE_ERROR + } Err(_) => SQLITE_ERROR, } }