Skip to main content

reifydb_engine/expression/
context.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use std::sync::LazyLock;
5
6use reifydb_core::{
7	interface::{
8		catalog::property::{ColumnPropertyKind, ColumnSaturationStrategy, DEFAULT_COLUMN_SATURATION_STRATEGY},
9		evaluate::TargetColumn,
10	},
11	value::column::columns::Columns,
12};
13use reifydb_extension::transform::context::TransformContext;
14use reifydb_routine::function::registry::Functions;
15use reifydb_runtime::context::{RuntimeContext, clock::Clock};
16use reifydb_type::{params::Params, value::identity::IdentityId};
17
18use crate::{
19	arena::QueryArena,
20	vm::{stack::SymbolTable, volcano::query::QueryContext},
21};
22
23/// Session-scoped evaluation context — holds the invariant fields
24/// within a given operator. Provides factory methods to produce `EvalContext`
25/// values that vary only in `columns` and `row_count`.
26#[derive(Clone, Copy)]
27pub struct EvalSession<'a> {
28	pub params: &'a Params,
29	pub symbols: &'a SymbolTable,
30	pub functions: &'a Functions,
31	pub runtime_context: &'a RuntimeContext,
32	pub arena: Option<&'a QueryArena>,
33	pub identity: IdentityId,
34	pub is_aggregate_context: bool,
35}
36
37impl<'a> EvalSession<'a> {
38	pub fn eval(&self, columns: Columns, row_count: usize) -> EvalContext<'a> {
39		EvalContext {
40			target: None,
41			columns,
42			row_count,
43			take: None,
44			params: self.params,
45			symbols: self.symbols,
46			is_aggregate_context: self.is_aggregate_context,
47			functions: self.functions,
48			runtime_context: self.runtime_context,
49			arena: self.arena,
50			identity: self.identity,
51		}
52	}
53
54	pub fn eval_empty(&self) -> EvalContext<'a> {
55		self.eval(Columns::empty(), 1)
56	}
57
58	pub fn eval_join(&self, columns: Columns) -> EvalContext<'a> {
59		let mut ctx = self.eval(columns, 1);
60		ctx.take = Some(1);
61		ctx
62	}
63
64	pub fn from_transform(ctx: &'a TransformContext, stored: &'a QueryContext) -> Self {
65		Self {
66			params: ctx.params,
67			symbols: &stored.symbols,
68			functions: ctx.functions,
69			runtime_context: ctx.runtime_context,
70			arena: None,
71			identity: stored.identity,
72			is_aggregate_context: false,
73		}
74	}
75
76	pub fn from_query(ctx: &'a QueryContext) -> Self {
77		Self {
78			params: &ctx.params,
79			symbols: &ctx.symbols,
80			functions: &ctx.services.functions,
81			runtime_context: &ctx.services.runtime_context,
82			arena: None,
83			identity: ctx.identity,
84			is_aggregate_context: false,
85		}
86	}
87
88	pub fn testing() -> EvalSession<'static> {
89		static EMPTY_PARAMS: LazyLock<Params> = LazyLock::new(|| Params::None);
90		static EMPTY_SYMBOL_TABLE: LazyLock<SymbolTable> = LazyLock::new(SymbolTable::new);
91		static EMPTY_FUNCTIONS: LazyLock<Functions> = LazyLock::new(Functions::empty);
92		static DEFAULT_RUNTIME_CONTEXT: LazyLock<RuntimeContext> =
93			LazyLock::new(|| RuntimeContext::with_clock(Clock::Real));
94
95		EvalSession {
96			params: &EMPTY_PARAMS,
97			symbols: &EMPTY_SYMBOL_TABLE,
98			functions: &EMPTY_FUNCTIONS,
99			runtime_context: &DEFAULT_RUNTIME_CONTEXT,
100			arena: None,
101			identity: IdentityId::root(),
102			is_aggregate_context: false,
103		}
104	}
105}
106
107pub struct EvalContext<'a> {
108	pub target: Option<TargetColumn>,
109	pub columns: Columns,
110	pub row_count: usize,
111	pub take: Option<usize>,
112	pub params: &'a Params,
113	pub symbols: &'a SymbolTable,
114	pub is_aggregate_context: bool,
115	pub functions: &'a Functions,
116	pub runtime_context: &'a RuntimeContext,
117	pub arena: Option<&'a QueryArena>,
118	pub identity: IdentityId,
119}
120
121impl<'a> EvalContext<'a> {
122	pub fn testing() -> Self {
123		EvalSession::testing().eval_empty()
124	}
125
126	pub(crate) fn saturation_policy(&self) -> ColumnSaturationStrategy {
127		self.target
128			.as_ref()
129			.and_then(|t| {
130				t.properties()
131					.into_iter()
132					.map(|p| {
133						let ColumnPropertyKind::Saturation(policy) = p;
134						policy
135					})
136					.next()
137			})
138			.unwrap_or(DEFAULT_COLUMN_SATURATION_STRATEGY.clone())
139	}
140}
141
142/// Compile-time context for resolving functions and UDFs.
143pub struct CompileContext<'a> {
144	pub functions: &'a Functions,
145	pub symbols: &'a SymbolTable,
146}