#![cfg(feature = "duckdb")]
use std::io::Write;
use tempfile::{Builder, TempPath};
use flowcode_core::duckdb_session::DuckSession;
use flowcode_core::types::TypedValue;
use flowcode_core::ast::ArgValue;
use flowcode_core::duckdb_verbs::map_verb_to_sql;
fn create_test_csv(content: &str) -> (TempPath, String) {
let mut temp_file = Builder::new()
.prefix("test_")
.suffix(".csv")
.tempfile()
.unwrap();
writeln!(temp_file, "{}", content).unwrap();
let temp_path = temp_file.into_temp_path(); let path_str = temp_path.to_str().unwrap().to_string();
(temp_path, path_str)
}
#[test]
fn test_group_by_single_column() {
let csv_content = "region,sales,category\nEast,1200,A\nWest,800,A\nEast,1500,B";
let (_guard, file_path) = create_test_csv(csv_content);
let session = DuckSession::new().unwrap();
let table_name = "test_sales_group";
let load_result = session.load_csv_auto(table_name, &file_path);
assert!(load_result.is_ok(), "Failed to load CSV: {:?}", load_result.err());
let args = vec![
TypedValue::new(
flowcode_core::types::ValueKind::String,
ArgValue::String(table_name.to_string())
),
TypedValue::new(
flowcode_core::types::ValueKind::String,
ArgValue::String("region".to_string())
)
];
let result = map_verb_to_sql("group", &args, &session);
assert!(result.is_ok());
let sql_query = result.unwrap();
assert_eq!(sql_query, format!("SELECT region FROM {} GROUP BY region", table_name));
let query_result = session.execute_sql(&sql_query);
assert!(query_result.is_ok(), "Group query failed: {:?}", query_result.err());
if let Ok(TypedValue { value: ArgValue::Table(data), .. }) = query_result {
assert_eq!(data.len(), 2, "Expected 2 rows from group by region");
assert_eq!(data[0].len(), 1, "Expected 1 column from group by region");
} else {
panic!("Expected table data in group result");
}
}
#[test]
fn test_group_by_multiple_columns() {
let csv_content = "region,sales,category\nEast,1200,A\nWest,800,B\nEast,1500,A";
let (_guard, file_path) = create_test_csv(csv_content);
let session = DuckSession::new().unwrap();
let table_name = "test_sales_group_multi";
let load_result = session.load_csv_auto(table_name, &file_path);
assert!(load_result.is_ok(), "Failed to load CSV: {:?}", load_result.err());
let args = vec![
TypedValue::new(
flowcode_core::types::ValueKind::String,
ArgValue::String(table_name.to_string())
),
TypedValue::new(
flowcode_core::types::ValueKind::String,
ArgValue::String("region".to_string())
),
TypedValue::new(
flowcode_core::types::ValueKind::String,
ArgValue::String("category".to_string())
)
];
let result = map_verb_to_sql("group", &args, &session);
assert!(result.is_ok());
let sql_query = result.unwrap();
assert_eq!(sql_query, format!("SELECT region, category FROM {} GROUP BY region, category", table_name));
let query_result = session.execute_sql(&sql_query);
assert!(query_result.is_ok(), "Group query failed: {:?}", query_result.err());
if let Ok(TypedValue { value: ArgValue::Table(data), .. }) = query_result {
assert_eq!(data.len(), 2, "Expected 2 rows from group by region and category");
assert_eq!(data[0].len(), 2, "Expected 2 columns from group by region and category");
} else {
panic!("Expected table data in group result");
}
}
#[test]
fn test_group_no_arguments() {
let session = DuckSession::new().unwrap();
let args = vec![];
let result = map_verb_to_sql("group", &args, &session);
assert!(result.is_err());
if let Err(e) = result {
assert!(e.to_string().contains("Invalid argument"));
}
}