Skip to main content

reifydb_engine/vm/volcano/
variable.rs

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