use fsqlite_core::connection::Connection;
use fsqlite_types::SqliteValue;
const TXNS: i64 = 64;
async fn read_value(conn: &Connection) -> Option<i64> {
conn.query_row("SELECT v FROM t WHERE id = 1;")
.await
.ok()
.and_then(|row| row.get(0).cloned())
.and_then(|value| match value {
SqliteValue::Integer(n) => Some(n),
_ => None,
})
}
#[test]
fn autocommit_increments_persist_without_external_oracle() {
asupersync::test_utils::run_test(|| async {
let dir = tempfile::tempdir().unwrap();
let db = dir
.path()
.join("seq_autocommit_no_oracle.db")
.to_string_lossy()
.into_owned();
let conn = Connection::open(&db).await.unwrap();
conn.execute("PRAGMA busy_timeout=5000;").await.unwrap();
conn.execute("PRAGMA fsqlite.concurrent_mode=ON;")
.await
.unwrap();
conn.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, v INTEGER NOT NULL);")
.await
.unwrap();
conn.execute("INSERT INTO t (id, v) VALUES (1, 0);")
.await
.unwrap();
for step in 0..TXNS {
assert_eq!(
conn.execute("UPDATE t SET v = v + 1 WHERE id = 1;")
.await
.unwrap(),
1,
"autocommit increment {step} should affect exactly one row"
);
assert_eq!(
read_value(&conn).await,
Some(step + 1),
"autocommit increment {step} must be visible to the writing connection"
);
}
drop(conn);
let verifier = Connection::open(&db).await.unwrap();
assert_eq!(
read_value(&verifier).await,
Some(TXNS),
"every autocommit increment must be durable for a fresh connection"
);
});
}
#[test]
fn autocommit_increments_persist_without_reads_or_external_oracle() {
asupersync::test_utils::run_test(|| async {
let dir = tempfile::tempdir().unwrap();
let db = dir
.path()
.join("seq_autocommit_no_reads.db")
.to_string_lossy()
.into_owned();
let conn = Connection::open(&db).await.unwrap();
conn.execute("PRAGMA busy_timeout=5000;").await.unwrap();
conn.execute("PRAGMA fsqlite.concurrent_mode=ON;")
.await
.unwrap();
conn.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, v INTEGER NOT NULL);")
.await
.unwrap();
conn.execute("INSERT INTO t (id, v) VALUES (1, 0);")
.await
.unwrap();
for step in 0..TXNS {
assert_eq!(
conn.execute("UPDATE t SET v = v + 1 WHERE id = 1;")
.await
.unwrap(),
1,
"autocommit increment {step} should affect exactly one row"
);
}
drop(conn);
let verifier = Connection::open(&db).await.unwrap();
assert_eq!(
read_value(&verifier).await,
Some(TXNS),
"every autocommit increment must be durable without read-boundary refreshes"
);
});
}
#[test]
fn autocommit_increments_survive_interleaved_rusqlite_oracle() {
asupersync::test_utils::run_test(|| async {
let dir = tempfile::tempdir().unwrap();
let db = dir
.path()
.join("seq_autocommit_rusqlite_oracle.db")
.to_string_lossy()
.into_owned();
let conn = Connection::open(&db).await.unwrap();
conn.execute("PRAGMA busy_timeout=5000;").await.unwrap();
conn.execute("PRAGMA fsqlite.concurrent_mode=ON;")
.await
.unwrap();
conn.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, v INTEGER NOT NULL);")
.await
.unwrap();
conn.execute("INSERT INTO t (id, v) VALUES (1, 0);")
.await
.unwrap();
for step in 0..TXNS {
assert_eq!(
conn.execute("UPDATE t SET v = v + 1 WHERE id = 1;")
.await
.unwrap(),
1,
"autocommit increment {step} should affect exactly one row"
);
if step == 0 {
let oracle = rusqlite::Connection::open(&db).unwrap();
let value: i64 = oracle
.query_row("SELECT v FROM t WHERE id = 1;", [], |row| row.get(0))
.unwrap();
assert_eq!(
value, 1,
"oracle should observe the first committed increment"
);
}
}
drop(conn);
let verifier = Connection::open(&db).await.unwrap();
assert_eq!(
read_value(&verifier).await,
Some(TXNS),
"autocommit increments must remain durable even after an external SQLite \
connection opened (and possibly reset the WAL) mid-loop"
);
});
}