surql_parser/upstream/fmt/
mod.rs1mod escape;
3use crate::compat::fmt::fmt_non_finite_f64;
4use crate::upstream::sql;
5pub use escape::{
6 EscapeIdent, EscapeKwFreeIdent, EscapeKwIdent, EscapeObjectKey, EscapeRidKey, QuoteStr,
7};
8use std::cell::Cell;
9use std::fmt::Display;
10use surrealdb_types::{SqlFormat, ToSql};
11pub struct Fmt<T, F> {
13 contents: Cell<Option<T>>,
14 formatter: F,
15}
16impl<T, F: Fn(T, &mut String, SqlFormat)> Fmt<T, F> {
17 pub fn new(t: T, formatter: F) -> Self {
18 Self {
19 contents: Cell::new(Some(t)),
20 formatter,
21 }
22 }
23}
24impl<T, F: Fn(T, &mut String, SqlFormat)> ToSql for Fmt<T, F> {
25 fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
27 let contents = self
28 .contents
29 .replace(None)
30 .expect("only call Fmt::fmt once");
31 (self.formatter)(contents, f, fmt)
32 }
33}
34impl<I: IntoIterator<Item = T>, T: ToSql> Fmt<I, fn(I, &mut String, SqlFormat)> {
35 pub fn comma_separated(into_iter: I) -> Self {
37 Self::new(into_iter, fmt_comma_separated)
38 }
39 pub fn verbar_separated(into_iter: I) -> Self {
41 Self::new(into_iter, fmt_verbar_separated)
42 }
43 pub fn pretty_comma_separated(into_iter: I) -> Self {
46 Self::new(into_iter, fmt_pretty_comma_separated)
47 }
48 pub fn one_line_separated(into_iter: I) -> Self {
50 Self::new(into_iter, fmt_one_line_separated)
51 }
52}
53fn fmt_comma_separated<T: ToSql, I: IntoIterator<Item = T>>(
54 into_iter: I,
55 f: &mut String,
56 fmt: SqlFormat,
57) {
58 for (i, v) in into_iter.into_iter().enumerate() {
59 if i > 0 {
60 f.push_str(", ");
61 }
62 v.fmt_sql(f, fmt);
63 }
64}
65fn fmt_verbar_separated<T: ToSql, I: IntoIterator<Item = T>>(
66 into_iter: I,
67 f: &mut String,
68 fmt: SqlFormat,
69) {
70 for (i, v) in into_iter.into_iter().enumerate() {
71 if i > 0 {
72 f.push_str(" | ");
73 }
74 v.fmt_sql(f, fmt);
75 }
76}
77fn fmt_pretty_comma_separated<T: ToSql, I: IntoIterator<Item = T>>(
78 into_iter: I,
79 f: &mut String,
80 fmt: SqlFormat,
81) {
82 for (i, v) in into_iter.into_iter().enumerate() {
83 if i > 0 {
84 if fmt.is_pretty() {
85 f.push_str(",\n");
86 } else {
87 f.push_str(", ");
88 }
89 }
90 v.fmt_sql(f, fmt);
91 }
92}
93fn fmt_one_line_separated<T: ToSql, I: IntoIterator<Item = T>>(
94 into_iter: I,
95 f: &mut String,
96 fmt: SqlFormat,
97) {
98 for (i, v) in into_iter.into_iter().enumerate() {
99 if i > 0 {
100 f.push('\n');
101 }
102 v.fmt_sql(f, fmt);
103 }
104}
105pub fn fmt_separated_by<T: ToSql, I: IntoIterator<Item = T>>(
108 separator: impl Display,
109) -> impl Fn(I, &mut String, SqlFormat) {
110 move |into_iter: I, f: &mut String, fmt: SqlFormat| {
111 let separator = separator.to_string();
112 for (i, v) in into_iter.into_iter().enumerate() {
113 if i > 0 {
114 f.push_str(&separator);
115 }
116 v.fmt_sql(f, fmt);
117 }
118 }
119}
120pub struct CoverStmts<'a>(pub &'a sql::Expr);
121impl ToSql for CoverStmts<'_> {
122 fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
123 match self.0 {
124 sql::Expr::Literal(_)
125 | sql::Expr::Param(_)
126 | sql::Expr::Idiom(_)
127 | sql::Expr::Table(_)
128 | sql::Expr::Mock(_)
129 | sql::Expr::Block(_)
130 | sql::Expr::Constant(_)
131 | sql::Expr::Prefix { .. }
132 | sql::Expr::Postfix { .. }
133 | sql::Expr::Binary { .. }
134 | sql::Expr::FunctionCall(_)
135 | sql::Expr::Closure(_)
136 | sql::Expr::Break
137 | sql::Expr::Continue
138 | sql::Expr::Throw(_) => self.0.fmt_sql(f, fmt),
139 sql::Expr::Return(x) => {
140 if x.fetch.is_some() {
141 f.push('(');
142 self.0.fmt_sql(f, fmt);
143 f.push(')')
144 } else {
145 self.0.fmt_sql(f, fmt);
146 }
147 }
148 sql::Expr::IfElse(_)
149 | sql::Expr::Select(_)
150 | sql::Expr::Create(_)
151 | sql::Expr::Update(_)
152 | sql::Expr::Upsert(_)
153 | sql::Expr::Delete(_)
154 | sql::Expr::Relate(_)
155 | sql::Expr::Insert(_)
156 | sql::Expr::Define(_)
157 | sql::Expr::Remove(_)
158 | sql::Expr::Rebuild(_)
159 | sql::Expr::Alter(_)
160 | sql::Expr::Info(_)
161 | sql::Expr::Foreach(_)
162 | sql::Expr::Let(_)
163 | sql::Expr::Sleep(_)
164 | sql::Expr::Explain { .. } => {
165 f.push('(');
166 self.0.fmt_sql(f, fmt);
167 f.push(')')
168 }
169 }
170 }
171}
172pub struct Float(pub f64);
173impl ToSql for Float {
174 fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
175 match fmt_non_finite_f64(self.0) {
176 Some(special) => f.push_str(special),
177 None => {
178 self.0.fmt_sql(f, fmt);
179 f.push('f');
180 }
181 }
182 }
183}