surrealpatch/core/src/sql/operator.rs
2024-05-08 14:26:41 +00:00

156 lines
3.7 KiB
Rust

use crate::idx::ft::MatchRef;
use crate::sql::index::Distance;
use revision::revisioned;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::fmt::Write;
/// Binary operators.
#[revisioned(revision = 2)]
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[non_exhaustive]
pub enum Operator {
//
Neg, // -
Not, // !
//
Or, // ||
And, // &&
Tco, // ?: Ternary conditional operator
Nco, // ?? Null coalescing operator
//
Add, // +
Sub, // -
Mul, // *
Div, // /
Pow, // **
Inc, // +=
Dec, // -=
Ext, // +?=
//
Equal, // =
Exact, // ==
NotEqual, // !=
AllEqual, // *=
AnyEqual, // ?=
//
Like, // ~
NotLike, // !~
AllLike, // *~
AnyLike, // ?~
Matches(Option<MatchRef>), // @{ref}@
//
LessThan, // <
LessThanOrEqual, // <=
MoreThan, // >
MoreThanOrEqual, // >=
//
Contain, // ∋
NotContain, // ∌
ContainAll, // ⊇
ContainAny, // ⊃
ContainNone, // ⊅
Inside, // ∈
NotInside, // ∉
AllInside, // ⊆
AnyInside, // ⊂
NoneInside, // ⊄
//
Outside,
Intersects,
//
Knn(u32, Option<Distance>), // <|{k}[,{dist}]|>
#[revision(start = 2)]
Ann(u32, u32), // <|{k},{ef}|>
//
Rem, // %
}
impl Default for Operator {
fn default() -> Self {
Self::Equal
}
}
impl Operator {
#[inline]
pub fn precedence(&self) -> u8 {
match self {
Self::Or => 1,
Self::And => 2,
Self::Tco => 3,
Self::Nco => 4,
Self::Sub => 6,
Self::Add => 7,
Self::Mul => 8,
Self::Div => 9,
Self::Rem => 10,
_ => 5,
}
}
}
impl fmt::Display for Operator {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Neg => f.write_str("-"),
Self::Not => f.write_str("!"),
Self::Or => f.write_str("OR"),
Self::And => f.write_str("AND"),
Self::Tco => f.write_str("?:"),
Self::Nco => f.write_str("??"),
Self::Add => f.write_str("+"),
Self::Sub => f.write_char('-'),
Self::Mul => f.write_char('*'),
Self::Div => f.write_char('/'),
Self::Rem => f.write_char('%'),
Self::Pow => f.write_str("**"),
Self::Inc => f.write_str("+="),
Self::Dec => f.write_str("-="),
Self::Ext => f.write_str("+?="),
Self::Equal => f.write_char('='),
Self::Exact => f.write_str("=="),
Self::NotEqual => f.write_str("!="),
Self::AllEqual => f.write_str("*="),
Self::AnyEqual => f.write_str("?="),
Self::Like => f.write_char('~'),
Self::NotLike => f.write_str("!~"),
Self::AllLike => f.write_str("*~"),
Self::AnyLike => f.write_str("?~"),
Self::LessThan => f.write_char('<'),
Self::LessThanOrEqual => f.write_str("<="),
Self::MoreThan => f.write_char('>'),
Self::MoreThanOrEqual => f.write_str(">="),
Self::Contain => f.write_str("CONTAINS"),
Self::NotContain => f.write_str("CONTAINSNOT"),
Self::ContainAll => f.write_str("CONTAINSALL"),
Self::ContainAny => f.write_str("CONTAINSANY"),
Self::ContainNone => f.write_str("CONTAINSNONE"),
Self::Inside => f.write_str("INSIDE"),
Self::NotInside => f.write_str("NOTINSIDE"),
Self::AllInside => f.write_str("ALLINSIDE"),
Self::AnyInside => f.write_str("ANYINSIDE"),
Self::NoneInside => f.write_str("NONEINSIDE"),
Self::Outside => f.write_str("OUTSIDE"),
Self::Intersects => f.write_str("INTERSECTS"),
Self::Matches(reference) => {
if let Some(r) = reference {
write!(f, "@{r}@")
} else {
f.write_str("@@")
}
}
Self::Knn(k, dist) => {
if let Some(d) = dist {
write!(f, "<|{k},{d}|>")
} else {
write!(f, "<|{k}|>")
}
}
Self::Ann(k, ef) => {
write!(f, "<{k},{ef}>")
}
}
}
}