Skip to main content

reifydb_rql/expression/
fragment.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3use reifydb_type::{
4	fragment::Fragment,
5	value::{
6		Value,
7		boolean::parse::parse_bool,
8		number::parse::{parse_float, parse_primitive_int, parse_primitive_uint},
9	},
10};
11
12use crate::expression::{
13	AddExpression, CastExpression, ConstantExpression, DivExpression, Expression, MulExpression,
14	ParameterExpression, RemExpression, SubExpression,
15};
16
17impl Expression {
18	pub fn lazy_fragment(&self) -> impl Fn() -> Fragment {
19		move || match self {
20			Expression::AccessSource(expr) => expr.full_fragment_owned(),
21			Expression::Alias(expr) => expr.expression.full_fragment_owned(),
22			Expression::Cast(CastExpression {
23				expression: expr,
24				..
25			}) => expr.full_fragment_owned(),
26			Expression::Constant(expr) => match expr {
27				ConstantExpression::None {
28					fragment,
29				}
30				| ConstantExpression::Bool {
31					fragment,
32				}
33				| ConstantExpression::Number {
34					fragment,
35				}
36				| ConstantExpression::Temporal {
37					fragment,
38				}
39				| ConstantExpression::Text {
40					fragment,
41				} => fragment.clone(),
42			},
43			Expression::Column(expr) => expr.full_fragment_owned(),
44
45			Expression::Add(expr) => expr.full_fragment_owned(),
46			Expression::Sub(expr) => expr.full_fragment_owned(),
47			Expression::GreaterThan(expr) => expr.full_fragment_owned(),
48			Expression::GreaterThanEqual(expr) => expr.full_fragment_owned(),
49			Expression::LessThan(expr) => expr.full_fragment_owned(),
50			Expression::LessThanEqual(expr) => expr.full_fragment_owned(),
51			Expression::Equal(expr) => expr.full_fragment_owned(),
52			Expression::NotEqual(expr) => expr.full_fragment_owned(),
53			Expression::Between(expr) => expr.full_fragment_owned(),
54			Expression::And(expr) => expr.full_fragment_owned(),
55			Expression::Or(expr) => expr.full_fragment_owned(),
56			Expression::Xor(expr) => expr.full_fragment_owned(),
57
58			Expression::Mul(expr) => expr.full_fragment_owned(),
59			Expression::Div(expr) => expr.full_fragment_owned(),
60			Expression::Rem(expr) => expr.full_fragment_owned(),
61
62			Expression::Tuple(expr) => {
63				let fragments =
64					expr.expressions.iter().map(|e| e.full_fragment_owned()).collect::<Vec<_>>();
65				Fragment::merge_all(fragments)
66			}
67			Expression::List(expr) => {
68				let fragments =
69					expr.expressions.iter().map(|e| e.full_fragment_owned()).collect::<Vec<_>>();
70				Fragment::merge_all(fragments)
71			}
72			Expression::Type(expr) => expr.fragment.clone(),
73
74			Expression::Prefix(expr) => expr.full_fragment_owned(),
75
76			Expression::Call(expr) => expr.full_fragment_owned(),
77			Expression::Parameter(param) => match param {
78				ParameterExpression::Positional {
79					fragment,
80					..
81				} => fragment.clone(),
82				ParameterExpression::Named {
83					fragment,
84				} => fragment.clone(),
85			},
86			Expression::Variable(var) => var.fragment.clone(),
87			Expression::If(if_expr) => if_expr.full_fragment_owned(),
88			Expression::Map(map_expr) => map_expr.fragment.clone(),
89			Expression::Extend(extend_expr) => extend_expr.fragment.clone(),
90			Expression::In(in_expr) => in_expr.fragment.clone(),
91			Expression::Contains(contains_expr) => contains_expr.fragment.clone(),
92			Expression::SumTypeConstructor(ctor) => ctor.fragment.clone(),
93			Expression::IsVariant(e) => e.fragment.clone(),
94			Expression::FieldAccess(expr) => expr.full_fragment_owned(),
95		}
96	}
97}
98
99impl AddExpression {
100	pub fn full_fragment_owned(&self) -> Fragment {
101		Fragment::merge_all([
102			self.left.full_fragment_owned(),
103			self.fragment.clone(),
104			self.right.full_fragment_owned(),
105		])
106	}
107}
108
109impl ConstantExpression {
110	pub fn full_fragment_owned(&self) -> Fragment {
111		match self {
112			ConstantExpression::None {
113				fragment,
114			} => fragment.clone(),
115			ConstantExpression::Bool {
116				fragment,
117			} => fragment.clone(),
118			ConstantExpression::Number {
119				fragment,
120			} => fragment.clone(),
121			ConstantExpression::Temporal {
122				fragment,
123			} => fragment.clone(),
124			ConstantExpression::Text {
125				fragment,
126			} => fragment.clone(),
127		}
128	}
129
130	pub fn to_value(&self) -> Value {
131		match self {
132			Self::None {
133				..
134			} => Value::none(),
135			Self::Bool {
136				fragment,
137			} => parse_bool(fragment.clone()).map(Value::Boolean).unwrap_or(Value::none()),
138			Self::Number {
139				fragment,
140			} => Self::parse_number(fragment),
141			Self::Text {
142				fragment,
143			} => Value::Utf8(fragment.text().to_string()),
144			Self::Temporal {
145				fragment,
146			} => Value::Utf8(fragment.text().to_string()),
147		}
148	}
149
150	fn parse_number(fragment: &Fragment) -> Value {
151		let text = fragment.text();
152		if text.contains('.') || text.contains('e') || text.contains('E') {
153			return parse_float::<f64>(fragment.clone()).map(Value::float8).unwrap_or(Value::none());
154		}
155		parse_primitive_int::<i8>(fragment.clone())
156			.map(Value::Int1)
157			.or_else(|_| parse_primitive_int::<i16>(fragment.clone()).map(Value::Int2))
158			.or_else(|_| parse_primitive_int::<i32>(fragment.clone()).map(Value::Int4))
159			.or_else(|_| parse_primitive_int::<i64>(fragment.clone()).map(Value::Int8))
160			.or_else(|_| parse_primitive_int::<i128>(fragment.clone()).map(Value::Int16))
161			.or_else(|_| parse_primitive_uint::<u128>(fragment.clone()).map(Value::Uint16))
162			.unwrap_or(Value::none())
163	}
164}
165
166impl SubExpression {
167	pub fn full_fragment_owned(&self) -> Fragment {
168		Fragment::merge_all([
169			self.left.full_fragment_owned(),
170			self.fragment.clone(),
171			self.right.full_fragment_owned(),
172		])
173	}
174}
175
176impl MulExpression {
177	pub fn full_fragment_owned(&self) -> Fragment {
178		Fragment::merge_all([
179			self.left.full_fragment_owned(),
180			self.fragment.clone(),
181			self.right.full_fragment_owned(),
182		])
183	}
184}
185
186impl DivExpression {
187	pub fn full_fragment_owned(&self) -> Fragment {
188		Fragment::merge_all([
189			self.left.full_fragment_owned(),
190			self.fragment.clone(),
191			self.right.full_fragment_owned(),
192		])
193	}
194}
195
196impl RemExpression {
197	pub fn full_fragment_owned(&self) -> Fragment {
198		Fragment::merge_all([
199			self.left.full_fragment_owned(),
200			self.fragment.clone(),
201			self.right.full_fragment_owned(),
202		])
203	}
204}
205
206impl Expression {
207	pub fn full_fragment_owned(&self) -> Fragment {
208		self.lazy_fragment()()
209	}
210}