Skip to main content

surrealdb_sql/
idiom.rs

1use common::fmt::EscapeIdent;
2use surrealdb_strand::Strand;
3use surrealdb_types::write_sql;
4
5use crate::{Expr, Literal, Part};
6
7#[derive(Clone, Debug, Default, PartialEq, Eq)]
8pub struct Idiom(pub Vec<Part>);
9
10impl Idiom {
11	/// Simplifies this Idiom for use in object keys
12	pub fn simplify(&self) -> Idiom {
13		Idiom(
14			self.0
15				.iter()
16				.filter(|&p| matches!(p, Part::Field(_) | Part::Start(_) | Part::Graph(_)))
17				.cloned()
18				.collect(),
19		)
20	}
21
22	pub fn field(name: impl Into<Strand>) -> Self {
23		Idiom(vec![Part::Field(name.into())])
24	}
25}
26
27impl surrealdb_types::ToSql for Idiom {
28	fn fmt_sql(&self, f: &mut String, fmt: surrealdb_types::SqlFormat) {
29		let mut iter = self.0.iter();
30		match iter.next() {
31			Some(Part::Field(v)) => EscapeIdent(v).fmt_sql(f, fmt),
32			Some(Part::Start(x)) => {
33				if x.needs_parentheses()
34					|| matches!(x, Expr::Binary { .. } | Expr::Prefix { .. } | Expr::Postfix { .. })
35				{
36					write_sql!(f, fmt, "({x})");
37				} else if let Expr::Literal(Literal::Decimal(d)) = x
38					&& d.is_sign_negative()
39				{
40					write_sql!(f, fmt, "({x})");
41				} else if let Expr::Literal(Literal::Integer(i)) = x
42					&& i.is_negative()
43				{
44					write_sql!(f, fmt, "({x})");
45				} else if let Expr::Literal(Literal::Float(float)) = x
46					&& float.is_sign_negative()
47				{
48					write_sql!(f, fmt, "({x})");
49				} else {
50					write_sql!(f, fmt, "{x}");
51				}
52			}
53			Some(x) => x.fmt_sql(f, fmt),
54			None => {}
55		};
56		for p in iter {
57			p.fmt_sql(f, fmt);
58		}
59	}
60}