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, 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("text::trim", text::TextTrim::new)
47				.register_scalar("text::upper", text::TextUpper::new)
48				.register_scalar("text::substring", text::TextSubstring::new)
49				.register_scalar("text::length", text::TextLength::new)
50				.build(),
51		}
52	}
53}
54
55impl StandardColumnEvaluator {
56	pub fn evaluate<'a>(
57		&self,
58		ctx: &ColumnEvaluationContext<'a>,
59		expr: &Expression<'a>,
60	) -> crate::Result<Column<'a>> {
61		match expr {
62			Expression::AccessSource(expr) => self.access(ctx, expr),
63			Expression::Alias(expr) => self.alias(ctx, expr),
64			Expression::Add(expr) => self.add(ctx, expr),
65			Expression::Div(expr) => self.div(ctx, expr),
66			Expression::Call(expr) => self.call(ctx, expr),
67			Expression::Cast(expr) => self.cast(ctx, expr),
68			Expression::Column(expr) => self.column(ctx, expr),
69			Expression::Constant(expr) => self.constant(ctx, expr),
70			Expression::GreaterThan(expr) => self.greater_than(ctx, expr),
71			Expression::GreaterThanEqual(expr) => self.greater_than_equal(ctx, expr),
72			Expression::LessThan(expr) => self.less_than(ctx, expr),
73			Expression::LessThanEqual(expr) => self.less_than_equal(ctx, expr),
74			Expression::Equal(expr) => self.equal(ctx, expr),
75			Expression::NotEqual(expr) => self.not_equal(ctx, expr),
76			Expression::Between(expr) => self.between(ctx, expr),
77			Expression::And(expr) => self.and(ctx, expr),
78			Expression::Or(expr) => self.or(ctx, expr),
79			Expression::Xor(expr) => self.xor(ctx, expr),
80			Expression::Rem(expr) => self.rem(ctx, expr),
81			Expression::Mul(expr) => self.mul(ctx, expr),
82			Expression::Prefix(expr) => self.prefix(ctx, expr),
83			Expression::Sub(expr) => self.sub(ctx, expr),
84			Expression::Tuple(expr) => self.tuple(ctx, expr),
85			Expression::Parameter(expr) => self.parameter(ctx, expr),
86			Expression::Variable(expr) => self.variable(ctx, expr),
87			Expression::If(expr) => self.if_expr(ctx, expr),
88			Expression::Map(expr) => self.map_expr(ctx, expr),
89			Expression::Extend(expr) => self.extend_expr(ctx, expr),
90			expr => unimplemented!("{expr:?}"),
91		}
92	}
93}
94
95pub fn evaluate<'a>(ctx: &ColumnEvaluationContext<'a>, expr: &Expression<'a>) -> crate::Result<Column<'a>> {
96	let evaluator = StandardColumnEvaluator {
97		functions: Functions::builder()
98			.register_scalar("math::abs", math::scalar::Abs::new)
99			.register_scalar("math::avg", math::scalar::Avg::new)
100			.register_scalar("math::max", math::scalar::Max::new)
101			.register_scalar("math::min", math::scalar::Min::new)
102			.register_scalar("math::power", math::scalar::Power::new)
103			.register_scalar("math::round", math::scalar::Round::new)
104			.register_scalar("blob::hex", blob::BlobHex::new)
105			.register_scalar("blob::b58", blob::BlobB58::new)
106			.register_scalar("blob::b64", blob::BlobB64::new)
107			.register_scalar("blob::b64url", blob::BlobB64url::new)
108			.register_scalar("blob::utf8", blob::BlobUtf8::new)
109			.register_scalar("text::trim", text::TextTrim::new)
110			.register_scalar("text::upper", text::TextUpper::new)
111			.register_scalar("text::substring", text::TextSubstring::new)
112			.register_scalar("text::length", text::TextLength::new)
113			.build(),
114	};
115
116	// Ensures that result column data type matches the expected target
117	// column type
118	if let Some(ty) = ctx.target.as_ref().map(|c| c.column_type()) {
119		let mut column = evaluator.evaluate(ctx, expr)?;
120		let data = cast::cast_column_data(ctx, &column.data(), ty, &expr.lazy_fragment())?;
121		column = Column {
122			name: column.name,
123			data,
124		};
125		Ok(column)
126	} else {
127		evaluator.evaluate(ctx, expr)
128	}
129}