surrealdb_sql/statements/
ifelse.rs1use crate::ctx::Context;
2use crate::dbs::{Options, Transaction};
3use crate::doc::CursorDoc;
4use crate::err::Error;
5use crate::fmt::{fmt_separated_by, is_pretty, pretty_indent, Fmt, Pretty};
6use crate::Value;
7use derive::Store;
8use revision::revisioned;
9use serde::{Deserialize, Serialize};
10use std::fmt::{self, Display, Write};
11
12#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
13#[revisioned(revision = 1)]
14pub struct IfelseStatement {
15 pub exprs: Vec<(Value, Value)>,
16 pub close: Option<Value>,
17}
18
19impl IfelseStatement {
20 pub(crate) fn writeable(&self) -> bool {
22 for (cond, then) in self.exprs.iter() {
23 if cond.writeable() || then.writeable() {
24 return true;
25 }
26 }
27 self.close.as_ref().map_or(false, |v| v.writeable())
28 }
29 pub(crate) fn bracketed(&self) -> bool {
31 self.exprs.iter().all(|(_, v)| matches!(v, Value::Block(_)))
32 && (self.close.as_ref().is_none()
33 || self.close.as_ref().is_some_and(|v| matches!(v, Value::Block(_))))
34 }
35 pub(crate) async fn compute(
37 &self,
38 ctx: &Context<'_>,
39 opt: &Options,
40 txn: &Transaction,
41 doc: Option<&CursorDoc<'_>>,
42 ) -> Result<Value, Error> {
43 for (ref cond, ref then) in &self.exprs {
44 let v = cond.compute(ctx, opt, txn, doc).await?;
45 if v.is_truthy() {
46 return then.compute(ctx, opt, txn, doc).await;
47 }
48 }
49 match self.close {
50 Some(ref v) => v.compute(ctx, opt, txn, doc).await,
51 None => Ok(Value::None),
52 }
53 }
54}
55
56impl Display for IfelseStatement {
57 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58 let mut f = Pretty::from(f);
59 match self.bracketed() {
60 true => {
61 write!(
62 f,
63 "{}",
64 &Fmt::new(
65 self.exprs.iter().map(|args| {
66 Fmt::new(args, |(cond, then), f| {
67 if is_pretty() {
68 write!(f, "IF {cond}")?;
69 let indent = pretty_indent();
70 write!(f, "{then}")?;
71 drop(indent);
72 } else {
73 write!(f, "IF {cond} {then}")?;
74 }
75 Ok(())
76 })
77 }),
78 if is_pretty() {
79 fmt_separated_by("ELSE")
80 } else {
81 fmt_separated_by(" ELSE ")
82 },
83 ),
84 )?;
85 if let Some(ref v) = self.close {
86 if is_pretty() {
87 write!(f, "ELSE")?;
88 let indent = pretty_indent();
89 write!(f, "{v}")?;
90 drop(indent);
91 } else {
92 write!(f, " ELSE {v}")?;
93 }
94 }
95 Ok(())
96 }
97 false => {
98 write!(
99 f,
100 "{}",
101 &Fmt::new(
102 self.exprs.iter().map(|args| {
103 Fmt::new(args, |(cond, then), f| {
104 if is_pretty() {
105 write!(f, "IF {cond} THEN")?;
106 let indent = pretty_indent();
107 write!(f, "{then}")?;
108 drop(indent);
109 } else {
110 write!(f, "IF {cond} THEN {then}")?;
111 }
112 Ok(())
113 })
114 }),
115 if is_pretty() {
116 fmt_separated_by("ELSE")
117 } else {
118 fmt_separated_by(" ELSE ")
119 },
120 ),
121 )?;
122 if let Some(ref v) = self.close {
123 if is_pretty() {
124 write!(f, "ELSE")?;
125 let indent = pretty_indent();
126 write!(f, "{v}")?;
127 drop(indent);
128 } else {
129 write!(f, " ELSE {v}")?;
130 }
131 }
132 if is_pretty() {
133 f.write_str("END")?;
134 } else {
135 f.write_str(" END")?;
136 }
137 Ok(())
138 }
139 }
140 }
141}