use stoolap::Database;
fn setup_large_table(db: &Database) {
db.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, val TEXT)", ())
.unwrap();
for batch_start in (1..=10_500).step_by(500) {
let batch_end = (batch_start + 499).min(10_500);
let values: Vec<String> = (batch_start..=batch_end)
.map(|i| format!("({}, 'row{}')", i, i))
.collect();
db.execute(&format!("INSERT INTO t VALUES {}", values.join(",")), ())
.unwrap();
}
}
#[test]
fn test_current_transaction_id_in_where_parallel() {
let db = Database::open("memory://txn_id_parallel").unwrap();
setup_large_table(&db);
let mut tx = db.begin().unwrap();
let mut rows = tx
.query(
"SELECT COUNT(*) FROM t WHERE CURRENT_TRANSACTION_ID() > 0",
(),
)
.unwrap();
let count = if let Some(Ok(row)) = rows.next() {
row.get::<i64>(0).unwrap()
} else {
0
};
drop(rows);
tx.rollback().unwrap();
assert_eq!(
count, 10_500,
"CURRENT_TRANSACTION_ID() > 0 should match all 10,500 rows via parallel filter"
);
}
#[test]
fn test_current_transaction_id_in_where_small() {
let db = Database::open("memory://txn_id_where").unwrap();
db.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, val TEXT)", ())
.unwrap();
db.execute("INSERT INTO t VALUES (1, 'a')", ()).unwrap();
db.execute("INSERT INTO t VALUES (2, 'b')", ()).unwrap();
db.execute("INSERT INTO t VALUES (3, 'c')", ()).unwrap();
let mut tx = db.begin().unwrap();
let mut rows = tx
.query(
"SELECT id FROM t WHERE CURRENT_TRANSACTION_ID() > 0 ORDER BY id",
(),
)
.unwrap();
let mut ids = Vec::new();
while let Some(Ok(row)) = rows.next() {
ids.push(row.get::<i64>(0).unwrap());
}
drop(rows);
tx.rollback().unwrap();
assert_eq!(
ids,
vec![1, 2, 3],
"CURRENT_TRANSACTION_ID() > 0 should match all rows in a transaction"
);
}
#[test]
fn test_current_transaction_id_is_not_null() {
let db = Database::open("memory://txn_id_not_null").unwrap();
db.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, val TEXT)", ())
.unwrap();
db.execute("INSERT INTO t VALUES (1, 'a')", ()).unwrap();
db.execute("INSERT INTO t VALUES (2, 'b')", ()).unwrap();
let mut tx = db.begin().unwrap();
let mut rows = tx
.query(
"SELECT id FROM t WHERE CURRENT_TRANSACTION_ID() IS NOT NULL ORDER BY id",
(),
)
.unwrap();
let mut ids = Vec::new();
while let Some(Ok(row)) = rows.next() {
ids.push(row.get::<i64>(0).unwrap());
}
drop(rows);
tx.rollback().unwrap();
assert_eq!(
ids,
vec![1, 2],
"CURRENT_TRANSACTION_ID() IS NOT NULL should match all rows in a transaction"
);
}
#[test]
fn test_current_transaction_id_null_in_autocommit() {
let db = Database::open("memory://txn_id_autocommit").unwrap();
db.execute("CREATE TABLE t (id INTEGER PRIMARY KEY, val TEXT)", ())
.unwrap();
db.execute("INSERT INTO t VALUES (1, 'a')", ()).unwrap();
let mut rows = db
.query("SELECT CURRENT_TRANSACTION_ID() IS NULL FROM t", ())
.unwrap();
if let Some(Ok(row)) = rows.next() {
let is_null = row.get::<bool>(0).unwrap();
assert!(
is_null,
"CURRENT_TRANSACTION_ID() should be NULL in auto-commit mode"
);
} else {
panic!("Expected one row");
}
}