1use crate::upstream::fmt::{CoverStmts, EscapeKwFreeIdent, Fmt};
2use crate::upstream::sql::index::Distance;
3use crate::upstream::sql::{Expr, Kind};
4use surrealdb_types::{SqlFormat, ToSql, write_sql};
5#[derive(Clone, Debug, Eq, PartialEq)]
6#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
7pub enum PrefixOperator {
8 Not,
10 Positive,
12 Negate,
14 Range,
16 RangeInclusive,
18 Cast(Kind),
19}
20impl ToSql for PrefixOperator {
21 fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
22 match self {
23 Self::Not => f.push('!'),
24 Self::Positive => f.push('+'),
25 Self::Negate => f.push('-'),
26 Self::Range => f.push_str(".."),
27 Self::RangeInclusive => f.push_str("..="),
28 Self::Cast(kind) => write_sql!(f, fmt, "<{kind}> "),
29 }
30 }
31}
32#[derive(Clone, Debug, Eq, PartialEq)]
33#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
34pub enum PostfixOperator {
35 Range,
36 RangeSkip,
37 #[cfg_attr(feature = "arbitrary", arbitrary(skip))]
38 MethodCall(String, Vec<Expr>),
39 Call(Vec<Expr>),
40}
41impl ToSql for PostfixOperator {
42 fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
43 match self {
44 Self::Range => f.push_str(".."),
45 Self::RangeSkip => f.push_str(">.."),
46 Self::MethodCall(name, x) => {
47 write_sql!(
48 f,
49 fmt,
50 ".{}({})",
51 EscapeKwFreeIdent(name),
52 Fmt::comma_separated(x.iter().map(CoverStmts))
53 );
54 }
55 Self::Call(args) => {
56 write_sql!(
57 f,
58 fmt,
59 "({})",
60 Fmt::comma_separated(args.iter().map(CoverStmts))
61 )
62 }
63 }
64 }
65}
66#[derive(Clone, Debug, Eq, PartialEq)]
67#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
68pub enum BinaryOperator {
69 Subtract,
71 Add,
73 Multiply,
75 Divide,
77 Remainder,
79 Power,
81 Equal,
83 ExactEqual,
85 NotEqual,
87 AllEqual,
89 AnyEqual,
91 Or,
93 And,
95 NullCoalescing,
97 TenaryCondition,
98 LessThan,
100 LessThanEqual,
102 MoreThan,
104 MoreThanEqual,
106 Contain,
108 NotContain,
110 ContainAll,
112 ContainAny,
114 ContainNone,
116 Inside,
118 NotInside,
120 AllInside,
122 AnyInside,
124 NoneInside,
126 Outside,
128 Intersects,
130 Range,
132 RangeInclusive,
134 RangeSkip,
136 RangeSkipInclusive,
138 Matches(MatchesOperator),
139 NearestNeighbor(Box<NearestNeighbor>),
140}
141#[derive(Clone, Debug, Eq, PartialEq)]
142#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
143pub struct MatchesOperator {
144 pub rf: Option<u8>,
145 pub operator: Option<BooleanOperator>,
146}
147impl ToSql for MatchesOperator {
148 fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
149 if let Some(r) = self.rf {
150 if let Some(ref o) = self.operator {
151 if !matches!(o, BooleanOperator::And) {
152 write_sql!(f, fmt, "@{r},{o}@");
153 } else {
154 write_sql!(f, fmt, "@{r}@");
155 }
156 } else {
157 write_sql!(f, fmt, "@{r}@");
158 }
159 } else if let Some(ref o) = self.operator {
160 if !matches!(o, BooleanOperator::And) {
161 write_sql!(f, fmt, "@{o}@");
162 } else {
163 f.push_str("@@");
164 }
165 } else {
166 f.push_str("@@");
167 }
168 }
169}
170#[derive(Clone, Debug, Eq, PartialEq)]
172#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
173pub enum BooleanOperator {
174 And,
175 Or,
176}
177impl ToSql for BooleanOperator {
178 fn fmt_sql(&self, f: &mut String, _fmt: SqlFormat) {
179 match self {
180 Self::And => f.push_str("AND"),
181 Self::Or => f.push_str("OR"),
182 }
183 }
184}
185#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Hash)]
186#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
187pub enum NearestNeighbor {
188 K(u32, Distance),
190 KTree(u32),
192 Approximate(u32, u32),
194}
195impl ToSql for NearestNeighbor {
196 fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
197 match self {
198 Self::K(k, d) => write_sql!(f, fmt, "<|{k},{d}|>"),
199 Self::KTree(k) => write_sql!(f, fmt, "<|{k}|>"),
200 Self::Approximate(k, ef) => write_sql!(f, fmt, "<|{k},{ef}|>"),
201 }
202 }
203}
204impl ToSql for BinaryOperator {
205 fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
206 match self {
207 Self::Or => f.push_str("OR"),
208 Self::And => f.push_str("AND"),
209 Self::NullCoalescing => f.push_str("??"),
210 Self::TenaryCondition => f.push_str("?:"),
211 Self::Add => f.push('+'),
212 Self::Subtract => f.push('-'),
213 Self::Multiply => f.push('*'),
214 Self::Divide => f.push('/'),
215 Self::Remainder => f.push('%'),
216 Self::Power => f.push_str("**"),
217 Self::Equal => f.push('='),
218 Self::ExactEqual => f.push_str("=="),
219 Self::NotEqual => f.push_str("!="),
220 Self::AllEqual => f.push_str("*="),
221 Self::AnyEqual => f.push_str("?="),
222 Self::LessThan => f.push('<'),
223 Self::LessThanEqual => f.push_str("<="),
224 Self::MoreThan => f.push('>'),
225 Self::MoreThanEqual => f.push_str(">="),
226 Self::Contain => f.push_str("CONTAINS"),
227 Self::NotContain => f.push_str("CONTAINSNOT"),
228 Self::ContainAll => f.push_str("CONTAINSALL"),
229 Self::ContainAny => f.push_str("CONTAINSANY"),
230 Self::ContainNone => f.push_str("CONTAINSNONE"),
231 Self::Inside => f.push_str("INSIDE"),
232 Self::NotInside => f.push_str("NOTINSIDE"),
233 Self::AllInside => f.push_str("ALLINSIDE"),
234 Self::AnyInside => f.push_str("ANYINSIDE"),
235 Self::NoneInside => f.push_str("NONEINSIDE"),
236 Self::Outside => f.push_str("OUTSIDE"),
237 Self::Intersects => f.push_str("INTERSECTS"),
238 Self::Matches(m) => m.fmt_sql(f, fmt),
239 Self::Range => f.push_str(".."),
240 Self::RangeInclusive => f.push_str("..="),
241 Self::RangeSkip => f.push_str(">.."),
242 Self::RangeSkipInclusive => f.push_str(">..="),
243 Self::NearestNeighbor(n) => match &**n {
244 NearestNeighbor::KTree(k) => {
245 write_sql!(f, fmt, "<|{k}|>");
246 }
247 NearestNeighbor::K(k, distance) => {
248 write_sql!(f, fmt, "<|{k},{distance}|>");
249 }
250 NearestNeighbor::Approximate(k, ef) => {
251 write_sql!(f, fmt, "<|{k},{ef}|>");
252 }
253 },
254 }
255 }
256}
257#[derive(Clone, Debug, Eq, PartialEq, PartialOrd)]
258#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
259pub enum AssignOperator {
260 Assign,
261 Add,
262 Subtract,
263 Extend,
264}
265impl ToSql for AssignOperator {
266 fn fmt_sql(&self, f: &mut String, _fmt: SqlFormat) {
267 match self {
268 Self::Assign => f.push('='),
269 Self::Add => f.push_str("+="),
270 Self::Subtract => f.push_str("-="),
271 Self::Extend => f.push_str("+?="),
272 }
273 }
274}
275#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
280pub enum BindingPower {
281 Base,
282 Or,
283 And,
284 Equality,
285 Relation,
286 AddSub,
287 MulDiv,
288 Power,
289 Nullish,
290 Prefix,
291 Range,
292 Call,
293 Prime,
294}
295impl BindingPower {
296 pub fn for_binary_operator(op: &BinaryOperator) -> Self {
306 match op {
307 BinaryOperator::Or => BindingPower::Or,
308 BinaryOperator::And => BindingPower::And,
309 BinaryOperator::Equal
310 | BinaryOperator::ExactEqual
311 | BinaryOperator::NotEqual
312 | BinaryOperator::AllEqual
313 | BinaryOperator::AnyEqual => BindingPower::Equality,
314 BinaryOperator::LessThan
315 | BinaryOperator::LessThanEqual
316 | BinaryOperator::MoreThan
317 | BinaryOperator::MoreThanEqual
318 | BinaryOperator::Matches(_)
319 | BinaryOperator::Contain
320 | BinaryOperator::NotContain
321 | BinaryOperator::ContainAll
322 | BinaryOperator::ContainAny
323 | BinaryOperator::ContainNone
324 | BinaryOperator::Inside
325 | BinaryOperator::NotInside
326 | BinaryOperator::AllInside
327 | BinaryOperator::AnyInside
328 | BinaryOperator::NoneInside
329 | BinaryOperator::Outside
330 | BinaryOperator::Intersects
331 | BinaryOperator::NearestNeighbor(_) => BindingPower::Relation,
332 BinaryOperator::Add | BinaryOperator::Subtract => BindingPower::AddSub,
333 BinaryOperator::Multiply | BinaryOperator::Divide | BinaryOperator::Remainder => {
334 BindingPower::MulDiv
335 }
336 BinaryOperator::Power => BindingPower::Power,
337 BinaryOperator::NullCoalescing | BinaryOperator::TenaryCondition => {
338 BindingPower::Nullish
339 }
340 BinaryOperator::Range
341 | BinaryOperator::RangeInclusive
342 | BinaryOperator::RangeSkip
343 | BinaryOperator::RangeSkipInclusive => BindingPower::Range,
344 }
345 }
346 pub fn for_postfix_operator(op: &PostfixOperator) -> Self {
347 match op {
348 PostfixOperator::Range | PostfixOperator::RangeSkip => BindingPower::Range,
349 PostfixOperator::MethodCall(..) | PostfixOperator::Call(..) => BindingPower::Call,
350 }
351 }
352 pub fn for_prefix_operator(op: &PrefixOperator) -> Self {
353 match op {
354 PrefixOperator::Range | PrefixOperator::RangeInclusive => BindingPower::Range,
355 PrefixOperator::Not
356 | PrefixOperator::Positive
357 | PrefixOperator::Negate
358 | PrefixOperator::Cast(_) => BindingPower::Prefix,
359 }
360 }
361 pub fn for_expr(expr: &Expr) -> BindingPower {
366 match expr {
367 Expr::Prefix { op, .. } => {
368 if let PrefixOperator::Range | PrefixOperator::RangeInclusive = *op {
369 BindingPower::Range
370 } else {
371 BindingPower::Prefix
372 }
373 }
374 Expr::Postfix { op, .. } => {
375 if let PostfixOperator::Range | PostfixOperator::RangeSkip = *op {
376 BindingPower::Range
377 } else {
378 BindingPower::Prefix
379 }
380 }
381 Expr::Binary { op, .. } => BindingPower::for_binary_operator(op),
382 _ => BindingPower::Prime,
383 }
384 }
385}