surrealdb_sql/
expression.rs

1use crate::ctx::Context;
2use crate::dbs::{Options, Transaction};
3use crate::doc::CursorDoc;
4use crate::err::Error;
5use crate::fnc;
6use crate::operator::Operator;
7use crate::value::Value;
8use revision::revisioned;
9use serde::{Deserialize, Serialize};
10use std::fmt;
11use std::str;
12
13pub(crate) const TOKEN: &str = "$surrealdb::private::crate::Expression";
14
15/// Binary expressions.
16#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
17#[serde(rename = "$surrealdb::private::crate::Expression")]
18#[revisioned(revision = 1)]
19pub enum Expression {
20	Unary {
21		o: Operator,
22		v: Value,
23	},
24	Binary {
25		l: Value,
26		o: Operator,
27		r: Value,
28	},
29}
30
31impl Default for Expression {
32	fn default() -> Expression {
33		Expression::Binary {
34			l: Value::Null,
35			o: Operator::default(),
36			r: Value::Null,
37		}
38	}
39}
40
41impl Expression {
42	/// Create a new binary expression
43	#[doc(hidden)]
44	pub fn new(l: Value, o: Operator, r: Value) -> Self {
45		Self::Binary {
46			l,
47			o,
48			r,
49		}
50	}
51	/// Augment an existing expression
52	pub(crate) fn augment(mut self, l: Value, o: Operator) -> Self {
53		match &mut self {
54			Self::Binary {
55				l: left,
56				o: op,
57				..
58			} if o.precedence() >= op.precedence() => match left {
59				Value::Expression(x) => {
60					*x.as_mut() = std::mem::take(x).augment(l, o);
61					self
62				}
63				_ => {
64					*left = Self::new(l, o, std::mem::take(left)).into();
65					self
66				}
67			},
68			e => {
69				let r = Value::from(std::mem::take(e));
70				Self::new(l, o, r)
71			}
72		}
73	}
74}
75
76impl Expression {
77	pub(crate) fn writeable(&self) -> bool {
78		match self {
79			Self::Unary {
80				v,
81				..
82			} => v.writeable(),
83			Self::Binary {
84				l,
85				r,
86				..
87			} => l.writeable() || r.writeable(),
88		}
89	}
90
91	pub(crate) fn is_static(&self) -> bool {
92		match self {
93			Self::Unary {
94				v,
95				..
96			} => v.is_static(),
97			Self::Binary {
98				l,
99				r,
100				..
101			} => l.is_static() && r.is_static(),
102		}
103	}
104
105	/// Returns the operator
106	pub(crate) fn operator(&self) -> &Operator {
107		match self {
108			Expression::Unary {
109				o,
110				..
111			} => o,
112			Expression::Binary {
113				o,
114				..
115			} => o,
116		}
117	}
118
119	/// Process this type returning a computed simple Value
120	pub(crate) async fn compute(
121		&self,
122		ctx: &Context<'_>,
123		opt: &Options,
124		txn: &Transaction,
125		doc: Option<&CursorDoc<'_>>,
126	) -> Result<Value, Error> {
127		let (l, o, r) = match self {
128			Self::Unary {
129				o,
130				v,
131			} => {
132				let operand = v.compute(ctx, opt, txn, doc).await?;
133				return match o {
134					Operator::Neg => fnc::operate::neg(operand),
135					Operator::Not => fnc::operate::not(operand),
136					op => unreachable!("{op:?} is not a unary op"),
137				};
138			}
139			Self::Binary {
140				l,
141				o,
142				r,
143			} => (l, o, r),
144		};
145
146		let l = l.compute(ctx, opt, txn, doc).await?;
147		match o {
148			Operator::Or => {
149				if let true = l.is_truthy() {
150					return Ok(l);
151				}
152			}
153			Operator::And => {
154				if let false = l.is_truthy() {
155					return Ok(l);
156				}
157			}
158			Operator::Tco => {
159				if let true = l.is_truthy() {
160					return Ok(l);
161				}
162			}
163			Operator::Nco => {
164				if let true = l.is_some() {
165					return Ok(l);
166				}
167			}
168			_ => {} // Continue
169		}
170		let r = r.compute(ctx, opt, txn, doc).await?;
171		match o {
172			Operator::Or => fnc::operate::or(l, r),
173			Operator::And => fnc::operate::and(l, r),
174			Operator::Tco => fnc::operate::tco(l, r),
175			Operator::Nco => fnc::operate::nco(l, r),
176			Operator::Add => fnc::operate::add(l, r),
177			Operator::Sub => fnc::operate::sub(l, r),
178			Operator::Mul => fnc::operate::mul(l, r),
179			Operator::Div => fnc::operate::div(l, r),
180			Operator::Pow => fnc::operate::pow(l, r),
181			Operator::Equal => fnc::operate::equal(&l, &r),
182			Operator::Exact => fnc::operate::exact(&l, &r),
183			Operator::NotEqual => fnc::operate::not_equal(&l, &r),
184			Operator::AllEqual => fnc::operate::all_equal(&l, &r),
185			Operator::AnyEqual => fnc::operate::any_equal(&l, &r),
186			Operator::Like => fnc::operate::like(&l, &r),
187			Operator::NotLike => fnc::operate::not_like(&l, &r),
188			Operator::AllLike => fnc::operate::all_like(&l, &r),
189			Operator::AnyLike => fnc::operate::any_like(&l, &r),
190			Operator::LessThan => fnc::operate::less_than(&l, &r),
191			Operator::LessThanOrEqual => fnc::operate::less_than_or_equal(&l, &r),
192			Operator::MoreThan => fnc::operate::more_than(&l, &r),
193			Operator::MoreThanOrEqual => fnc::operate::more_than_or_equal(&l, &r),
194			Operator::Contain => fnc::operate::contain(&l, &r),
195			Operator::NotContain => fnc::operate::not_contain(&l, &r),
196			Operator::ContainAll => fnc::operate::contain_all(&l, &r),
197			Operator::ContainAny => fnc::operate::contain_any(&l, &r),
198			Operator::ContainNone => fnc::operate::contain_none(&l, &r),
199			Operator::Inside => fnc::operate::inside(&l, &r),
200			Operator::NotInside => fnc::operate::not_inside(&l, &r),
201			Operator::AllInside => fnc::operate::inside_all(&l, &r),
202			Operator::AnyInside => fnc::operate::inside_any(&l, &r),
203			Operator::NoneInside => fnc::operate::inside_none(&l, &r),
204			Operator::Outside => fnc::operate::outside(&l, &r),
205			Operator::Intersects => fnc::operate::intersects(&l, &r),
206			Operator::Matches(_) => fnc::operate::matches(ctx, txn, doc, self).await,
207			Operator::Knn(_) => fnc::operate::knn(ctx, txn, doc, self).await,
208			_ => unreachable!(),
209		}
210	}
211}
212
213impl fmt::Display for Expression {
214	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
215		match self {
216			Self::Unary {
217				o,
218				v,
219			} => write!(f, "{o}{v}"),
220			Self::Binary {
221				l,
222				o,
223				r,
224			} => write!(f, "{l} {o} {r}"),
225		}
226	}
227}