use vantage_expressions::Expression;
use vantage_expressions::traits::datasource::ExprDataSource;
use vantage_expressions::traits::expressive::{DeferredFn, ExpressiveEnum};
use crate::Csv;
use crate::condition::resolve_param;
use crate::type_system::AnyCsvType;
impl ExprDataSource<AnyCsvType> for Csv {
async fn execute(&self, expr: &Expression<AnyCsvType>) -> vantage_core::Result<AnyCsvType> {
if expr.parameters.len() == 1 {
resolve_param(&expr.parameters[0]).await
} else if expr.parameters.is_empty() {
Ok(AnyCsvType::new(expr.template.clone()))
} else {
let mut results = Vec::new();
for param in &expr.parameters {
let resolved = resolve_param(param).await?;
results.push(resolved.value().clone());
}
Ok(AnyCsvType::new(results.join(",")))
}
}
fn defer(&self, expr: Expression<AnyCsvType>) -> DeferredFn<AnyCsvType>
where
AnyCsvType: Clone + Send + Sync + 'static,
{
let csv = self.clone();
DeferredFn::new(move || {
let csv = csv.clone();
let expr = expr.clone();
Box::pin(async move {
let result = csv.execute(&expr).await?;
Ok(ExpressiveEnum::Scalar(result))
})
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use vantage_table::table::Table;
use vantage_table::traits::table_source::TableSource;
use vantage_types::EmptyEntity;
fn test_csv() -> Csv {
Csv::new(format!("{}/data", env!("CARGO_MANIFEST_DIR")))
}
#[tokio::test]
async fn test_execute_column_table_values_expr() {
let csv = test_csv();
let table = Table::<Csv, EmptyEntity>::new("client", csv.clone())
.with_column_of::<String>("name")
.with_column_of::<bool>("is_paying_client");
let name_col = csv.create_column::<String>("name");
let associated = csv.column_table_values_expr(&table, &name_col);
let result = csv.execute(associated.expression()).await.unwrap();
let names = result.try_get::<Vec<AnyCsvType>>().unwrap();
let name_strings: Vec<&str> = names.iter().map(|v| v.value().as_str()).collect();
assert!(name_strings.contains(&"Marty McFly"));
assert!(name_strings.contains(&"Doc Brown"));
assert!(name_strings.contains(&"Biff Tannen"));
}
#[tokio::test]
async fn test_execute_column_values_with_condition() {
use crate::operation::CsvOperation;
let csv = test_csv();
let mut table = Table::<Csv, EmptyEntity>::new("client", csv.clone())
.with_column_of::<String>("name")
.with_column_of::<bool>("is_paying_client");
table.add_condition(table["is_paying_client"].eq(AnyCsvType::new(true)));
let name_col = csv.create_column::<String>("name");
let associated = csv.column_table_values_expr(&table, &name_col);
let result = csv.execute(associated.expression()).await.unwrap();
let names = result.try_get::<Vec<AnyCsvType>>().unwrap();
let name_strings: Vec<&str> = names.iter().map(|v| v.value().as_str()).collect();
assert!(name_strings.contains(&"Marty McFly"));
assert!(name_strings.contains(&"Doc Brown"));
assert!(!name_strings.contains(&"Biff Tannen"));
}
}