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#[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 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 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 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 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 match self {
109 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 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 _ => {} }
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}