Skip to main content

vortex_array/scalar_fn/unstable/row/
row_fn.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4//! The [`RowFn`] contract for scalar functions whose natural kernel computes one row at a time.
5//!
6//! Implementations declare their arity and fallibility, then use [`RowFn::dispatch`] to select the
7//! typed row signature for each supported dtype combination. Optional methods provide
8//! serialization without putting persistence plumbing in the row kernel.
9
10use std::fmt::Debug;
11use std::fmt::Display;
12use std::hash::Hash;
13
14use vortex_error::VortexResult;
15use vortex_error::vortex_bail;
16use vortex_session::VortexSession;
17
18use super::visitor::RowVisitor;
19use crate::dtype::DType;
20use crate::scalar_fn::ScalarFnId;
21
22/// A strict scalar function whose row kernel cannot produce null from valid inputs.
23///
24/// This is stronger than
25/// [`ScalarFnVTable::is_strict`](crate::scalar_fn::ScalarFnVTable::is_strict), which requires null
26/// propagation but permits valid inputs to produce null. The framework derives output validity
27/// only from input validity.
28///
29/// A dispatched [`OutputElement`] or [`OutputSink`] describes the non-nullable values produced for
30/// valid rows. The framework widens that dtype when an input dtype is nullable, attaches the
31/// input-derived validity, and casts the finished array to the widened dtype. Implementations do
32/// not construct nullable placeholders for invalid rows.
33///
34/// Declare argument names and use [`dispatch`](Self::dispatch) to select element and output types.
35/// Every implementation receives the standard [`ScalarFnVTable`]. A public type that needs custom
36/// vtable hooks can delegate its row kernel through [`row_fn_return_dtype`] and [`execute_rows`].
37///
38/// [`OutputElement`]: crate::scalar_fn::unstable::row::OutputElement
39/// [`OutputSink`]: crate::scalar_fn::unstable::row::OutputSink
40/// [`ScalarFnVTable`]: crate::scalar_fn::ScalarFnVTable
41/// [`execute_rows`]: crate::scalar_fn::unstable::row::execute_rows
42/// [`row_fn_return_dtype`]: crate::scalar_fn::unstable::row::row_fn_return_dtype
43pub trait RowFn: 'static + Sized + Clone + Send + Sync {
44    /// Options for this function, or [`EmptyOptions`](crate::scalar_fn::EmptyOptions) for none.
45    type Options: 'static + Send + Sync + Clone + Debug + Display + PartialEq + Eq + Hash;
46
47    /// The arguments in display order. Its length is the function's exact arity.
48    const ARG_NAMES: &'static [&'static str];
49
50    /// Whether every dispatch is infallible.
51    ///
52    /// See [`ScalarFnVTable::is_infallible`](crate::scalar_fn::ScalarFnVTable::is_infallible) for
53    /// a more detailed explanation of semantic errors.
54    ///
55    /// The framework checks dispatched element and result types. A conservative `false` is allowed.
56    const INFALLIBLE: bool;
57
58    /// Returns the ID of the scalar function.
59    fn id(&self) -> ScalarFnId;
60
61    /// Serialize this function's options, or return `None` when the function is not serializable.
62    fn serialize(&self, options: &Self::Options) -> VortexResult<Option<Vec<u8>>> {
63        _ = options;
64        Ok(None)
65    }
66
67    /// Restore options written by [`serialize`](Self::serialize).
68    fn deserialize(
69        &self,
70        _metadata: &[u8],
71        _session: &VortexSession,
72    ) -> VortexResult<Self::Options> {
73        vortex_bail!("Expression {} is not deserializable", self.id())
74    }
75
76    /// Choose element types for these input dtypes and visit the framework with them.
77    ///
78    /// Planning and execution both call this method, so its result **must** depend only on
79    /// `options` and `args`. Cross-argument dtype validation belongs here.
80    fn dispatch<V: RowVisitor<Self::Options>>(
81        &self,
82        options: &Self::Options,
83        args: &[DType],
84        visitor: V,
85    ) -> VortexResult<V::VisitResult>;
86}