reifydb_engine/expression/
context.rs1use 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#[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
142pub struct CompileContext<'a> {
144 pub functions: &'a Functions,
145 pub symbols: &'a SymbolTable,
146}