use stoolap::Database;
fn setup_time_test_table(db: &Database) {
db.execute(
"CREATE TABLE time_functions_test (
id INTEGER,
employee_name TEXT,
department TEXT,
event_timestamp TIMESTAMP
)",
(),
)
.expect("Failed to create test table");
db.execute(
"INSERT INTO time_functions_test (id, employee_name, department, event_timestamp) VALUES
(1, 'Alice', 'Engineering', TIMESTAMP '2021-03-15 09:15:30'),
(2, 'Bob', 'Engineering', TIMESTAMP '2021-03-15 10:25:45'),
(3, 'Charlie', 'Marketing', TIMESTAMP '2021-03-15 11:35:15'),
(4, 'Diana', 'Marketing', TIMESTAMP '2021-05-20 14:45:10'),
(5, 'Eve', 'Finance', TIMESTAMP '2022-01-10 08:55:20')",
(),
)
.expect("Failed to insert test data");
}
fn setup_sales_table(db: &Database) {
db.execute(
"CREATE TABLE time_function_sales (
id INTEGER,
product_id INTEGER,
amount FLOAT,
transaction_time TIMESTAMP
)",
(),
)
.expect("Failed to create sales table");
db.execute(
"INSERT INTO time_function_sales (id, product_id, amount, transaction_time) VALUES
(1, 101, 50.0, TIMESTAMP '2023-01-01 09:15:00'),
(2, 102, 25.0, TIMESTAMP '2023-01-01 09:30:00'),
(3, 101, 75.0, TIMESTAMP '2023-01-01 10:15:00'),
(4, 103, 100.0, TIMESTAMP '2023-01-01 10:45:00'),
(5, 102, 35.0, TIMESTAMP '2023-01-01 11:15:00'),
(6, 101, 60.0, TIMESTAMP '2023-01-01 11:45:00')",
(),
)
.expect("Failed to insert sales data");
}
#[test]
fn test_date_trunc_year() {
let db = Database::open("memory://time_trunc_year").expect("Failed to create database");
setup_time_test_table(&db);
let result = db
.query(
"SELECT DATE_TRUNC('year', event_timestamp) AS year_trunc
FROM time_functions_test
ORDER BY id",
(),
)
.expect("Failed to query");
let mut results: Vec<String> = Vec::new();
for row in result {
let row = row.expect("Failed to get row");
let truncated: String = row.get(0).unwrap();
results.push(truncated);
}
assert_eq!(results.len(), 5, "Expected 5 rows");
assert!(
results[0].contains("2021-01-01"),
"Expected first date to be truncated to 2021-01-01, got {}",
results[0]
);
}
#[test]
fn test_date_trunc_month() {
let db = Database::open("memory://time_trunc_month").expect("Failed to create database");
setup_time_test_table(&db);
let result = db
.query(
"SELECT DATE_TRUNC('month', event_timestamp) AS month_trunc
FROM time_functions_test
WHERE id = 1",
(),
)
.expect("Failed to query");
for row in result {
let row = row.expect("Failed to get row");
let truncated: String = row.get(0).unwrap();
assert!(
truncated.contains("2021-03-01"),
"Expected date truncated to 2021-03-01, got {}",
truncated
);
}
}
#[test]
fn test_date_trunc_day() {
let db = Database::open("memory://time_trunc_day").expect("Failed to create database");
setup_time_test_table(&db);
let result = db
.query(
"SELECT DATE_TRUNC('day', event_timestamp) AS day_trunc
FROM time_functions_test
WHERE id = 1",
(),
)
.expect("Failed to query");
for row in result {
let row = row.expect("Failed to get row");
let truncated: String = row.get(0).unwrap();
assert!(
truncated.contains("2021-03-15"),
"Expected date truncated to 2021-03-15, got {}",
truncated
);
}
}
#[test]
fn test_time_trunc_hour() {
let db = Database::open("memory://time_trunc_hour").expect("Failed to create database");
setup_time_test_table(&db);
let result = db
.query(
"SELECT TIME_TRUNC('1h', event_timestamp) AS hour_trunc
FROM time_functions_test
ORDER BY id",
(),
)
.expect("Failed to query");
let mut results: Vec<String> = Vec::new();
for row in result {
let row = row.expect("Failed to get row");
let truncated: String = row.get(0).unwrap();
results.push(truncated);
}
assert_eq!(results.len(), 5, "Expected 5 rows");
assert!(
results[0].contains("09:00:00"),
"Expected first time to be truncated to 09:00:00, got {}",
results[0]
);
}
#[test]
fn test_time_trunc_minutes() {
let db = Database::open("memory://time_trunc_min").expect("Failed to create database");
setup_time_test_table(&db);
let result = db
.query(
"SELECT TIME_TRUNC('15m', event_timestamp) AS minute_trunc
FROM time_functions_test
WHERE id = 1",
(),
)
.expect("Failed to query");
for row in result {
let row = row.expect("Failed to get row");
let truncated: String = row.get(0).unwrap();
assert!(
truncated.contains("09:15:00"),
"Expected time truncated to 09:15:00, got {}",
truncated
);
}
}
#[test]
fn test_time_trunc_group_by() {
let db = Database::open("memory://time_trunc_group").expect("Failed to create database");
setup_sales_table(&db);
let result = db
.query(
"SELECT
TIME_TRUNC('1h', transaction_time) AS hour_bucket,
SUM(amount) AS total_sales
FROM time_function_sales
GROUP BY TIME_TRUNC('1h', transaction_time)
ORDER BY hour_bucket",
(),
)
.expect("Failed to query");
let mut buckets: Vec<(String, f64)> = Vec::new();
for row in result {
let row = row.expect("Failed to get row");
let bucket: String = row.get(0).unwrap();
let sales: f64 = row.get(1).unwrap();
buckets.push((bucket, sales));
}
assert_eq!(buckets.len(), 3, "Expected 3 hour buckets");
for (bucket, sales) in &buckets {
if bucket.contains("09:") {
assert!(
(*sales - 75.0).abs() < 0.001,
"Expected 75.0 for 9:00 hour bucket, got {}",
sales
);
} else if bucket.contains("10:") {
assert!(
(*sales - 175.0).abs() < 0.001,
"Expected 175.0 for 10:00 hour bucket, got {}",
sales
);
} else if bucket.contains("11:") {
assert!(
(*sales - 95.0).abs() < 0.001,
"Expected 95.0 for 11:00 hour bucket, got {}",
sales
);
}
}
}
#[test]
fn test_date_trunc_group_by() {
let db = Database::open("memory://date_trunc_group").expect("Failed to create database");
setup_time_test_table(&db);
let result = db
.query(
"SELECT
DATE_TRUNC('year', event_timestamp) AS year_bucket,
COUNT(*) AS event_count
FROM time_functions_test
GROUP BY DATE_TRUNC('year', event_timestamp)
ORDER BY year_bucket",
(),
)
.expect("Failed to query");
let mut buckets: Vec<(String, i64)> = Vec::new();
for row in result {
let row = row.expect("Failed to get row");
let bucket: String = row.get(0).unwrap();
let count: i64 = row.get(1).unwrap();
buckets.push((bucket, count));
}
assert_eq!(buckets.len(), 2, "Expected 2 year buckets");
for (bucket, count) in &buckets {
if bucket.contains("2021") {
assert_eq!(*count, 4, "Expected 4 events in 2021");
} else if bucket.contains("2022") {
assert_eq!(*count, 1, "Expected 1 event in 2022");
}
}
}
#[test]
fn test_date_trunc_month_group_by() {
let db = Database::open("memory://date_trunc_month_group").expect("Failed to create database");
setup_time_test_table(&db);
let result = db
.query(
"SELECT
DATE_TRUNC('month', event_timestamp) AS month_bucket,
COUNT(*) AS event_count
FROM time_functions_test
GROUP BY DATE_TRUNC('month', event_timestamp)
ORDER BY month_bucket",
(),
)
.expect("Failed to query");
let mut count = 0;
for row in result {
let _ = row.expect("Failed to get row");
count += 1;
}
assert_eq!(count, 3, "Expected 3 month buckets");
}
#[test]
fn test_time_trunc_30min() {
let db = Database::open("memory://time_trunc_30min").expect("Failed to create database");
setup_sales_table(&db);
let result = db
.query(
"SELECT TIME_TRUNC('30m', transaction_time) AS half_hour_bucket
FROM time_function_sales
ORDER BY id",
(),
)
.expect("Failed to query");
let mut results: Vec<String> = Vec::new();
for row in result {
let row = row.expect("Failed to get row");
let bucket: String = row.get(0).unwrap();
results.push(bucket);
}
assert_eq!(results.len(), 6, "Expected 6 rows");
assert!(
results[0].contains("09:00:00"),
"Expected 09:15 truncated to 09:00, got {}",
results[0]
);
assert!(
results[1].contains("09:30:00"),
"Expected 09:30 to stay at 09:30, got {}",
results[1]
);
}
#[test]
fn test_date_trunc_week() {
let db = Database::open("memory://time_trunc_week").expect("Failed to create database");
setup_time_test_table(&db);
let result = db
.query(
"SELECT DATE_TRUNC('week', event_timestamp) AS week_trunc
FROM time_functions_test
WHERE id = 1",
(),
)
.expect("Failed to query");
for row in result {
let row = row.expect("Failed to get row");
let truncated: String = row.get(0).unwrap();
assert!(
truncated.contains("2021-03-15") || truncated.contains("2021-03-14"),
"Expected week start, got {}",
truncated
);
}
}
#[test]
fn test_date_trunc_quarter() {
let db = Database::open("memory://time_trunc_quarter").expect("Failed to create database");
setup_time_test_table(&db);
let result = db
.query(
"SELECT DATE_TRUNC('quarter', event_timestamp) AS quarter_trunc
FROM time_functions_test
WHERE id = 1",
(),
)
.expect("Failed to query");
for row in result {
let row = row.expect("Failed to get row");
let truncated: String = row.get(0).unwrap();
assert!(
truncated.contains("2021-01-01"),
"Expected quarter start 2021-01-01, got {}",
truncated
);
}
}