vegafusion_runtime/transform/
formula.rs1use crate::expression::compiler::compile;
2use crate::expression::compiler::config::CompilationConfig;
3use crate::transform::TransformTrait;
4
5use vegafusion_core::error::{Result, ResultWithContext};
6use vegafusion_core::proto::gen::transforms::Formula;
7
8use crate::expression::compiler::utils::VfSimplifyInfo;
9use async_trait::async_trait;
10use datafusion::prelude::DataFrame;
11use datafusion_optimizer::simplify_expressions::ExprSimplifier;
12use vegafusion_common::column::flat_col;
13use vegafusion_core::task_graph::task_value::TaskValue;
14
15#[async_trait]
16impl TransformTrait for Formula {
17 async fn eval(
18 &self,
19 dataframe: DataFrame,
20 config: &CompilationConfig,
21 ) -> Result<(DataFrame, Vec<TaskValue>)> {
22 let formula_expr = compile(
23 self.expr.as_ref().unwrap(),
24 config,
25 Some(dataframe.schema()),
26 )?;
27
28 let simplifier = ExprSimplifier::new(VfSimplifyInfo::from(dataframe.schema().clone()));
30 let formula_expr = simplifier.simplify(formula_expr)?;
31
32 let formula_expr = formula_expr.alias(&self.r#as);
34
35 let mut selections = Vec::new();
39 let mut as_field_added = false;
40 for field in dataframe.schema().fields().iter() {
41 if field.name() == &self.r#as {
42 selections.push(formula_expr.clone());
43 as_field_added = true;
44 } else {
45 selections.push(flat_col(field.name()))
46 }
47 }
48 if !as_field_added {
49 selections.push(formula_expr);
50 }
51
52 let result = dataframe.select(selections).with_context(|| {
54 format!(
55 "Formula transform failed with expression: {}",
56 &self.expr.as_ref().unwrap()
57 )
58 })?;
59
60 Ok((result, Default::default()))
61 }
62}