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::routine::registry::Routines;
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
23pub struct EvalContext<'a> {
24	pub target: Option<TargetColumn>,
25	pub columns: Columns,
26	pub row_count: usize,
27	pub take: Option<usize>,
28	pub params: &'a Params,
29	pub symbols: &'a SymbolTable,
30	pub is_aggregate_context: bool,
31	pub routines: &'a Routines,
32	pub runtime_context: &'a RuntimeContext,
33	pub arena: Option<&'a QueryArena>,
34	pub identity: IdentityId,
35}
36
37impl<'a> EvalContext<'a> {
38	pub fn testing() -> EvalContext<'static> {
39		static EMPTY_PARAMS: LazyLock<Params> = LazyLock::new(|| Params::None);
40		static EMPTY_SYMBOL_TABLE: LazyLock<SymbolTable> = LazyLock::new(SymbolTable::new);
41		static EMPTY_ROUTINES: LazyLock<Routines> = LazyLock::new(Routines::empty);
42		static DEFAULT_RUNTIME_CONTEXT: LazyLock<RuntimeContext> =
43			LazyLock::new(|| RuntimeContext::with_clock(Clock::Real));
44
45		EvalContext {
46			target: None,
47			columns: Columns::empty(),
48			row_count: 1,
49			take: None,
50			params: &EMPTY_PARAMS,
51			symbols: &EMPTY_SYMBOL_TABLE,
52			is_aggregate_context: false,
53			routines: &EMPTY_ROUTINES,
54			runtime_context: &DEFAULT_RUNTIME_CONTEXT,
55			arena: None,
56			identity: IdentityId::root(),
57		}
58	}
59
60	pub fn with_eval(&self, columns: Columns, row_count: usize) -> EvalContext<'a> {
61		EvalContext {
62			target: None,
63			columns,
64			row_count,
65			take: None,
66			params: self.params,
67			symbols: self.symbols,
68			is_aggregate_context: self.is_aggregate_context,
69			routines: self.routines,
70			runtime_context: self.runtime_context,
71			arena: self.arena,
72			identity: self.identity,
73		}
74	}
75
76	pub fn with_eval_empty(&self) -> EvalContext<'a> {
77		self.with_eval(Columns::empty(), 1)
78	}
79
80	pub fn with_eval_join(&self, columns: Columns) -> EvalContext<'a> {
81		let mut ctx = self.with_eval(columns, 1);
82		ctx.take = Some(1);
83		ctx
84	}
85
86	pub fn from_query(ctx: &'a QueryContext) -> Self {
87		EvalContext {
88			target: None,
89			columns: Columns::empty(),
90			row_count: 1,
91			take: None,
92			params: &ctx.params,
93			symbols: &ctx.symbols,
94			is_aggregate_context: false,
95			routines: &ctx.services.routines,
96			runtime_context: &ctx.services.runtime_context,
97			arena: None,
98			identity: ctx.identity,
99		}
100	}
101
102	pub fn from_transform(ctx: &'a TransformContext, stored: &'a QueryContext) -> Self {
103		EvalContext {
104			target: None,
105			columns: Columns::empty(),
106			row_count: 1,
107			take: None,
108			params: ctx.params,
109			symbols: &stored.symbols,
110			is_aggregate_context: false,
111			routines: &stored.services.routines,
112			runtime_context: ctx.runtime_context,
113			arena: None,
114			identity: stored.identity,
115		}
116	}
117
118	pub(crate) fn saturation_policy(&self) -> ColumnSaturationStrategy {
119		self.target
120			.as_ref()
121			.and_then(|t| {
122				t.properties()
123					.into_iter()
124					.map(|p| {
125						let ColumnPropertyKind::Saturation(policy) = p;
126						policy
127					})
128					.next()
129			})
130			.unwrap_or(DEFAULT_COLUMN_SATURATION_STRATEGY.clone())
131	}
132}
133
134pub struct CompileContext<'a> {
135	pub symbols: &'a SymbolTable,
136}