use sql_cli::data::data_view::DataView;
use sql_cli::data::datatable::{DataColumn, DataRow, DataTable, DataValue};
use sql_cli::data::query_engine::QueryEngine;
use std::sync::Arc;
fn get_value(view: &DataView, row_idx: usize, col_idx: usize) -> DataValue {
view.get_row(row_idx).unwrap().get(col_idx).unwrap().clone()
}
fn create_test_table() -> Arc<DataTable> {
let mut table = DataTable::new("test_dates");
table.add_column(DataColumn::new("id"));
table.add_column(DataColumn::new("order_date"));
table.add_column(DataColumn::new("ship_date"));
table.add_column(DataColumn::new("birth_date"));
table.add_column(DataColumn::new("last_login"));
table
.add_row(DataRow::new(vec![
DataValue::Integer(1),
DataValue::String("2024-01-15".to_string()),
DataValue::String("2024-01-16".to_string()), DataValue::String("1990-01-15".to_string()), DataValue::String("2024-01-10 10:30:00".to_string()), ]))
.unwrap();
table
.add_row(DataRow::new(vec![
DataValue::Integer(2),
DataValue::String("2024-01-20".to_string()),
DataValue::String("2024-01-25".to_string()), DataValue::String("1985-03-10".to_string()), DataValue::String("2024-01-15 14:45:00".to_string()), ]))
.unwrap();
table
.add_row(DataRow::new(vec![
DataValue::Integer(3),
DataValue::String("2024-02-01".to_string()),
DataValue::String("2024-01-22".to_string()), DataValue::String("2000-06-15".to_string()), DataValue::String("2024-01-31 09:00:00".to_string()), ]))
.unwrap();
Arc::new(table)
}
#[test]
fn test_datediff_days() {
let table = create_test_table();
let engine = QueryEngine::new();
let query = r"SELECT id, DATEDIFF('day', order_date, ship_date) as days_diff FROM test";
let result = engine.execute(table.clone(), query).unwrap();
assert_eq!(result.column_count(), 2);
assert_eq!(result.row_count(), 3);
assert_eq!(get_value(&result, 0, 1), DataValue::Integer(1)); assert_eq!(get_value(&result, 1, 1), DataValue::Integer(5)); assert_eq!(get_value(&result, 2, 1), DataValue::Integer(-10)); }
#[test]
fn test_datediff_years() {
let table = create_test_table();
let engine = QueryEngine::new();
let query = r"SELECT id, DATEDIFF('year', birth_date, order_date) as age_years FROM test";
let result = engine.execute(table.clone(), query).unwrap();
assert_eq!(result.column_count(), 2);
assert_eq!(result.row_count(), 3);
assert_eq!(get_value(&result, 0, 1), DataValue::Integer(34)); assert_eq!(get_value(&result, 1, 1), DataValue::Integer(38)); assert_eq!(get_value(&result, 2, 1), DataValue::Integer(23)); }
#[test]
fn test_datediff_with_datetime() {
let table = create_test_table();
let engine = QueryEngine::new();
let query =
r"SELECT id, DATEDIFF('hour', last_login, order_date) as hours_diff FROM test WHERE id = 1";
let result = engine.execute(table.clone(), query).unwrap();
assert_eq!(result.column_count(), 2);
assert_eq!(result.row_count(), 1);
let hours = match get_value(&result, 0, 1) {
DataValue::Integer(h) => h,
_ => panic!("Expected integer result"),
};
assert!(
(108..=112).contains(&hours),
"Hours difference should be around 110, got {hours}"
);
}
#[test]
fn test_now_function() {
let table = create_test_table();
let engine = QueryEngine::new();
let query = r"SELECT NOW() as current_time FROM test LIMIT 1";
let result = engine.execute(table.clone(), query).unwrap();
assert_eq!(result.column_count(), 1);
assert_eq!(result.row_count(), 1);
match get_value(&result, 0, 0) {
DataValue::DateTime(dt) | DataValue::String(dt) => {
assert!(dt.contains('-'));
assert!(dt.contains(':'));
}
_ => panic!("NOW() should return a datetime string"),
}
}
#[test]
fn test_today_function() {
let table = create_test_table();
let engine = QueryEngine::new();
let query = r"SELECT TODAY() as current_date FROM test LIMIT 1";
let result = engine.execute(table.clone(), query).unwrap();
assert_eq!(result.column_count(), 1);
assert_eq!(result.row_count(), 1);
match get_value(&result, 0, 0) {
DataValue::String(dt) => {
assert!(dt.contains('-'));
assert!(!dt.contains(':')); assert_eq!(dt.len(), 10); }
_ => panic!("TODAY() should return a date string"),
}
}
#[test]
fn test_datediff_with_now() {
let table = create_test_table();
let engine = QueryEngine::new();
let query =
r"SELECT id, DATEDIFF('day', order_date, NOW()) as days_since FROM test WHERE id = 1";
let result = engine.execute(table.clone(), query).unwrap();
assert_eq!(result.column_count(), 2);
assert_eq!(result.row_count(), 1);
match get_value(&result, 0, 1) {
DataValue::Integer(days) => {
assert!(days > 0, "Days since order should be positive");
assert!(days > 200, "Should be more than 200 days from Jan 2024");
}
_ => panic!("Expected integer result"),
}
}
#[test]
fn test_datediff_in_where_clause() {
let table = create_test_table();
let engine = QueryEngine::new();
let query = r"SELECT id, order_date, ship_date FROM test WHERE DATEDIFF('day', order_date, ship_date) > 3";
let result = engine.execute(table.clone(), query).unwrap();
assert_eq!(result.column_count(), 3);
assert_eq!(result.row_count(), 1);
assert_eq!(get_value(&result, 0, 0), DataValue::Integer(2));
}
#[test]
fn test_datediff_negative_values() {
let table = create_test_table();
let engine = QueryEngine::new();
let query = r"SELECT id, DATEDIFF('day', order_date, ship_date) as diff FROM test WHERE DATEDIFF('day', order_date, ship_date) < 0";
let result = engine.execute(table.clone(), query).unwrap();
assert_eq!(result.column_count(), 2);
assert_eq!(result.row_count(), 1);
assert_eq!(get_value(&result, 0, 0), DataValue::Integer(3));
assert_eq!(get_value(&result, 0, 1), DataValue::Integer(-10));
}