use stoolap::Database;
#[test]
fn test_now_minus_interval_in_where() {
let db = Database::open("memory://const_fold_now").unwrap();
db.execute(
"CREATE TABLE events (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
name TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
)",
(),
)
.unwrap();
db.execute(
"INSERT INTO events (name, created_at) VALUES ('recent', NOW())",
(),
)
.unwrap();
db.execute(
"INSERT INTO events (name, created_at) VALUES ('old', NOW() - INTERVAL '48 hours')",
(),
)
.unwrap();
let results: Vec<String> = db
.query(
"SELECT name FROM events WHERE created_at > NOW() - INTERVAL '24 hours'",
(),
)
.unwrap()
.map(|r| r.unwrap().get::<String>(0).unwrap())
.collect();
assert_eq!(results, vec!["recent"]);
}
#[test]
fn test_arithmetic_constant_folding() {
let db = Database::open("memory://const_fold_arith").unwrap();
db.execute(
"CREATE TABLE numbers (id INTEGER PRIMARY KEY, value INTEGER NOT NULL)",
(),
)
.unwrap();
db.execute(
"INSERT INTO numbers (id, value) VALUES (1, 10), (2, 20), (3, 30)",
(),
)
.unwrap();
let results: Vec<i64> = db
.query(
"SELECT value FROM numbers WHERE value > 2 * 5 + 5 ORDER BY value",
(),
)
.unwrap()
.map(|r| r.unwrap().get::<i64>(0).unwrap())
.collect();
assert_eq!(results, vec![20, 30]);
}
#[test]
fn test_function_constant_folding() {
let db = Database::open("memory://const_fold_func").unwrap();
db.execute(
"CREATE TABLE items (id INTEGER PRIMARY KEY, name TEXT NOT NULL)",
(),
)
.unwrap();
db.execute(
"INSERT INTO items (id, name) VALUES (1, 'HELLO'), (2, 'world')",
(),
)
.unwrap();
let results: Vec<String> = db
.query("SELECT name FROM items WHERE name = UPPER('hello')", ())
.unwrap()
.map(|r| r.unwrap().get::<String>(0).unwrap())
.collect();
assert_eq!(results, vec!["HELLO"]);
}
#[test]
fn test_current_date_constant_folding() {
let db = Database::open("memory://const_fold_date").unwrap();
db.execute(
"CREATE TABLE logs (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
msg TEXT NOT NULL,
ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
)",
(),
)
.unwrap();
db.execute("INSERT INTO logs (msg) VALUES ('today')", ())
.unwrap();
let count: i64 = db
.query("SELECT COUNT(*) FROM logs WHERE ts >= CURRENT_DATE", ())
.unwrap()
.next()
.unwrap()
.unwrap()
.get(0)
.unwrap();
assert_eq!(count, 1);
}
#[test]
fn test_interval_arithmetic_folding() {
let db = Database::open("memory://const_fold_interval").unwrap();
db.execute(
"CREATE TABLE schedules (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
event_name TEXT NOT NULL,
scheduled_at TIMESTAMP NOT NULL
)",
(),
)
.unwrap();
db.execute(
"INSERT INTO schedules (event_name, scheduled_at) VALUES
('past', NOW() - INTERVAL '2 days'),
('soon', NOW() + INTERVAL '1 hour'),
('future', NOW() + INTERVAL '7 days')",
(),
)
.unwrap();
let results: Vec<String> = db
.query(
"SELECT event_name FROM schedules
WHERE scheduled_at > NOW() AND scheduled_at < NOW() + INTERVAL '24 hours'",
(),
)
.unwrap()
.map(|r| r.unwrap().get::<String>(0).unwrap())
.collect();
assert_eq!(results, vec!["soon"]);
}
#[test]
fn test_select_constant_expression() {
let db = Database::open("memory://const_fold_select").unwrap();
let val: i64 = db
.query("SELECT 1 + 2 + 3", ())
.unwrap()
.next()
.unwrap()
.unwrap()
.get(0)
.unwrap();
assert_eq!(val, 6);
}
#[test]
fn test_mixed_constant_and_column() {
let db = Database::open("memory://const_fold_mixed").unwrap();
db.execute(
"CREATE TABLE data (id INTEGER PRIMARY KEY, x INTEGER NOT NULL)",
(),
)
.unwrap();
db.execute(
"INSERT INTO data (id, x) VALUES (1, 5), (2, 15), (3, 25)",
(),
)
.unwrap();
let results: Vec<i64> = db
.query("SELECT x + (2 * 3) FROM data ORDER BY id", ())
.unwrap()
.map(|r| r.unwrap().get::<i64>(0).unwrap())
.collect();
assert_eq!(results, vec![11, 21, 31]);
}