use stoolap::Database;
fn setup_first_last_table(db: &Database) {
db.execute(
"CREATE TABLE test_first_last (
id INTEGER,
group_id INTEGER,
value INTEGER,
text_value TEXT
)",
(),
)
.expect("Failed to create table");
db.execute(
"INSERT INTO test_first_last (id, group_id, value, text_value) VALUES
(1, 1, 10, 'Apple'),
(2, 1, 20, 'Banana'),
(3, 1, 30, 'Cherry'),
(4, 2, 15, 'Grape'),
(5, 2, 25, 'Lemon'),
(6, 2, NULL, 'Orange'),
(7, 3, NULL, NULL),
(8, 3, 35, 'Pear'),
(9, 3, 45, 'Plum')",
(),
)
.expect("Failed to insert data");
}
#[test]
fn test_first_function() {
let db = Database::open("memory://first_fn").expect("Failed to create database");
setup_first_last_table(&db);
let result = db
.query(
"SELECT group_id, FIRST(value), FIRST(text_value)
FROM test_first_last
GROUP BY group_id
ORDER BY group_id",
(),
)
.expect("Failed to query");
let mut row_count = 0;
for row in result {
let row = row.expect("Failed to get row");
let group_id: i64 = row.get(0).unwrap();
row_count += 1;
match group_id {
1 => {
let first_val: i64 = row.get(1).unwrap();
assert_eq!(first_val, 10, "Group 1 FIRST value should be 10");
let first_text: String = row.get(2).unwrap();
assert_eq!(first_text, "Apple", "Group 1 FIRST text should be Apple");
}
2 => {
let first_val: i64 = row.get(1).unwrap();
assert_eq!(first_val, 15, "Group 2 FIRST value should be 15");
let first_text: String = row.get(2).unwrap();
assert_eq!(first_text, "Grape", "Group 2 FIRST text should be Grape");
}
3 => {
let first_val: i64 = row.get(1).unwrap();
assert_eq!(first_val, 35, "Group 3 FIRST value should be 35");
let first_text: String = row.get(2).unwrap();
assert_eq!(first_text, "Pear", "Group 3 FIRST text should be Pear");
}
_ => panic!("Unexpected group_id: {}", group_id),
}
}
assert_eq!(row_count, 3, "Expected 3 groups");
}
#[test]
fn test_last_function() {
let db = Database::open("memory://last_fn").expect("Failed to create database");
setup_first_last_table(&db);
let result = db
.query(
"SELECT group_id, LAST(value), LAST(text_value)
FROM test_first_last
GROUP BY group_id
ORDER BY group_id",
(),
)
.expect("Failed to query");
let mut row_count = 0;
for row in result {
let row = row.expect("Failed to get row");
let group_id: i64 = row.get(0).unwrap();
row_count += 1;
match group_id {
1 => {
let last_val: i64 = row.get(1).unwrap();
assert_eq!(last_val, 30, "Group 1 LAST value should be 30");
let last_text: String = row.get(2).unwrap();
assert_eq!(last_text, "Cherry", "Group 1 LAST text should be Cherry");
}
2 => {
let last_val: i64 = row.get(1).unwrap();
assert_eq!(last_val, 25, "Group 2 LAST value should be 25");
let last_text: String = row.get(2).unwrap();
assert_eq!(last_text, "Orange", "Group 2 LAST text should be Orange");
}
3 => {
let last_val: i64 = row.get(1).unwrap();
assert_eq!(last_val, 45, "Group 3 LAST value should be 45");
let last_text: String = row.get(2).unwrap();
assert_eq!(last_text, "Plum", "Group 3 LAST text should be Plum");
}
_ => panic!("Unexpected group_id: {}", group_id),
}
}
assert_eq!(row_count, 3, "Expected 3 groups");
}
#[test]
fn test_first_with_all_nulls() {
let db = Database::open("memory://first_all_nulls").expect("Failed to create database");
db.execute("CREATE TABLE all_nulls (id INTEGER, value INTEGER)", ())
.expect("Failed to create table");
db.execute(
"INSERT INTO all_nulls (id, value) VALUES (1, NULL), (2, NULL), (3, NULL)",
(),
)
.expect("Failed to insert data");
let result = db
.query("SELECT FIRST(value) FROM all_nulls", ())
.expect("Failed to query");
let mut found = false;
for row in result {
let row = row.expect("Failed to get row");
let is_null = row.is_null(0);
assert!(is_null, "FIRST of all NULLs should be NULL");
found = true;
}
assert!(found, "Expected a result row");
}
#[test]
fn test_first_without_group_by() {
let db = Database::open("memory://first_no_group").expect("Failed to create database");
db.execute("CREATE TABLE simple_first (id INTEGER, value INTEGER)", ())
.expect("Failed to create table");
db.execute(
"INSERT INTO simple_first VALUES (1, 100), (2, 200), (3, 300)",
(),
)
.expect("Failed to insert data");
let first_val: i64 = db
.query_one("SELECT FIRST(value) FROM simple_first", ())
.expect("Failed to query");
assert_eq!(first_val, 100, "FIRST value should be 100");
}
#[test]
fn test_last_without_group_by() {
let db = Database::open("memory://last_no_group").expect("Failed to create database");
db.execute("CREATE TABLE simple_last (id INTEGER, value INTEGER)", ())
.expect("Failed to create table");
db.execute(
"INSERT INTO simple_last VALUES (1, 100), (2, 200), (3, 300)",
(),
)
.expect("Failed to insert data");
let last_val: i64 = db
.query_one("SELECT LAST(value) FROM simple_last", ())
.expect("Failed to query");
assert_eq!(last_val, 300, "LAST value should be 300");
}
#[test]
fn test_first_last_mixed_nulls() {
let db = Database::open("memory://first_last_mixed").expect("Failed to create database");
db.execute("CREATE TABLE mixed_nulls (id INTEGER, val INTEGER)", ())
.expect("Failed to create table");
db.execute(
"INSERT INTO mixed_nulls VALUES
(1, NULL),
(2, 10),
(3, 20),
(4, NULL),
(5, 30)",
(),
)
.expect("Failed to insert data");
let first_val: i64 = db
.query_one("SELECT FIRST(val) FROM mixed_nulls", ())
.expect("Failed to query FIRST");
assert_eq!(first_val, 10, "FIRST should be 10 (first non-NULL)");
let last_val: i64 = db
.query_one("SELECT LAST(val) FROM mixed_nulls", ())
.expect("Failed to query LAST");
assert_eq!(last_val, 30, "LAST should be 30 (last non-NULL)");
}