surrealdb_core/sql/
expression.rs

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