vantage_csv/
expr_data_source.rs1use vantage_expressions::Expression;
7use vantage_expressions::traits::datasource::ExprDataSource;
8use vantage_expressions::traits::expressive::{DeferredFn, ExpressiveEnum};
9
10use crate::Csv;
11use crate::condition::resolve_param;
12use crate::type_system::AnyCsvType;
13
14impl ExprDataSource<AnyCsvType> for Csv {
15 async fn execute(&self, expr: &Expression<AnyCsvType>) -> vantage_core::Result<AnyCsvType> {
16 if expr.parameters.len() == 1 {
20 resolve_param(&expr.parameters[0]).await
21 } else if expr.parameters.is_empty() {
22 Ok(AnyCsvType::new(expr.template.clone()))
23 } else {
24 let mut results = Vec::new();
26 for param in &expr.parameters {
27 let resolved = resolve_param(param).await?;
28 results.push(resolved.value().clone());
29 }
30 Ok(AnyCsvType::new(results.join(",")))
31 }
32 }
33
34 fn defer(&self, expr: Expression<AnyCsvType>) -> DeferredFn<AnyCsvType>
35 where
36 AnyCsvType: Clone + Send + Sync + 'static,
37 {
38 let csv = self.clone();
39 DeferredFn::new(move || {
40 let csv = csv.clone();
41 let expr = expr.clone();
42 Box::pin(async move {
43 let result = csv.execute(&expr).await?;
44 Ok(ExpressiveEnum::Scalar(result))
45 })
46 })
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use vantage_table::table::Table;
54 use vantage_table::traits::table_source::TableSource;
55 use vantage_types::EmptyEntity;
56
57 fn test_csv() -> Csv {
58 Csv::new(format!("{}/data", env!("CARGO_MANIFEST_DIR")))
59 }
60
61 #[tokio::test]
62 async fn test_execute_column_table_values_expr() {
63 let csv = test_csv();
64 let table = Table::<Csv, EmptyEntity>::new("client", csv.clone())
65 .with_column_of::<String>("name")
66 .with_column_of::<bool>("is_paying_client");
67
68 let name_col = csv.create_column::<String>("name");
69 let associated = csv.column_table_values_expr(&table, &name_col);
70 let result = csv.execute(associated.expression()).await.unwrap();
71
72 let names = result.try_get::<Vec<AnyCsvType>>().unwrap();
74 let name_strings: Vec<&str> = names.iter().map(|v| v.value().as_str()).collect();
75 assert!(name_strings.contains(&"Marty McFly"));
76 assert!(name_strings.contains(&"Doc Brown"));
77 assert!(name_strings.contains(&"Biff Tannen"));
78 }
79
80 #[tokio::test]
81 async fn test_execute_column_values_with_condition() {
82 use crate::operation::CsvOperation;
83
84 let csv = test_csv();
85 let mut table = Table::<Csv, EmptyEntity>::new("client", csv.clone())
86 .with_column_of::<String>("name")
87 .with_column_of::<bool>("is_paying_client");
88
89 table.add_condition(table["is_paying_client"].eq(AnyCsvType::new(true)));
90
91 let name_col = csv.create_column::<String>("name");
92 let associated = csv.column_table_values_expr(&table, &name_col);
93 let result = csv.execute(associated.expression()).await.unwrap();
94
95 let names = result.try_get::<Vec<AnyCsvType>>().unwrap();
96 let name_strings: Vec<&str> = names.iter().map(|v| v.value().as_str()).collect();
97 assert!(name_strings.contains(&"Marty McFly"));
98 assert!(name_strings.contains(&"Doc Brown"));
99 assert!(!name_strings.contains(&"Biff Tannen"));
100 }
101}