Skip to main content

vortex_array/aggregate_fn/
plugin.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use std::sync::Arc;
5
6use vortex_error::VortexResult;
7use vortex_session::VortexSession;
8
9use crate::aggregate_fn::AggregateFn;
10use crate::aggregate_fn::AggregateFnId;
11use crate::aggregate_fn::AggregateFnRef;
12use crate::aggregate_fn::AggregateFnVTable;
13use crate::dtype::DType;
14
15/// Reference-counted pointer to an aggregate function plugin.
16pub type AggregateFnPluginRef = Arc<dyn AggregateFnPlugin>;
17
18/// Registry trait for ID-based deserialization of aggregate functions.
19///
20/// Plugins are registered in the session by their [`AggregateFnId`]. When a serialized aggregate
21/// function is encountered, the session resolves the ID to the plugin and calls [`deserialize`]
22/// to reconstruct the value as an [`AggregateFnRef`].
23///
24/// [`deserialize`]: AggregateFnPlugin::deserialize
25pub trait AggregateFnPlugin: 'static + Send + Sync {
26    /// Returns the ID for this aggregate function.
27    fn id(&self) -> AggregateFnId;
28
29    /// Deserialize an aggregate function from serialized metadata.
30    fn deserialize(&self, metadata: &[u8], session: &VortexSession)
31    -> VortexResult<AggregateFnRef>;
32
33    /// The default zone statistic (per-chunk) for a column of `input_dtype`, or `None` if the
34    /// dtype is not supported (or this aggregate is not a zone statistic at all).
35    ///
36    /// This is how a registered aggregate volunteers itself as a per-chunk statistic: when a
37    /// zoned layout writer opens a column, it collects every plugin's default via
38    /// [`AggregateFnSession::zone_stat_defaults`], so new statistics can be added without the
39    /// writer knowing about them.
40    ///
41    /// [`AggregateFnSession::zone_stat_defaults`]: crate::aggregate_fn::session::AggregateFnSession::zone_stat_defaults
42    fn zone_stat_default(&self, _input_dtype: &DType) -> Option<AggregateFnRef> {
43        None
44    }
45}
46
47impl std::fmt::Debug for dyn AggregateFnPlugin {
48    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49        f.debug_tuple("AggregateFnPlugin")
50            .field(&self.id())
51            .finish()
52    }
53}
54
55impl<V: AggregateFnVTable> AggregateFnPlugin for V {
56    fn id(&self) -> AggregateFnId {
57        AggregateFnVTable::id(self)
58    }
59
60    fn deserialize(
61        &self,
62        metadata: &[u8],
63        session: &VortexSession,
64    ) -> VortexResult<AggregateFnRef> {
65        let options = AggregateFnVTable::deserialize(self, metadata, session)?;
66        Ok(AggregateFn::new(self.clone(), options).erased())
67    }
68
69    fn zone_stat_default(&self, input_dtype: &DType) -> Option<AggregateFnRef> {
70        AggregateFnVTable::zone_stat_default(self, input_dtype)
71    }
72}