Skip to main content

reifydb_engine/vm/volcano/
variable.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use std::sync::Arc;
5
6use reifydb_core::value::column::{columns::Columns, headers::ColumnHeaders};
7use reifydb_rql::expression::VariableExpression;
8use reifydb_transaction::transaction::Transaction;
9
10use crate::{
11	Result,
12	error::EngineError,
13	vm::{
14		stack::Variable,
15		volcano::query::{QueryContext, QueryNode},
16	},
17};
18
19pub(crate) struct VariableNode {
20	variable_expr: VariableExpression,
21	context: Option<Arc<QueryContext>>,
22	executed: bool,
23}
24
25impl VariableNode {
26	pub fn new(variable_expr: VariableExpression) -> Self {
27		Self {
28			variable_expr,
29			context: None,
30			executed: false,
31		}
32	}
33}
34
35impl QueryNode for VariableNode {
36	fn initialize<'a>(&mut self, _rx: &mut Transaction<'a>, ctx: &QueryContext) -> Result<()> {
37		self.context = Some(Arc::new(ctx.clone()));
38		Ok(())
39	}
40
41	fn next<'a>(&mut self, _rx: &mut Transaction<'a>, ctx: &mut QueryContext) -> Result<Option<Columns>> {
42		debug_assert!(self.context.is_some(), "VariableNode::next() called before initialize()");
43
44		if self.executed {
45			return Ok(None);
46		}
47
48		let variable_name = self.variable_expr.name();
49
50		match ctx.symbols.get(variable_name) {
51			Some(Variable::Columns {
52				columns,
53			}) => {
54				self.executed = true;
55				Ok(Some(columns.clone()))
56			}
57			Some(Variable::ForIterator {
58				columns,
59				..
60			}) => {
61				self.executed = true;
62
63				Ok(Some(columns.clone()))
64			}
65			Some(Variable::Closure(_)) => Err(EngineError::VariableNotFound {
66				name: variable_name.to_string(),
67			}
68			.into()),
69			None => Err(EngineError::VariableNotFound {
70				name: variable_name.to_string(),
71			}
72			.into()),
73		}
74	}
75
76	fn headers(&self) -> Option<ColumnHeaders> {
77		None
78	}
79}