Skip to content

Commit 6120bb5

Browse files
authored
implement pretty-printing with {:#} (#1847)
1 parent 052ad4a commit 6120bb5

File tree

5 files changed

+591
-160
lines changed

5 files changed

+591
-160
lines changed

src/ast/mod.rs

Lines changed: 79 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,14 @@ use serde::{Deserialize, Serialize};
4040
#[cfg(feature = "visitor")]
4141
use sqlparser_derive::{Visit, VisitMut};
4242

43-
use crate::keywords::Keyword;
44-
use crate::tokenizer::{Span, Token};
43+
use crate::{
44+
display_utils::SpaceOrNewline,
45+
tokenizer::{Span, Token},
46+
};
47+
use crate::{
48+
display_utils::{Indent, NewLine},
49+
keywords::Keyword,
50+
};
4551

4652
pub use self::data_type::{
4753
ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
@@ -134,9 +140,9 @@ where
134140
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135141
let mut delim = "";
136142
for t in self.slice {
137-
write!(f, "{delim}")?;
143+
f.write_str(delim)?;
138144
delim = self.sep;
139-
write!(f, "{t}")?;
145+
t.fmt(f)?;
140146
}
141147
Ok(())
142148
}
@@ -628,7 +634,12 @@ pub struct CaseWhen {
628634

629635
impl fmt::Display for CaseWhen {
630636
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
631-
write!(f, "WHEN {} THEN {}", self.condition, self.result)
637+
f.write_str("WHEN ")?;
638+
self.condition.fmt(f)?;
639+
f.write_str(" THEN")?;
640+
SpaceOrNewline.fmt(f)?;
641+
Indent(&self.result).fmt(f)?;
642+
Ok(())
632643
}
633644
}
634645

@@ -1662,23 +1673,29 @@ impl fmt::Display for Expr {
16621673
write!(f, "{data_type}")?;
16631674
write!(f, " {value}")
16641675
}
1665-
Expr::Function(fun) => write!(f, "{fun}"),
1676+
Expr::Function(fun) => fun.fmt(f),
16661677
Expr::Case {
16671678
operand,
16681679
conditions,
16691680
else_result,
16701681
} => {
1671-
write!(f, "CASE")?;
1682+
f.write_str("CASE")?;
16721683
if let Some(operand) = operand {
1673-
write!(f, " {operand}")?;
1684+
f.write_str(" ")?;
1685+
operand.fmt(f)?;
16741686
}
16751687
for when in conditions {
1676-
write!(f, " {when}")?;
1688+
SpaceOrNewline.fmt(f)?;
1689+
Indent(when).fmt(f)?;
16771690
}
16781691
if let Some(else_result) = else_result {
1679-
write!(f, " ELSE {else_result}")?;
1692+
SpaceOrNewline.fmt(f)?;
1693+
Indent("ELSE").fmt(f)?;
1694+
SpaceOrNewline.fmt(f)?;
1695+
Indent(Indent(else_result)).fmt(f)?;
16801696
}
1681-
write!(f, " END")
1697+
SpaceOrNewline.fmt(f)?;
1698+
f.write_str("END")
16821699
}
16831700
Expr::Exists { subquery, negated } => write!(
16841701
f,
@@ -1867,8 +1884,14 @@ pub enum WindowType {
18671884
impl Display for WindowType {
18681885
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18691886
match self {
1870-
WindowType::WindowSpec(spec) => write!(f, "({})", spec),
1871-
WindowType::NamedWindow(name) => write!(f, "{}", name),
1887+
WindowType::WindowSpec(spec) => {
1888+
f.write_str("(")?;
1889+
NewLine.fmt(f)?;
1890+
Indent(spec).fmt(f)?;
1891+
NewLine.fmt(f)?;
1892+
f.write_str(")")
1893+
}
1894+
WindowType::NamedWindow(name) => name.fmt(f),
18721895
}
18731896
}
18741897
}
@@ -1896,27 +1919,36 @@ pub struct WindowSpec {
18961919

18971920
impl fmt::Display for WindowSpec {
18981921
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1899-
let mut delim = "";
1922+
let mut is_first = true;
19001923
if let Some(window_name) = &self.window_name {
1901-
delim = " ";
1924+
if !is_first {
1925+
SpaceOrNewline.fmt(f)?;
1926+
}
1927+
is_first = false;
19021928
write!(f, "{window_name}")?;
19031929
}
19041930
if !self.partition_by.is_empty() {
1905-
f.write_str(delim)?;
1906-
delim = " ";
1931+
if !is_first {
1932+
SpaceOrNewline.fmt(f)?;
1933+
}
1934+
is_first = false;
19071935
write!(
19081936
f,
19091937
"PARTITION BY {}",
19101938
display_comma_separated(&self.partition_by)
19111939
)?;
19121940
}
19131941
if !self.order_by.is_empty() {
1914-
f.write_str(delim)?;
1915-
delim = " ";
1942+
if !is_first {
1943+
SpaceOrNewline.fmt(f)?;
1944+
}
1945+
is_first = false;
19161946
write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
19171947
}
19181948
if let Some(window_frame) = &self.window_frame {
1919-
f.write_str(delim)?;
1949+
if !is_first {
1950+
SpaceOrNewline.fmt(f)?;
1951+
}
19201952
if let Some(end_bound) = &window_frame.end_bound {
19211953
write!(
19221954
f,
@@ -4204,6 +4236,28 @@ impl fmt::Display for RaisErrorOption {
42044236
}
42054237

42064238
impl fmt::Display for Statement {
4239+
/// Formats a SQL statement with support for pretty printing.
4240+
///
4241+
/// When using the alternate flag (`{:#}`), the statement will be formatted with proper
4242+
/// indentation and line breaks. For example:
4243+
///
4244+
/// ```
4245+
/// # use sqlparser::dialect::GenericDialect;
4246+
/// # use sqlparser::parser::Parser;
4247+
/// let sql = "SELECT a, b FROM table_1";
4248+
/// let ast = Parser::parse_sql(&GenericDialect, sql).unwrap();
4249+
///
4250+
/// // Regular formatting
4251+
/// assert_eq!(format!("{}", ast[0]), "SELECT a, b FROM table_1");
4252+
///
4253+
/// // Pretty printing
4254+
/// assert_eq!(format!("{:#}", ast[0]),
4255+
/// r#"SELECT
4256+
/// a,
4257+
/// b
4258+
/// FROM
4259+
/// table_1"#);
4260+
/// ```
42074261
// Clippy thinks this function is too complicated, but it is painful to
42084262
// split up without extracting structs for each `Statement` variant.
42094263
#[allow(clippy::cognitive_complexity)]
@@ -4219,7 +4273,8 @@ impl fmt::Display for Statement {
42194273
} => {
42204274
write!(f, "FLUSH")?;
42214275
if let Some(location) = location {
4222-
write!(f, " {location}")?;
4276+
f.write_str(" ")?;
4277+
location.fmt(f)?;
42234278
}
42244279
write!(f, " {object_type}")?;
42254280

@@ -4301,7 +4356,7 @@ impl fmt::Display for Statement {
43014356

43024357
write!(f, "{statement}")
43034358
}
4304-
Statement::Query(s) => write!(f, "{s}"),
4359+
Statement::Query(s) => s.fmt(f),
43054360
Statement::Declare { stmts } => {
43064361
write!(f, "DECLARE ")?;
43074362
write!(f, "{}", display_separated(stmts, "; "))
@@ -7056,7 +7111,8 @@ impl fmt::Display for Function {
70567111
}
70577112

70587113
if let Some(o) = &self.over {
7059-
write!(f, " OVER {o}")?;
7114+
f.write_str(" OVER ")?;
7115+
o.fmt(f)?;
70607116
}
70617117

70627118
if self.uses_odbc_syntax {

0 commit comments

Comments
 (0)