Skip to main content

surql_parser/upstream/sql/
idiom.rs

1use crate::upstream::fmt::{EscapeIdent, Fmt};
2use crate::upstream::sql::{Expr, Literal, Part};
3use std::ops::Deref;
4use surrealdb_types::{SqlFormat, ToSql, write_sql};
5#[derive(Clone, Debug, Default, Eq, PartialEq)]
6#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
7#[allow(dead_code)]
8pub struct Idioms(pub Vec<Idiom>);
9impl Deref for Idioms {
10	type Target = Vec<Idiom>;
11	fn deref(&self) -> &Self::Target {
12		&self.0
13	}
14}
15impl IntoIterator for Idioms {
16	type Item = Idiom;
17	type IntoIter = std::vec::IntoIter<Self::Item>;
18	fn into_iter(self) -> Self::IntoIter {
19		self.0.into_iter()
20	}
21}
22impl ToSql for Idioms {
23	fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
24		write_sql!(f, fmt, "{}", Fmt::comma_separated(&self.0))
25	}
26}
27#[derive(Clone, Debug, Default, PartialEq, Eq)]
28pub struct Idiom(pub Vec<Part>);
29impl Idiom {
30	/// Simplifies this Idiom for use in object keys
31	pub fn simplify(&self) -> Idiom {
32		Idiom(
33			self.0
34				.iter()
35				.filter(|&p| matches!(p, Part::Field(_) | Part::Start(_) | Part::Graph(_)))
36				.cloned()
37				.collect(),
38		)
39	}
40	pub fn field(name: String) -> Self {
41		Idiom(vec![Part::Field(name)])
42	}
43}
44impl surrealdb_types::ToSql for Idiom {
45	fn fmt_sql(&self, f: &mut String, fmt: surrealdb_types::SqlFormat) {
46		let mut iter = self.0.iter();
47		match iter.next() {
48			Some(Part::Field(v)) => EscapeIdent(v).fmt_sql(f, fmt),
49			Some(Part::Start(x)) => {
50				if x.needs_parentheses()
51					|| matches!(
52						x,
53						Expr::Binary { .. } | Expr::Prefix { .. } | Expr::Postfix { .. }
54					) {
55					write_sql!(f, fmt, "({x})");
56				} else if let Expr::Literal(Literal::Decimal(d)) = x
57					&& d.is_sign_negative()
58				{
59					write_sql!(f, fmt, "({x})");
60				} else if let Expr::Literal(Literal::Integer(i)) = x
61					&& i.is_negative()
62				{
63					write_sql!(f, fmt, "({x})");
64				} else if let Expr::Literal(Literal::Float(float)) = x
65					&& float.is_sign_negative()
66				{
67					write_sql!(f, fmt, "({x})");
68				} else {
69					write_sql!(f, fmt, "{x}");
70				}
71			}
72			Some(x) => x.fmt_sql(f, fmt),
73			None => {}
74		};
75		for p in iter {
76			p.fmt_sql(f, fmt);
77		}
78	}
79}