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