Skip to main content

surrealdb_sql/
block.rs

1use surrealdb_types::{SqlFormat, ToSql, write_sql};
2
3use crate::{BinaryOperator, Expr, Literal};
4
5#[derive(Clone, Debug, PartialEq, Eq)]
6#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
7pub struct Block(pub Vec<Expr>);
8
9impl ToSql for Block {
10	fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
11		match self.0.len() {
12			0 => f.push_str("{;}"),
13			1 => {
14				let v = &self.0[0];
15				if fmt.is_pretty() {
16					// Pretty mode: use expanded format even for single element
17					f.push('{');
18					f.push('\n');
19					f.push('\n');
20					let fmt = fmt.increment();
21					fmt.write_indent(f);
22					if let Expr::Literal(Literal::RecordId(_)) = v {
23						write_sql!(f, fmt, "({v})");
24					} else if let Expr::Binary {
25						left,
26						op: BinaryOperator::Equal,
27						..
28					} = v && let Expr::Param(_) = **left
29					{
30						write_sql!(f, fmt, "({v})");
31					} else {
32						v.fmt_sql(f, fmt);
33					}
34					f.push('\n');
35					// Write indent at the block's level
36					if let SqlFormat::Indented(level) = fmt
37						&& level > 0
38					{
39						for _ in 0..(level - 1) {
40							f.push('\t');
41						}
42					}
43					f.push('}')
44				} else {
45					// Non-pretty: compact format
46					f.push_str("{ ");
47					if let Expr::Literal(Literal::RecordId(_)) = v {
48						write_sql!(f, fmt, "({v})");
49					} else if let Expr::Binary {
50						left,
51						op: BinaryOperator::Equal,
52						..
53					} = v && let Expr::Param(_) = **left
54					{
55						write_sql!(f, fmt, "({v})");
56					} else {
57						v.fmt_sql(f, fmt);
58					}
59					f.push_str(" }");
60				}
61			}
62			_ => {
63				// Multi-element blocks
64				if fmt.is_pretty() {
65					f.push('{');
66					f.push('\n');
67					f.push('\n');
68					let fmt = fmt.increment();
69					for (i, v) in self.0.iter().enumerate() {
70						if i > 0 {
71							f.push('\n');
72							f.push('\n');
73						}
74						fmt.write_indent(f);
75						if i == 0
76							&& let Expr::Literal(Literal::RecordId(_)) = v
77						{
78							write_sql!(f, fmt, "({v})");
79						} else if let Expr::Binary {
80							left,
81							op: BinaryOperator::Equal,
82							..
83						} = v && let Expr::Param(_) = **left
84						{
85							write_sql!(f, fmt, "({v})");
86						} else {
87							v.fmt_sql(f, fmt);
88						}
89						f.push(';');
90					}
91					f.push('\n');
92					// Write indent at the block's level (not the content level)
93					// The content was at fmt (incremented), so block's level is one less
94					if let SqlFormat::Indented(level) = fmt
95						&& level > 0
96					{
97						for _ in 0..(level - 1) {
98							f.push('\t');
99						}
100					}
101					f.push('}')
102				} else {
103					// Non-pretty: all on one line with space separation
104					f.push_str("{ ");
105					for (i, v) in self.0.iter().enumerate() {
106						if i > 0 {
107							f.push(' ');
108						}
109
110						if i == 0
111							&& let Expr::Literal(Literal::RecordId(_)) = v
112						{
113							write_sql!(f, fmt, "({v})");
114						} else if let Expr::Binary {
115							left,
116							op: BinaryOperator::Equal,
117							..
118						} = v && let Expr::Param(_) = **left
119						{
120							write_sql!(f, fmt, "({v})");
121						} else {
122							v.fmt_sql(f, fmt);
123						}
124
125						f.push(';');
126					}
127					f.push_str(" }")
128				}
129			}
130		}
131	}
132}