Skip to main content

reifydb_engine/expression/
context.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use std::sync::LazyLock;
5
6use reifydb_core::{
7	interface::{catalog::property::ColumnSaturationStrategy, evaluate::TargetColumn},
8	value::column::{cast::convert::TargetConvert, columns::Columns},
9};
10use reifydb_extension::transform::context::TransformContext;
11use reifydb_routine::routine::registry::Routines;
12use reifydb_runtime::context::{RuntimeContext, clock::Clock};
13use reifydb_value::{params::Params, value::identity::IdentityId};
14
15use crate::{
16	arena::QueryArena,
17	vm::{stack::SymbolTable, volcano::query::QueryContext},
18};
19
20pub struct EvalContext<'a> {
21	pub target: Option<TargetColumn>,
22	pub columns: Columns,
23	pub row_count: usize,
24	pub take: Option<usize>,
25	pub params: &'a Params,
26	pub symbols: &'a SymbolTable,
27	pub is_aggregate_context: bool,
28	pub routines: &'a Routines,
29	pub runtime_context: &'a RuntimeContext,
30	pub arena: Option<&'a QueryArena>,
31	pub identity: IdentityId,
32}
33
34impl<'a> EvalContext<'a> {
35	pub fn testing() -> EvalContext<'static> {
36		static EMPTY_PARAMS: LazyLock<Params> = LazyLock::new(|| Params::None);
37		static EMPTY_SYMBOL_TABLE: LazyLock<SymbolTable> = LazyLock::new(SymbolTable::new);
38		static EMPTY_ROUTINES: LazyLock<Routines> = LazyLock::new(Routines::empty);
39		static DEFAULT_RUNTIME_CONTEXT: LazyLock<RuntimeContext> =
40			LazyLock::new(|| RuntimeContext::with_clock(Clock::Real));
41
42		EvalContext {
43			target: None,
44			columns: Columns::empty(),
45			row_count: 1,
46			take: None,
47			params: &EMPTY_PARAMS,
48			symbols: &EMPTY_SYMBOL_TABLE,
49			is_aggregate_context: false,
50			routines: &EMPTY_ROUTINES,
51			runtime_context: &DEFAULT_RUNTIME_CONTEXT,
52			arena: None,
53			identity: IdentityId::root(),
54		}
55	}
56
57	pub fn with_eval(&self, columns: Columns, row_count: usize) -> EvalContext<'a> {
58		EvalContext {
59			target: None,
60			columns,
61			row_count,
62			take: None,
63			params: self.params,
64			symbols: self.symbols,
65			is_aggregate_context: self.is_aggregate_context,
66			routines: self.routines,
67			runtime_context: self.runtime_context,
68			arena: self.arena,
69			identity: self.identity,
70		}
71	}
72
73	pub fn with_eval_empty(&self) -> EvalContext<'a> {
74		self.with_eval(Columns::empty(), 1)
75	}
76
77	pub fn with_eval_join(&self, columns: Columns) -> EvalContext<'a> {
78		let mut ctx = self.with_eval(columns, 1);
79		ctx.take = Some(1);
80		ctx
81	}
82
83	pub fn from_query(ctx: &'a QueryContext) -> Self {
84		EvalContext {
85			target: None,
86			columns: Columns::empty(),
87			row_count: 1,
88			take: None,
89			params: &ctx.params,
90			symbols: &ctx.symbols,
91			is_aggregate_context: false,
92			routines: &ctx.services.routines,
93			runtime_context: &ctx.services.runtime_context,
94			arena: None,
95			identity: ctx.identity,
96		}
97	}
98
99	pub fn from_transform(ctx: &'a TransformContext, stored: &'a QueryContext) -> Self {
100		EvalContext {
101			target: None,
102			columns: Columns::empty(),
103			row_count: 1,
104			take: None,
105			params: ctx.params,
106			symbols: &stored.symbols,
107			is_aggregate_context: false,
108			routines: &stored.services.routines,
109			runtime_context: ctx.runtime_context,
110			arena: None,
111			identity: stored.identity,
112		}
113	}
114
115	pub(crate) fn saturation_policy(&self) -> ColumnSaturationStrategy {
116		TargetConvert {
117			target: self.target.as_ref(),
118		}
119		.saturation_policy()
120	}
121}
122
123pub struct CompileContext<'a> {
124	pub symbols: &'a SymbolTable,
125}