vortex_array/scalar_fn/mod.rs
1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4//! Scalar function vtable machinery.
5//!
6//! This module contains the [`ScalarFnVTable`] trait and all built-in scalar function
7//! implementations. Expressions ([`crate::expr::Expression`]) reference scalar functions
8//! at each node.
9//!
10//! Strict functions with row-at-a-time kernels can implement `unstable::row::RowFn`. It handles
11//! decoding, constants, null propagation, output construction, and validity. This API requires the
12//! `unstable_row_fns` feature and has no compatibility guarantees. Implement [`ScalarFnVTable`]
13//! directly for columnar kernels and functions that alias an input or can produce null from valid
14//! inputs.
15
16use vortex_session::registry::Id;
17
18use crate::scalar_fn::fns::byte_length::ByteLength;
19use crate::scalar_fn::fns::ext_storage::ExtStorage;
20use crate::scalar_fn::fns::get_item::GetItem;
21use crate::scalar_fn::fns::literal::Literal;
22
23mod vtable;
24pub use vtable::*;
25
26mod plugin;
27pub use plugin::*;
28
29mod foreign;
30pub use foreign::*;
31
32mod typed;
33pub use typed::*;
34
35mod erased;
36pub use erased::*;
37
38mod options;
39pub use options::*;
40
41mod signature;
42pub use signature::*;
43
44#[cfg(feature = "unstable_row_fns")]
45pub mod unstable;
46#[cfg(not(feature = "unstable_row_fns"))]
47#[allow(dead_code, unused_imports)]
48pub(crate) mod unstable;
49
50pub mod fns;
51pub mod internal;
52pub mod session;
53
54/// A unique identifier for a scalar function.
55pub type ScalarFnId = Id;
56
57/// Private module to seal [`typed::DynScalarFn`].
58mod sealed {
59 use crate::scalar_fn::ScalarFnVTable;
60 use crate::scalar_fn::typed::TypedScalarFnInstance;
61
62 /// Marker trait to prevent external implementations of [`super::typed::DynScalarFn`].
63 pub(crate) trait Sealed {}
64
65 /// This can be the **only** implementor for [`super::typed::DynScalarFn`].
66 impl<V: ScalarFnVTable> Sealed for TypedScalarFnInstance<V> {}
67}
68
69/// A scalar function has a negative cost if applying it to an array and
70/// canonicalizing is cheaper than canonicalizing an array and applying it.
71///
72/// Example of negative cost expressions are byte_length(), ext_storage(), and get_item() since
73/// they don't depend on input size.
74///
75/// Example of non-negative cost expression is like() as it's linear over
76/// individual input.
77pub fn is_negative_cost(id: ScalarFnId) -> bool {
78 id == ScalarFnVTable::id(&ByteLength)
79 || id == ScalarFnVTable::id(&ExtStorage)
80 || id == ScalarFnVTable::id(&GetItem)
81 || id == ScalarFnVTable::id(&Literal)
82}