1use crate::ctx::{Context, MutableContext};
2use crate::dbs::Options;
3use crate::doc::CursorDoc;
4use crate::err::Error;
5use crate::sql::fmt::{is_pretty, pretty_indent, Fmt, Pretty};
6use crate::sql::statements::info::InfoStructure;
7use crate::sql::statements::rebuild::RebuildStatement;
8use crate::sql::statements::{
9 AlterStatement, BreakStatement, ContinueStatement, CreateStatement, DefineStatement,
10 DeleteStatement, ForeachStatement, IfelseStatement, InsertStatement, OutputStatement,
11 RelateStatement, RemoveStatement, SelectStatement, SetStatement, ThrowStatement,
12 UpdateStatement, UpsertStatement,
13};
14use crate::sql::value::Value;
15use reblessive::tree::Stk;
16use revision::revisioned;
17use serde::{Deserialize, Serialize};
18use std::cmp::Ordering;
19use std::fmt::{self, Display, Formatter, Write};
20use std::ops::Deref;
21
22pub(crate) const TOKEN: &str = "$surrealdb::private::sql::Block";
23
24#[revisioned(revision = 1)]
25#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
26#[serde(rename = "$surrealdb::private::sql::Block")]
27#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
28#[non_exhaustive]
29pub struct Block(pub Vec<Entry>);
30
31impl Deref for Block {
32 type Target = Vec<Entry>;
33 fn deref(&self) -> &Self::Target {
34 &self.0
35 }
36}
37
38impl From<Value> for Block {
39 fn from(v: Value) -> Self {
40 Block(vec![Entry::Value(v)])
41 }
42}
43
44impl Block {
45 pub(crate) fn writeable(&self) -> bool {
47 self.iter().any(Entry::writeable)
48 }
49 pub(crate) async fn compute(
51 &self,
52 stk: &mut Stk,
53 ctx: &Context,
54 opt: &Options,
55 doc: Option<&CursorDoc>,
56 ) -> Result<Value, Error> {
57 let mut ctx = MutableContext::new(ctx).freeze();
59 for (i, v) in self.iter().enumerate() {
61 match v {
62 Entry::Set(v) => {
63 let val = v.compute(stk, &ctx, opt, doc).await?;
64 let mut c = MutableContext::unfreeze(ctx)?;
65 c.add_value(v.name.to_owned(), val.into());
66 ctx = c.freeze();
67 }
68 Entry::Throw(v) => {
69 v.compute(stk, &ctx, opt, doc).await?;
71 }
72 Entry::Break(v) => {
73 v.compute(&ctx, opt, doc).await?;
75 }
76 Entry::Continue(v) => {
77 v.compute(&ctx, opt, doc).await?;
79 }
80 Entry::Foreach(v) => {
81 v.compute(stk, &ctx, opt, doc).await?;
82 }
83 Entry::Ifelse(v) => {
84 v.compute(stk, &ctx, opt, doc).await?;
85 }
86 Entry::Select(v) => {
87 v.compute(stk, &ctx, opt, doc).await?;
88 }
89 Entry::Create(v) => {
90 v.compute(stk, &ctx, opt, doc).await?;
91 }
92 Entry::Upsert(v) => {
93 v.compute(stk, &ctx, opt, doc).await?;
94 }
95 Entry::Update(v) => {
96 v.compute(stk, &ctx, opt, doc).await?;
97 }
98 Entry::Delete(v) => {
99 v.compute(stk, &ctx, opt, doc).await?;
100 }
101 Entry::Relate(v) => {
102 v.compute(stk, &ctx, opt, doc).await?;
103 }
104 Entry::Insert(v) => {
105 v.compute(stk, &ctx, opt, doc).await?;
106 }
107 Entry::Define(v) => {
108 v.compute(stk, &ctx, opt, doc).await?;
109 }
110 Entry::Rebuild(v) => {
111 v.compute(stk, &ctx, opt, doc).await?;
112 }
113 Entry::Remove(v) => {
114 v.compute(&ctx, opt, doc).await?;
115 }
116 Entry::Output(v) => {
117 v.compute(stk, &ctx, opt, doc).await?;
118 }
119 Entry::Alter(v) => {
120 v.compute(stk, &ctx, opt, doc).await?;
121 }
122 Entry::Value(v) => {
123 if i == self.len() - 1 {
124 return v.compute_unbordered(stk, &ctx, opt, doc).await;
126 } else {
127 v.compute_unbordered(stk, &ctx, opt, doc).await?;
129 }
130 }
131 }
132 }
133 Ok(Value::None)
135 }
136}
137
138impl Display for Block {
139 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
140 let mut f = Pretty::from(f);
141 match (self.len(), self.first()) {
142 (0, _) => f.write_str("{}"),
143 (1, Some(Entry::Value(v))) => {
144 write!(f, "{{ {v} }}")
145 }
146 (l, _) => {
147 f.write_char('{')?;
148 if l > 1 {
149 f.write_char('\n')?;
150 } else if !is_pretty() {
151 f.write_char(' ')?;
152 }
153 let indent = pretty_indent();
154 if is_pretty() {
155 write!(
156 f,
157 "{}",
158 &Fmt::two_line_separated(
159 self.0.iter().map(|args| Fmt::new(args, |v, f| write!(f, "{};", v))),
160 )
161 )?;
162 } else {
163 write!(
164 f,
165 "{}",
166 &Fmt::one_line_separated(
167 self.0.iter().map(|args| Fmt::new(args, |v, f| write!(f, "{};", v))),
168 )
169 )?;
170 }
171 drop(indent);
172 if l > 1 {
173 f.write_char('\n')?;
174 } else if !is_pretty() {
175 f.write_char(' ')?;
176 }
177 f.write_char('}')
178 }
179 }
180 }
181}
182
183impl InfoStructure for Block {
184 fn structure(self) -> Value {
185 self.to_string().into()
186 }
187}
188
189#[revisioned(revision = 4)]
190#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)]
191#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
192#[non_exhaustive]
193pub enum Entry {
194 Value(Value),
195 Set(SetStatement),
196 Ifelse(IfelseStatement),
197 Select(SelectStatement),
198 Create(CreateStatement),
199 Update(UpdateStatement),
200 Delete(DeleteStatement),
201 Relate(RelateStatement),
202 Insert(InsertStatement),
203 Output(OutputStatement),
204 Define(DefineStatement),
205 Remove(RemoveStatement),
206 Throw(ThrowStatement),
207 Break(BreakStatement),
208 Continue(ContinueStatement),
209 Foreach(ForeachStatement),
210 #[revision(start = 2)]
211 Rebuild(RebuildStatement),
212 #[revision(start = 3)]
213 Upsert(UpsertStatement),
214 #[revision(start = 4)]
215 Alter(AlterStatement),
216}
217
218impl PartialOrd for Entry {
219 #[inline]
220 fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
221 None
222 }
223}
224
225impl Entry {
226 pub(crate) fn writeable(&self) -> bool {
228 match self {
229 Self::Set(v) => v.writeable(),
230 Self::Value(v) => v.writeable(),
231 Self::Ifelse(v) => v.writeable(),
232 Self::Select(v) => v.writeable(),
233 Self::Create(v) => v.writeable(),
234 Self::Upsert(v) => v.writeable(),
235 Self::Update(v) => v.writeable(),
236 Self::Delete(v) => v.writeable(),
237 Self::Relate(v) => v.writeable(),
238 Self::Insert(v) => v.writeable(),
239 Self::Output(v) => v.writeable(),
240 Self::Define(v) => v.writeable(),
241 Self::Rebuild(v) => v.writeable(),
242 Self::Remove(v) => v.writeable(),
243 Self::Throw(v) => v.writeable(),
244 Self::Break(v) => v.writeable(),
245 Self::Continue(v) => v.writeable(),
246 Self::Foreach(v) => v.writeable(),
247 Self::Alter(v) => v.writeable(),
248 }
249 }
250}
251
252impl Display for Entry {
253 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
254 match self {
255 Self::Set(v) => write!(f, "{v}"),
256 Self::Value(v) => Display::fmt(v, f),
257 Self::Ifelse(v) => write!(f, "{v}"),
258 Self::Select(v) => write!(f, "{v}"),
259 Self::Create(v) => write!(f, "{v}"),
260 Self::Upsert(v) => write!(f, "{v}"),
261 Self::Update(v) => write!(f, "{v}"),
262 Self::Delete(v) => write!(f, "{v}"),
263 Self::Relate(v) => write!(f, "{v}"),
264 Self::Insert(v) => write!(f, "{v}"),
265 Self::Output(v) => write!(f, "{v}"),
266 Self::Define(v) => write!(f, "{v}"),
267 Self::Rebuild(v) => write!(f, "{v}"),
268 Self::Remove(v) => write!(f, "{v}"),
269 Self::Throw(v) => write!(f, "{v}"),
270 Self::Break(v) => write!(f, "{v}"),
271 Self::Continue(v) => write!(f, "{v}"),
272 Self::Foreach(v) => write!(f, "{v}"),
273 Self::Alter(v) => write!(f, "{v}"),
274 }
275 }
276}