Files
turso/tests/integration/wal/test_wal.rs
Pekka Enberg 936ae307b7 core: Kill value type
We currently have two value types, `Value` and `OwnedValue`. The
original thinking was that `Value` is external type and `OwnedValue` is
internal type. However, this just results in unnecessary transformation
between the types as data crosses the Limbo library boundary.

Let's just follow SQLite here and consolidate on a single value type
(where `sqlite3_value` is just an alias for the internal `Mem` type).
The way this will eventually work is that we can have bunch of
pre-allocated `OwnedValue` objects in `ProgramState` and basically
return a reference to them all the way to the application itself, which
extracts the actual value.
2025-02-26 10:57:45 +02:00

95 lines
3.1 KiB
Rust

use crate::common::{do_flush, TempDatabase};
use limbo_core::{Connection, LimboError, Result, StepResult};
use std::cell::RefCell;
use std::rc::Rc;
#[allow(clippy::arc_with_non_send_sync)]
#[test]
fn test_wal_checkpoint_result() -> Result<()> {
let tmp_db = TempDatabase::new("test_wal.db");
let conn = tmp_db.connect_limbo();
conn.execute("CREATE TABLE t1 (id text);")?;
let res = execute_and_get_strings(&tmp_db, &conn, "pragma journal_mode;")?;
assert_eq!(res, vec!["wal"]);
conn.execute("insert into t1(id) values (1), (2);")?;
do_flush(&conn, &tmp_db).unwrap();
conn.execute("select * from t1;")?;
do_flush(&conn, &tmp_db).unwrap();
// checkpoint result should return > 0 num pages now as database has data
let res = execute_and_get_ints(&tmp_db, &conn, "pragma wal_checkpoint;")?;
println!("'pragma wal_checkpoint;' returns: {res:?}");
assert_eq!(res.len(), 3);
assert_eq!(res[0], 0); // checkpoint successfully
assert!(res[1] > 0); // num pages in wal
assert!(res[2] > 0); // num pages checkpointed successfully
Ok(())
}
/// Execute a statement and get strings result
pub(crate) fn execute_and_get_strings(
tmp_db: &TempDatabase,
conn: &Rc<Connection>,
sql: &str,
) -> Result<Vec<String>> {
let statement = conn.prepare(sql)?;
let stmt = Rc::new(RefCell::new(statement));
let mut result = Vec::new();
let mut stmt = stmt.borrow_mut();
while let Ok(step_result) = stmt.step() {
match step_result {
StepResult::Row => {
let row = stmt.row().unwrap();
for el in row.get_values() {
result.push(format!("{el}"));
}
}
StepResult::Done => break,
StepResult::Interrupt => break,
StepResult::IO => tmp_db.io.run_once()?,
StepResult::Busy => tmp_db.io.run_once()?,
}
}
Ok(result)
}
/// Execute a statement and get integers
pub(crate) fn execute_and_get_ints(
tmp_db: &TempDatabase,
conn: &Rc<Connection>,
sql: &str,
) -> Result<Vec<i64>> {
let statement = conn.prepare(sql)?;
let stmt = Rc::new(RefCell::new(statement));
let mut result = Vec::new();
let mut stmt = stmt.borrow_mut();
while let Ok(step_result) = stmt.step() {
match step_result {
StepResult::Row => {
let row = stmt.row().unwrap();
for value in row.get_values() {
let out = match value {
limbo_core::OwnedValue::Integer(i) => i,
_ => {
return Err(LimboError::ConversionError(format!(
"cannot convert {value} to int"
)))
}
};
result.push(*out);
}
}
StepResult::Done => break,
StepResult::Interrupt => break,
StepResult::IO => tmp_db.io.run_once()?,
StepResult::Busy => tmp_db.io.run_once()?,
}
}
Ok(result)
}