vegafusion_core/spec/transform/
mod.rs

1pub mod aggregate;
2pub mod bin;
3pub mod collect;
4pub mod extent;
5pub mod filter;
6pub mod fold;
7pub mod formula;
8pub mod identifier;
9pub mod impute;
10pub mod joinaggregate;
11pub mod lookup;
12pub mod pivot;
13pub mod project;
14pub mod sequence;
15pub mod stack;
16pub mod timeunit;
17pub mod unsupported;
18pub mod window;
19
20use crate::spec::transform::{extent::ExtentTransformSpec, filter::FilterTransformSpec};
21
22use crate::error::Result;
23use crate::expression::column_usage::{ColumnUsage, DatasetsColumnUsage, VlSelectionFields};
24use crate::planning::plan::PlannerConfig;
25use crate::spec::transform::aggregate::AggregateTransformSpec;
26use crate::spec::transform::bin::BinTransformSpec;
27use crate::spec::transform::collect::CollectTransformSpec;
28use crate::spec::transform::fold::FoldTransformSpec;
29use crate::spec::transform::formula::FormulaTransformSpec;
30use crate::spec::transform::identifier::IdentifierTransformSpec;
31use crate::spec::transform::impute::ImputeTransformSpec;
32use crate::spec::transform::joinaggregate::JoinAggregateTransformSpec;
33use crate::spec::transform::lookup::LookupTransformSpec;
34use crate::spec::transform::pivot::PivotTransformSpec;
35use crate::spec::transform::project::ProjectTransformSpec;
36use crate::spec::transform::sequence::SequenceTransformSpec;
37use crate::spec::transform::stack::StackTransformSpec;
38use crate::spec::transform::timeunit::TimeUnitTransformSpec;
39use crate::spec::transform::unsupported::*;
40use crate::spec::transform::window::WindowTransformSpec;
41use crate::task_graph::graph::ScopedVariable;
42use crate::task_graph::scope::TaskScope;
43use crate::task_graph::task::InputVariable;
44use serde::{Deserialize, Serialize};
45use std::ops::Deref;
46
47#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
48#[serde(tag = "type", rename_all = "lowercase")]
49pub enum TransformSpec {
50    Extent(ExtentTransformSpec),
51    Filter(FilterTransformSpec),
52    Formula(FormulaTransformSpec),
53    Bin(Box<BinTransformSpec>), // Box since transform is much larger than others
54    Aggregate(AggregateTransformSpec),
55    Collect(CollectTransformSpec),
56    Timeunit(TimeUnitTransformSpec),
57    JoinAggregate(JoinAggregateTransformSpec),
58    Window(WindowTransformSpec),
59    Project(ProjectTransformSpec),
60    Stack(StackTransformSpec),
61    Impute(ImputeTransformSpec),
62    Pivot(PivotTransformSpec),
63    Identifier(IdentifierTransformSpec),
64    Fold(FoldTransformSpec),
65    Sequence(SequenceTransformSpec),
66
67    // Unsupported
68    CountPattern(CountpatternTransformSpec),
69    Contour(ContourTransformSpec),
70    Cross(CrossTransformSpec),
71    Crossfilter(CrossfilterTransformSpec),
72    Density(DensityTransformSpec),
73    DotBin(DotbinTransformSpec),
74    Flatten(FlattenTransformSpec),
75    Force(ForceTransformSpec),
76    GeoJson(GeojsonTransformSpec),
77    GeoPath(GeopathTransformSpec),
78    GeoPoint(GeopointTransformSpec),
79    GeoShape(GeoshapeTransformSpec),
80    Graticule(GraticuleTransformSpec),
81    Heatmap(HeatmapTransformSpec),
82    IsoContour(IsocontourTransformSpec),
83    Kde(KdeTransformSpec),
84    Kde2d(Kde2dTransformSpec),
85    Label(LabelTransformSpec),
86    LinkPath(LinkpathTransformSpec),
87    Loess(LoessTransformSpec),
88    Lookup(LookupTransformSpec),
89    Nest(NestTransformSpec),
90    Pack(PackTransformSpec),
91    Partition(PartitionTransformSpec),
92    Pie(PieTransformSpec),
93    Quantile(QuantileTransformSpec),
94    Regression(RegressionTransformSpec),
95    ResolveFilter(ResolvefilterTransformSpec),
96    Sample(SampleTransformSpec),
97    Stratify(StratifyTransformSpec),
98    Tree(TreeTransformSpec),
99    TreeLinks(TreelinksTransformSpec),
100    Treemap(TreemapTransformSpec),
101    Voronoi(VoronoiTransformSpec),
102    WordCloud(WordcloudTransformSpec),
103}
104
105impl Deref for TransformSpec {
106    type Target = dyn TransformSpecTrait;
107
108    fn deref(&self) -> &Self::Target {
109        match self {
110            TransformSpec::Extent(t) => t,
111            TransformSpec::Filter(t) => t,
112            TransformSpec::Formula(t) => t,
113            TransformSpec::Bin(t) => t.as_ref(),
114            TransformSpec::Aggregate(t) => t,
115            TransformSpec::Collect(t) => t,
116            TransformSpec::Timeunit(t) => t,
117            TransformSpec::Project(t) => t,
118            TransformSpec::Stack(t) => t,
119            TransformSpec::Impute(t) => t,
120            TransformSpec::Pivot(t) => t,
121            TransformSpec::Sequence(t) => t,
122
123            // Supported for dependency determination, not implementation
124            TransformSpec::Lookup(t) => t,
125
126            // Unsupported
127            TransformSpec::CountPattern(t) => t,
128            TransformSpec::Contour(t) => t,
129            TransformSpec::Cross(t) => t,
130            TransformSpec::Crossfilter(t) => t,
131            TransformSpec::Density(t) => t,
132            TransformSpec::DotBin(t) => t,
133            TransformSpec::Flatten(t) => t,
134            TransformSpec::Fold(t) => t,
135            TransformSpec::Force(t) => t,
136            TransformSpec::GeoJson(t) => t,
137            TransformSpec::GeoPath(t) => t,
138            TransformSpec::GeoPoint(t) => t,
139            TransformSpec::GeoShape(t) => t,
140            TransformSpec::Graticule(t) => t,
141            TransformSpec::Heatmap(t) => t,
142            TransformSpec::Identifier(t) => t,
143            TransformSpec::IsoContour(t) => t,
144            TransformSpec::JoinAggregate(t) => t,
145            TransformSpec::Kde(t) => t,
146            TransformSpec::Kde2d(t) => t,
147            TransformSpec::Label(t) => t,
148            TransformSpec::LinkPath(t) => t,
149            TransformSpec::Loess(t) => t,
150            TransformSpec::Nest(t) => t,
151            TransformSpec::Pack(t) => t,
152            TransformSpec::Partition(t) => t,
153            TransformSpec::Pie(t) => t,
154            TransformSpec::Quantile(t) => t,
155            TransformSpec::Regression(t) => t,
156            TransformSpec::ResolveFilter(t) => t,
157            TransformSpec::Sample(t) => t,
158            TransformSpec::Stratify(t) => t,
159            TransformSpec::Tree(t) => t,
160            TransformSpec::TreeLinks(t) => t,
161            TransformSpec::Treemap(t) => t,
162            TransformSpec::Voronoi(t) => t,
163            TransformSpec::Window(t) => t,
164            TransformSpec::WordCloud(t) => t,
165        }
166    }
167}
168
169pub trait TransformSpecTrait {
170    fn supported(&self) -> bool {
171        true
172    }
173
174    fn supported_and_allowed(
175        &self,
176        planner_config: &PlannerConfig,
177        task_scope: &TaskScope,
178        scope: &[u32],
179    ) -> bool {
180        let input_vars = self.input_vars().unwrap_or_default();
181        for input_var in &input_vars {
182            if let Ok(resolved) = task_scope.resolve_scope(&input_var.var, scope) {
183                let scoped_var: ScopedVariable = (resolved.var, resolved.scope);
184                if planner_config.client_only_vars.contains(&scoped_var) {
185                    // Transform requires a variable that may only live on the client
186                    return false;
187                }
188            }
189        }
190        self.supported()
191    }
192
193    fn output_signals(&self) -> Vec<String> {
194        Default::default()
195    }
196
197    fn input_vars(&self) -> Result<Vec<InputVariable>> {
198        Ok(Default::default())
199    }
200
201    fn transform_columns(
202        &self,
203        _datum_var: &Option<ScopedVariable>,
204        _usage_scope: &[u32],
205        _task_scope: &TaskScope,
206        _vl_selection_fields: &VlSelectionFields,
207    ) -> TransformColumns {
208        TransformColumns::Unknown
209    }
210
211    fn local_datetime_columns_produced(
212        &self,
213        _input_local_datetime_columns: &[String],
214    ) -> Vec<String> {
215        Vec::new()
216    }
217}
218
219pub enum TransformColumns {
220    /// Transforms that pass through existing columns and produce zero or more new columns
221    PassThrough {
222        usage: DatasetsColumnUsage,
223        produced: ColumnUsage,
224    },
225
226    /// Transforms that overwrite all input columns, leaving only those produced by the transform
227    Overwrite {
228        usage: DatasetsColumnUsage,
229        produced: ColumnUsage,
230    },
231
232    /// Transforms with unknown usage and/or production of columns
233    Unknown,
234}