Skip to main content

surrealdb_expr/expr/
operator.rs

1use surrealdb_types::{SqlFormat, ToSql};
2
3use crate::expr::{Expr, Kind};
4use crate::sql::index::Distance;
5/// A reference number tying a MATCHES operator to its statement-local index.
6pub type MatchRef = u8;
7
8#[derive(Clone, Debug, Eq, PartialEq, Hash)]
9pub enum PrefixOperator {
10	/// `!`
11	Not,
12	/// `+`
13	Positive,
14	/// `-`
15	Negate,
16	/// `..`
17	Range,
18	/// `..=`
19	RangeInclusive,
20	Cast(Kind),
21}
22
23impl ToSql for PrefixOperator {
24	fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
25		let prefix_operator: crate::sql::PrefixOperator = self.clone().into();
26		prefix_operator.fmt_sql(f, sql_fmt);
27	}
28}
29
30#[derive(Clone, Debug, Eq, PartialEq, Hash)]
31pub enum PostfixOperator {
32	Range,
33	RangeSkip,
34	/// Not used as of yet but will be once the idiom is properly restructured.
35	MethodCall(String, Vec<Expr>),
36	Call(Vec<Expr>),
37}
38
39impl ToSql for PostfixOperator {
40	fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
41		let postfix_operator: crate::sql::PostfixOperator = self.clone().into();
42		postfix_operator.fmt_sql(f, sql_fmt);
43	}
44}
45
46#[derive(Clone, Debug, Eq, PartialEq, Hash)]
47pub enum BinaryOperator {
48	/// `-`
49	Subtract,
50	/// `+`
51	Add,
52	/// `*`, `×`
53	Multiply,
54	/// `/`
55	Divide,
56	/// `%`
57	Remainder,
58	/// `**`
59	Power,
60	/// `=`
61	Equal,
62	/// `==`
63	ExactEqual,
64	/// `!=`
65	NotEqual,
66	/// `*=`
67	AllEqual,
68	/// `?=`
69	AnyEqual,
70
71	/// `||`, `OR`
72	Or,
73	/// `&&`, `AND`
74	And,
75	/// `??`
76	NullCoalescing,
77	/// `?:`
78	TenaryCondition,
79
80	/// `<`
81	LessThan,
82	/// `<=`
83	LessThanEqual,
84	/// `>`
85	MoreThan,
86	/// `>=`
87	MoreThanEqual,
88
89	/// `∋`
90	Contain,
91	/// `∌`
92	NotContain,
93	/// `⊇`
94	ContainAll,
95	/// `⊃`
96	ContainAny,
97	/// `⊅`
98	ContainNone,
99	/// `∈`
100	Inside,
101	/// `∉`
102	NotInside,
103	/// `⊆`
104	AllInside,
105	/// `⊂`
106	AnyInside,
107	/// `⊄`
108	NoneInside,
109
110	/// `OUTSIDE`
111	Outside,
112	/// `INTERSECTS`
113	Intersects,
114
115	/// `..`
116	Range,
117	/// `..=`
118	RangeInclusive,
119	/// `>..`
120	RangeSkip,
121	/// `>..=`
122	RangeSkipInclusive,
123
124	// `@@`
125	Matches(MatchesOperator),
126	// `<|k,..|>`
127	NearestNeighbor(Box<NearestNeighbor>),
128}
129
130#[derive(Clone, Debug, Eq, PartialEq, Hash)]
131pub struct MatchesOperator {
132	pub rf: Option<MatchRef>,
133	pub operator: BooleanOperator,
134}
135
136impl ToSql for MatchesOperator {
137	fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
138		let matches_operator: crate::sql::operator::MatchesOperator = self.clone().into();
139		matches_operator.fmt_sql(f, sql_fmt);
140	}
141}
142
143/// Boolean operation executed by the full-text index
144
145#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
146pub enum BooleanOperator {
147	And,
148	Or,
149}
150
151impl ToSql for BooleanOperator {
152	fn fmt_sql(&self, f: &mut String, _fmt: SqlFormat) {
153		match self {
154			Self::And => f.push_str("AND"),
155			Self::Or => f.push_str("OR"),
156		}
157	}
158}
159
160#[derive(Clone, Debug, Eq, PartialEq, Hash)]
161pub enum NearestNeighbor {
162	/// `<|k, dist|>`
163	K(u32, Distance),
164	/// `<|k|>`
165	KTree(u32),
166	/// `<|k, ef|>`
167	Approximate(u32, u32),
168}
169
170impl ToSql for NearestNeighbor {
171	fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
172		let nn: crate::sql::operator::NearestNeighbor = self.clone().into();
173		nn.fmt_sql(f, sql_fmt);
174	}
175}
176
177impl ToSql for BinaryOperator {
178	fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
179		let binary_operator: crate::sql::BinaryOperator = self.clone().into();
180		binary_operator.fmt_sql(f, sql_fmt);
181	}
182}
183
184#[derive(Clone, Debug, Eq, PartialEq, Hash)]
185pub enum AssignOperator {
186	Assign,
187	Add,
188	Subtract,
189	Extend,
190}
191
192impl ToSql for AssignOperator {
193	fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
194		let op: crate::sql::AssignOperator = self.clone().into();
195		op.fmt_sql(f, sql_fmt);
196	}
197}
198
199/// An enum which defines how strong a operator binds it's operands.
200///
201/// If a binding power is higher the operator is more likely to directly operate
202/// on it's neighbours.
203#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
204#[allow(dead_code)]
205pub enum BindingPower {
206	Nullish,
207	Or,
208	And,
209	Equality,
210	Relation,
211	AddSub,
212	MulDiv,
213	Power,
214	Range,
215	Prefix,
216	Postfix,
217	Prime,
218}
219
220#[allow(dead_code)]
221impl BindingPower {
222	/// Returns the binding power of this operator.
223	///
224	/// Note that there are some variants here which can have multiple meanings.
225	/// `Operator::Equal` can be assignment but can also be equality.
226	/// `Operator::Add` can be the add operator but also the plus prefix
227	/// operator which have different binding powers.
228	///
229	/// This function returns the binding power for if the operator is used in
230	/// the infix position.
231	pub fn for_binary_operator(op: &BinaryOperator) -> Self {
232		match op {
233			BinaryOperator::Or => BindingPower::Or,
234			BinaryOperator::And => BindingPower::And,
235
236			BinaryOperator::Equal
237			| BinaryOperator::ExactEqual
238			| BinaryOperator::NotEqual
239			| BinaryOperator::AllEqual
240			| BinaryOperator::AnyEqual => BindingPower::Equality,
241
242			BinaryOperator::LessThan
243			| BinaryOperator::LessThanEqual
244			| BinaryOperator::MoreThan
245			| BinaryOperator::MoreThanEqual
246			| BinaryOperator::Matches(_)
247			| BinaryOperator::Contain
248			| BinaryOperator::NotContain
249			| BinaryOperator::ContainAll
250			| BinaryOperator::ContainAny
251			| BinaryOperator::ContainNone
252			| BinaryOperator::Inside
253			| BinaryOperator::NotInside
254			| BinaryOperator::AllInside
255			| BinaryOperator::AnyInside
256			| BinaryOperator::NoneInside
257			| BinaryOperator::Outside
258			| BinaryOperator::Intersects
259			| BinaryOperator::NearestNeighbor(_) => BindingPower::Relation,
260
261			BinaryOperator::Add | BinaryOperator::Subtract => BindingPower::AddSub,
262
263			BinaryOperator::Multiply | BinaryOperator::Divide | BinaryOperator::Remainder => {
264				BindingPower::MulDiv
265			}
266
267			BinaryOperator::Power => BindingPower::Power,
268
269			BinaryOperator::NullCoalescing | BinaryOperator::TenaryCondition => {
270				BindingPower::Nullish
271			}
272
273			BinaryOperator::Range
274			| BinaryOperator::RangeInclusive
275			| BinaryOperator::RangeSkip
276			| BinaryOperator::RangeSkipInclusive => BindingPower::Range,
277		}
278	}
279
280	pub fn for_postfix_operator(op: &PostfixOperator) -> Self {
281		match op {
282			PostfixOperator::Range | PostfixOperator::RangeSkip => BindingPower::Range,
283			PostfixOperator::MethodCall(..) | PostfixOperator::Call(..) => BindingPower::Postfix,
284		}
285	}
286
287	pub fn for_prefix_operator(op: &PrefixOperator) -> Self {
288		match op {
289			PrefixOperator::Range | PrefixOperator::RangeInclusive => BindingPower::Range,
290			PrefixOperator::Not
291			| PrefixOperator::Positive
292			| PrefixOperator::Negate
293			| PrefixOperator::Cast(_) => BindingPower::Prefix,
294		}
295	}
296	/// Returns the binding power for this expression. This is generally
297	/// `BindingPower::Prime` as most value variants are prime expressions,
298	/// however some like Value::Expression and Value::Range have a different
299	/// binding power.
300	pub fn for_expr(expr: &Expr) -> BindingPower {
301		match expr {
302			Expr::Prefix {
303				op,
304				..
305			} => Self::for_prefix_operator(op),
306			Expr::Postfix {
307				op,
308				..
309			} => BindingPower::for_postfix_operator(op),
310			Expr::Binary {
311				op,
312				..
313			} => BindingPower::for_binary_operator(op),
314			_ => BindingPower::Prime,
315		}
316	}
317}