laminar_core/compiler/error.rs
1//! Error types and compiled expression wrappers for the JIT compiler.
2//!
3//! Defines [`CompileError`] for compilation failures, function pointer types
4//! for compiled filters and scalars, and the [`CompiledExpr`] / [`MaybeCompiledExpr`]
5//! wrappers used by downstream pipeline stages.
6
7use std::fmt;
8
9use super::row::FieldType;
10
11/// Errors that can occur during expression compilation.
12#[derive(Debug)]
13pub enum CompileError {
14 /// An expression node is not supported by the JIT compiler.
15 UnsupportedExpr(String),
16 /// A field type is not supported in the requested context.
17 UnsupportedType(FieldType),
18 /// A binary operation is not supported for the given type.
19 UnsupportedBinaryOp(FieldType, datafusion_expr::Operator),
20 /// A literal value type is not supported.
21 UnsupportedLiteral,
22 /// A referenced column was not found in the schema.
23 ColumnNotFound(String),
24 /// Cranelift module-level error during compilation or linking.
25 Cranelift(Box<cranelift_module::ModuleError>),
26}
27
28impl fmt::Display for CompileError {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 match self {
31 Self::UnsupportedExpr(desc) => write!(f, "unsupported expression: {desc}"),
32 Self::UnsupportedType(ft) => write!(f, "unsupported field type: {ft:?}"),
33 Self::UnsupportedBinaryOp(ft, op) => {
34 write!(f, "unsupported binary op {op} for type {ft:?}")
35 }
36 Self::UnsupportedLiteral => write!(f, "unsupported literal value"),
37 Self::ColumnNotFound(name) => write!(f, "column not found: {name}"),
38 Self::Cranelift(e) => write!(f, "cranelift error: {e}"),
39 }
40 }
41}
42
43impl std::error::Error for CompileError {
44 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
45 match self {
46 Self::Cranelift(e) => Some(e.as_ref()),
47 _ => None,
48 }
49 }
50}
51
52impl From<cranelift_module::ModuleError> for CompileError {
53 fn from(e: cranelift_module::ModuleError) -> Self {
54 Self::Cranelift(Box::new(e))
55 }
56}
57
58/// Errors that can occur during pipeline extraction from a logical plan.
59#[derive(Debug)]
60pub enum ExtractError {
61 /// The logical plan contains a node that cannot be decomposed into pipelines.
62 UnsupportedPlan(String),
63 /// A schema-related error during extraction (e.g., unsupported column type).
64 SchemaError(String),
65}
66
67impl fmt::Display for ExtractError {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 match self {
70 Self::UnsupportedPlan(desc) => write!(f, "unsupported plan node: {desc}"),
71 Self::SchemaError(desc) => write!(f, "schema error during extraction: {desc}"),
72 }
73 }
74}
75
76impl std::error::Error for ExtractError {}
77
78/// A compiled filter function: `fn(row_ptr: *const u8) -> u8`.
79///
80/// Returns 1 if the row passes the filter, 0 otherwise.
81/// The caller must ensure the pointer points to a valid `EventRow` byte buffer
82/// matching the schema used during compilation.
83pub type FilterFn = unsafe extern "C" fn(*const u8) -> u8;
84
85/// A compiled scalar function: `fn(row_ptr: *const u8, out_ptr: *mut u8) -> u8`.
86///
87/// Evaluates the expression and writes the result to `out_ptr`.
88/// Returns 1 if the result is null, 0 if valid.
89pub type ScalarFn = unsafe extern "C" fn(*const u8, *mut u8) -> u8;
90
91/// A successfully compiled expression, either a filter or a scalar projection.
92pub enum CompiledExpr {
93 /// A filter expression returning a boolean.
94 Filter(FilterFn),
95 /// A scalar expression writing its result to an output pointer.
96 Scalar(ScalarFn),
97}
98
99/// Result of attempting to compile an expression.
100///
101/// Falls back to interpretation when the JIT compiler encounters an
102/// unsupported expression node, preserving the reason for diagnostics.
103pub enum MaybeCompiledExpr {
104 /// Successfully compiled to native code.
105 Compiled(CompiledExpr),
106 /// Compilation failed; caller should use interpreted evaluation.
107 Interpreted {
108 /// The reason compilation failed.
109 reason: CompileError,
110 },
111}