reifydb_engine/evaluate/column/
mod.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the AGPL-3.0-or-later, see license.md file
3
4use reifydb_core::value::column::Column;
5use reifydb_rql::expression::Expression;
6
7pub(crate) use crate::evaluate::ColumnEvaluationContext;
8use crate::function::{Functions, blob, flow_node_type, math, text};
9
10mod access;
11mod alias;
12mod arith;
13mod call;
14pub(crate) mod cast;
15mod column;
16mod compare;
17pub(crate) mod constant;
18mod extend_expr;
19mod if_expr;
20mod logic;
21mod map_expr;
22mod parameter;
23mod prefix;
24mod tuple;
25mod variable;
26
27pub struct StandardColumnEvaluator {
28	functions: Functions,
29}
30
31impl Default for StandardColumnEvaluator {
32	fn default() -> Self {
33		Self {
34			functions: Functions::builder()
35				.register_scalar("math::abs", math::scalar::Abs::new)
36				.register_scalar("math::avg", math::scalar::Avg::new)
37				.register_scalar("math::max", math::scalar::Max::new)
38				.register_scalar("math::min", math::scalar::Min::new)
39				.register_scalar("math::power", math::scalar::Power::new)
40				.register_scalar("math::round", math::scalar::Round::new)
41				.register_scalar("blob::hex", blob::BlobHex::new)
42				.register_scalar("blob::b58", blob::BlobB58::new)
43				.register_scalar("blob::b64", blob::BlobB64::new)
44				.register_scalar("blob::b64url", blob::BlobB64url::new)
45				.register_scalar("blob::utf8", blob::BlobUtf8::new)
46				.register_scalar("flow_node_type::to_json", flow_node_type::FlowNodeTypeToJson::new)
47				.register_scalar("text::trim", text::TextTrim::new)
48				.register_scalar("text::upper", text::TextUpper::new)
49				.register_scalar("text::substring", text::TextSubstring::new)
50				.register_scalar("text::length", text::TextLength::new)
51				.build(),
52		}
53	}
54}
55
56impl StandardColumnEvaluator {
57	pub fn evaluate<'a>(
58		&self,
59		ctx: &ColumnEvaluationContext<'a>,
60		expr: &Expression<'a>,
61	) -> crate::Result<Column<'a>> {
62		match expr {
63			Expression::AccessSource(expr) => self.access(ctx, expr),
64			Expression::Alias(expr) => self.alias(ctx, expr),
65			Expression::Add(expr) => self.add(ctx, expr),
66			Expression::Div(expr) => self.div(ctx, expr),
67			Expression::Call(expr) => self.call(ctx, expr),
68			Expression::Cast(expr) => self.cast(ctx, expr),
69			Expression::Column(expr) => self.column(ctx, expr),
70			Expression::Constant(expr) => self.constant(ctx, expr),
71			Expression::GreaterThan(expr) => self.greater_than(ctx, expr),
72			Expression::GreaterThanEqual(expr) => self.greater_than_equal(ctx, expr),
73			Expression::LessThan(expr) => self.less_than(ctx, expr),
74			Expression::LessThanEqual(expr) => self.less_than_equal(ctx, expr),
75			Expression::Equal(expr) => self.equal(ctx, expr),
76			Expression::NotEqual(expr) => self.not_equal(ctx, expr),
77			Expression::Between(expr) => self.between(ctx, expr),
78			Expression::In(expr) => self.in_expr(ctx, expr),
79			Expression::And(expr) => self.and(ctx, expr),
80			Expression::Or(expr) => self.or(ctx, expr),
81			Expression::Xor(expr) => self.xor(ctx, expr),
82			Expression::Rem(expr) => self.rem(ctx, expr),
83			Expression::Mul(expr) => self.mul(ctx, expr),
84			Expression::Prefix(expr) => self.prefix(ctx, expr),
85			Expression::Sub(expr) => self.sub(ctx, expr),
86			Expression::Tuple(expr) => self.tuple(ctx, expr),
87			Expression::Parameter(expr) => self.parameter(ctx, expr),
88			Expression::Variable(expr) => self.variable(ctx, expr),
89			Expression::If(expr) => self.if_expr(ctx, expr),
90			Expression::Map(expr) => self.map_expr(ctx, expr),
91			Expression::Extend(expr) => self.extend_expr(ctx, expr),
92			expr => unimplemented!("{expr:?}"),
93		}
94	}
95}
96
97pub fn evaluate<'a>(ctx: &ColumnEvaluationContext<'a>, expr: &Expression<'a>) -> crate::Result<Column<'a>> {
98	let evaluator = StandardColumnEvaluator {
99		functions: Functions::builder()
100			.register_scalar("math::abs", math::scalar::Abs::new)
101			.register_scalar("math::avg", math::scalar::Avg::new)
102			.register_scalar("math::max", math::scalar::Max::new)
103			.register_scalar("math::min", math::scalar::Min::new)
104			.register_scalar("math::power", math::scalar::Power::new)
105			.register_scalar("math::round", math::scalar::Round::new)
106			.register_scalar("blob::hex", blob::BlobHex::new)
107			.register_scalar("blob::b58", blob::BlobB58::new)
108			.register_scalar("blob::b64", blob::BlobB64::new)
109			.register_scalar("blob::b64url", blob::BlobB64url::new)
110			.register_scalar("blob::utf8", blob::BlobUtf8::new)
111			.register_scalar("flow_node_type::to_json", flow_node_type::FlowNodeTypeToJson::new)
112			.register_scalar("text::trim", text::TextTrim::new)
113			.register_scalar("text::upper", text::TextUpper::new)
114			.register_scalar("text::substring", text::TextSubstring::new)
115			.register_scalar("text::length", text::TextLength::new)
116			.build(),
117	};
118
119	// Ensures that result column data type matches the expected target
120	// column type
121	if let Some(ty) = ctx.target.as_ref().map(|c| c.column_type()) {
122		let mut column = evaluator.evaluate(ctx, expr)?;
123		let data = cast::cast_column_data(ctx, &column.data(), ty, &expr.lazy_fragment())?;
124		column = Column {
125			name: column.name,
126			data,
127		};
128		Ok(column)
129	} else {
130		evaluator.evaluate(ctx, expr)
131	}
132}