uni_plugin/traits/pushdown.rs
1//! Pushdown negotiation traits — Spark DSv2 / Trino-style marker traits.
2//!
3//! Storage backends, index handles, catalog tables, and operator providers
4//! may *additionally* implement any subset of these traits to negotiate
5//! filter / projection / limit / topN / aggregate pushdown with the
6//! planner. Marker traits per capability let backends opt in to only what
7//! they can handle.
8
9use datafusion::logical_expr::Expr;
10
11/// Result of consulting a filter-pushdown source.
12#[derive(Clone, Debug, Default)]
13pub struct FilterApplication {
14 /// Indices into the filter list the source handles completely (the
15 /// planner removes the corresponding `Filter` ops).
16 pub fully_handled: Vec<usize>,
17 /// Indices the source handles approximately (planner keeps a
18 /// verifying `Filter`).
19 pub partially_handled: Vec<usize>,
20}
21
22/// Result of consulting a projection-pushdown source.
23#[derive(Clone, Debug, Default)]
24pub struct ProjectionApplication {
25 /// Column names to actually fetch.
26 pub keep: Vec<String>,
27}
28
29/// Scope at which a TopN pushdown was applied.
30#[derive(Clone, Copy, Debug, PartialEq, Eq)]
31pub enum TopNScope {
32 /// Per-partition local TopN (planner combines).
33 Local,
34 /// Globally-applied — no further `Sort + Limit` needed.
35 Global,
36}
37
38/// Result of consulting a TopN-pushdown source.
39#[derive(Clone, Debug)]
40pub struct TopNApplication {
41 /// Scope at which the source applied the topN.
42 pub applied: TopNScope,
43}
44
45/// Result of consulting an aggregate-pushdown source.
46#[derive(Clone, Debug, Default)]
47pub struct AggregateApplication {
48 /// Indices into the aggregate-expression list the source handles.
49 pub fully_handled: Vec<usize>,
50 /// `true` if the source returns *partial* state (the planner adds a
51 /// Final aggregate above to combine partials).
52 pub returns_partial_state: bool,
53}
54
55/// Marker trait: source supports filter pushdown.
56pub trait SupportsFilterPushdown {
57 /// Inspect filters and report which the source handles.
58 fn push_filters(&self, filters: &[Expr]) -> FilterApplication;
59}
60
61/// Marker trait: source supports projection pushdown.
62pub trait SupportsProjectionPushdown {
63 /// Declare which projected columns to actually read.
64 fn push_projection(&self, columns: &[String]) -> ProjectionApplication;
65}
66
67/// Marker trait: source supports limit pushdown.
68pub trait SupportsLimitPushdown {
69 /// `Some(applied)` if the source enforces the limit; `None` if not.
70 fn push_limit(&self, limit: usize) -> Option<usize>;
71}
72
73/// A sort expression for topN pushdown.
74#[derive(Clone, Debug)]
75pub struct SortExpr {
76 /// Column name to sort by.
77 pub column: String,
78 /// Sort direction.
79 pub ascending: bool,
80 /// Null ordering.
81 pub nulls_first: bool,
82}
83
84/// Marker trait: source supports topN (sort + limit) pushdown.
85pub trait SupportsTopNPushdown {
86 /// Apply topN at the source if possible.
87 fn push_topn(&self, sort: &[SortExpr], k: usize) -> Option<TopNApplication>;
88}
89
90/// Marker trait: source supports aggregate pushdown.
91pub trait SupportsAggregatePushdown {
92 /// Declare which aggregates the source can compute.
93 fn push_aggregates(&self, group_by: &[Expr], aggs: &[Expr]) -> AggregateApplication;
94}