add scaffolding for supporting wal checkpoint

This commit is contained in:
sonhmai 2025-01-15 13:00:56 +07:00 committed by sonhmai
parent 876788588b
commit 66d6291f32
8 changed files with 177 additions and 0 deletions

100
Cargo.lock generated
View file

@ -146,6 +146,22 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "assert_cmd"
version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d"
dependencies = [
"anstyle",
"bstr",
"doc-comment",
"libc",
"predicates",
"predicates-core",
"predicates-tree",
"wait-timeout",
]
[[package]]
name = "autocfg"
version = "1.4.0"
@ -197,6 +213,17 @@ dependencies = [
"generic-array",
]
[[package]]
name = "bstr"
version = "1.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0"
dependencies = [
"memchr",
"regex-automata",
"serde",
]
[[package]]
name = "bumpalo"
version = "3.16.0"
@ -391,6 +418,12 @@ dependencies = [
"memchr",
]
[[package]]
name = "comma"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335"
[[package]]
name = "concurrent-queue"
version = "2.5.0"
@ -568,6 +601,12 @@ dependencies = [
"uuid",
]
[[package]]
name = "difflib"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
[[package]]
name = "digest"
version = "0.10.7"
@ -599,6 +638,12 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "downcast"
version = "0.11.0"
@ -748,6 +793,15 @@ dependencies = [
"winapi",
]
[[package]]
name = "float-cmp"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
dependencies = [
"num-traits",
]
[[package]]
name = "fragile"
version = "2.0.0"
@ -1182,6 +1236,7 @@ name = "limbo"
version = "0.0.13"
dependencies = [
"anyhow",
"assert_cmd",
"clap",
"cli-table",
"csv",
@ -1190,6 +1245,8 @@ dependencies = [
"env_logger 0.10.2",
"limbo_core",
"miette",
"predicates",
"rexpect",
"rustyline",
]
@ -1479,6 +1536,17 @@ dependencies = [
"libc",
]
[[package]]
name = "nix"
version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
dependencies = [
"bitflags 2.6.0",
"cfg-if",
"libc",
]
[[package]]
name = "nix"
version = "0.29.0"
@ -1501,6 +1569,12 @@ dependencies = [
"minimal-lexical",
]
[[package]]
name = "normalize-line-endings"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
[[package]]
name = "num-format"
version = "0.4.4"
@ -1775,7 +1849,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573"
dependencies = [
"anstyle",
"difflib",
"float-cmp",
"normalize-line-endings",
"predicates-core",
"regex",
]
[[package]]
@ -2011,6 +2089,19 @@ version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2"
[[package]]
name = "rexpect"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c020234fb542618dc3e3d43724e9d93f87e1db74040a76a8c4e830220fb9b20d"
dependencies = [
"comma",
"nix 0.27.1",
"regex",
"tempfile",
"thiserror 1.0.69",
]
[[package]]
name = "rgb"
version = "0.8.50"
@ -2579,6 +2670,15 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wait-timeout"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
dependencies = [
"libc",
]
[[package]]
name = "walkdir"
version = "2.5.0"

View file

@ -32,3 +32,11 @@ miette = { version = "7.4.0", features = ["fancy"] }
[features]
io_uring = ["limbo_core/io_uring"]
[dev-dependencies]
assert_cmd = "^2"
predicates = "^3"
# rexpect does not support windows https://github.com/rust-cli/rexpect/issues/11
#[target.'cfg(not(windows))'.dev-dependencies]
rexpect = "0.6.0"

35
cli/tests/test_journal.rs Normal file
View file

@ -0,0 +1,35 @@
use assert_cmd::cargo::cargo_bin;
use rexpect::error::*;
use rexpect::session::spawn_command;
use std::process;
#[test]
fn test_pragma_journal_mode_wal() -> Result<(), Error> {
let mut child = spawn_command(run_cli(), Some(1000))?;
child.exp_regex("limbo>")?; // skip everything until limbo cursor appear
child.exp_regex(".?")?;
child.send_line("pragma journal_mode;")?;
child.exp_string("wal")?;
child.send_line(".quit")?;
child.exp_eof()?;
Ok(())
}
#[ignore = "wal checkpoint not yet implemented"]
#[test]
fn test_pragma_wal_checkpoint() -> Result<(), Error> {
let mut child = spawn_command(run_cli(), Some(1000))?;
child.exp_regex("limbo>")?; // skip everything until limbo cursor appear
child.exp_regex(".?")?;
child.send_line("pragma wal_checkpoint;")?;
child.exp_string("0|0|0")?;
child.send_line(".quit")?;
child.exp_eof()?;
Ok(())
}
fn run_cli() -> process::Command {
let bin_path = cargo_bin("limbo");
let mut cmd = process::Command::new(bin_path);
cmd
}

View file

@ -592,6 +592,10 @@ fn update_pragma(
query_pragma("journal_mode", header, program)?;
Ok(())
}
PragmaName::WalCheckpoint => {
// TODO
Ok(())
}
}
}
@ -618,6 +622,12 @@ fn query_pragma(
dest: register,
});
}
PragmaName::WalCheckpoint => {
program.emit_insn(Insn::Checkpoint {
reg: 12, // TODO fix hard-coded
dest: register,
});
}
}
program.emit_insn(Insn::ResultRow {

View file

@ -84,6 +84,15 @@ pub fn insn_to_str(
0,
format!("r[{}]=~r[{}]", dest, reg),
),
Insn::Checkpoint { reg, dest } => (
"Checkpoint",
*reg as i32,
*dest as i32,
0,
OwnedValue::build_text(Rc::new("".to_string())),
0,
format!("r[{}]=~r[{}]", dest, reg),
),
Insn::Remainder { lhs, rhs, dest } => (
"Remainder",
*lhs as i32,

View file

@ -66,6 +66,12 @@ pub enum Insn {
reg: usize,
dest: usize,
},
// Checkpoint the database (applying wal file content to database file).
Checkpoint {
// TODO support registers as in sqlite
reg: usize,
dest: usize,
},
// Divide lhs by rhs and place the remainder in dest register.
Remainder {
lhs: usize,

View file

@ -362,6 +362,12 @@ impl Program {
state.registers[*dest] = exec_bit_not(&state.registers[*reg]);
state.pc += 1;
}
Insn::Checkpoint { reg: _, dest } => {
// Write 1 (checkpoint SQLITE_BUSY) or 0 (not busy).
// fixme currently hard coded not implemented
state.registers[*dest] = OwnedValue::Integer(0);
state.pc += 1;
}
Insn::Null { dest, dest_end } => {
if let Some(dest_end) = dest_end {
for i in *dest..=*dest_end {

View file

@ -1591,6 +1591,8 @@ pub enum PragmaName {
CacheSize,
/// `journal_mode` pragma
JournalMode,
/// trigger a checkpoint to run on database(s) if WAL is enabled
WalCheckpoint,
}
impl FromStr for PragmaName {
@ -1599,6 +1601,7 @@ impl FromStr for PragmaName {
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"cache_size" => Ok(PragmaName::CacheSize),
"wal_checkpoint" => Ok(PragmaName::WalCheckpoint),
"journal_mode" => Ok(PragmaName::JournalMode),
_ => Err(()),
}