Skip to content

Commit 1d74a26

Browse files
author
Roman Borschel
committed
Avoid dialect-specific AST nodes.
1 parent 54d2325 commit 1d74a26

6 files changed

Lines changed: 254 additions & 226 deletions

File tree

src/ast/mod.rs

Lines changed: 108 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -2122,8 +2122,8 @@ pub struct CaseStatement {
21222122
/// The `CASE` token that starts the statement.
21232123
pub case_token: AttachedToken,
21242124
pub match_expr: Option<Expr>,
2125-
pub when_blocks: Vec<ConditionalStatements>,
2126-
pub else_block: Option<ConditionalStatements>,
2125+
pub when_blocks: Vec<ConditionalStatementBlock>,
2126+
pub else_block: Option<ConditionalStatementBlock>,
21272127
/// The last token of the statement (`END` or `CASE`).
21282128
pub end_case_token: AttachedToken,
21292129
}
@@ -2165,127 +2165,60 @@ impl fmt::Display for CaseStatement {
21652165
}
21662166

21672167
/// An `IF` statement.
2168+
///
2169+
/// Example (BigQuery or Snowflake):
2170+
/// ```sql
2171+
/// IF TRUE THEN
2172+
/// SELECT 1;
2173+
/// SELECT 2;
2174+
/// ELSEIF TRUE THEN
2175+
/// SELECT 3;
2176+
/// ELSE
2177+
/// SELECT 4;
2178+
/// END IF
2179+
/// ```
2180+
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2181+
/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2182+
///
2183+
/// Example (MSSQL):
2184+
/// ```sql
2185+
/// IF 1=1 SELECT 1 ELSE SELECT 2
2186+
/// ```
2187+
/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
21682188
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
21692189
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21702190
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2171-
pub enum IfStatement {
2172-
/// An `IF ... THEN [ELSE[IF] ...] END IF` statement.
2173-
///
2174-
/// Example:
2175-
/// ```sql
2176-
/// IF TRUE THEN
2177-
/// SELECT 1;
2178-
/// SELECT 2;
2179-
/// ELSEIF TRUE THEN
2180-
/// SELECT 3;
2181-
/// ELSE
2182-
/// SELECT 4;
2183-
/// END IF
2184-
/// ```
2185-
///
2186-
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2187-
/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2188-
IfThenElseEnd {
2189-
/// The `IF` token that starts the statement.
2190-
if_token: AttachedToken,
2191-
if_block: ConditionalStatements,
2192-
elseif_blocks: Vec<ConditionalStatements>,
2193-
else_block: Option<ConditionalStatements>,
2194-
/// The `IF` token that ends the statement.
2195-
end_if_token: AttachedToken,
2196-
},
2197-
/// An MSSQL `IF ... ELSE ...` statement.
2198-
///
2199-
/// Example:
2200-
/// ```sql
2201-
/// IF 1=1 SELECT 1 ELSE SELECT 2
2202-
/// ```
2203-
///
2204-
/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
2205-
MsSqlIfElse {
2206-
if_token: AttachedToken,
2207-
condition: Expr,
2208-
if_statements: MsSqlIfStatements,
2209-
else_statements: Option<MsSqlIfStatements>,
2210-
},
2191+
pub struct IfStatement {
2192+
pub if_block: ConditionalStatementBlock,
2193+
pub elseif_blocks: Vec<ConditionalStatementBlock>,
2194+
pub else_block: Option<ConditionalStatementBlock>,
2195+
pub end_token: Option<AttachedToken>,
22112196
}
22122197

22132198
impl fmt::Display for IfStatement {
22142199
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2215-
match self {
2216-
IfStatement::IfThenElseEnd {
2217-
if_token: _,
2218-
if_block,
2219-
elseif_blocks,
2220-
else_block,
2221-
end_if_token: _,
2222-
} => {
2223-
write!(f, "{if_block}")?;
2224-
2225-
if !elseif_blocks.is_empty() {
2226-
write!(f, " {}", display_separated(elseif_blocks, " "))?;
2227-
}
2228-
2229-
if let Some(else_block) = else_block {
2230-
write!(f, " {else_block}")?;
2231-
}
2232-
2233-
write!(f, " END IF")?;
2234-
2235-
Ok(())
2236-
}
2237-
IfStatement::MsSqlIfElse {
2238-
if_token: _,
2239-
condition,
2240-
if_statements,
2241-
else_statements,
2242-
} => {
2243-
write!(f, "IF {condition} {if_statements}")?;
2200+
let IfStatement {
2201+
if_block,
2202+
elseif_blocks,
2203+
else_block,
2204+
end_token,
2205+
} = self;
22442206

2245-
if let Some(els) = else_statements {
2246-
write!(f, " ELSE {els}")?;
2247-
}
2207+
write!(f, "{if_block}")?;
22482208

2249-
Ok(())
2250-
}
2209+
for elseif_block in elseif_blocks {
2210+
write!(f, " {elseif_block}")?;
22512211
}
2252-
}
2253-
}
22542212

2255-
/// (MSSQL) Either a single [Statement] or a block of statements
2256-
/// enclosed in `BEGIN` and `END`.
2257-
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2258-
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2259-
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2260-
pub enum MsSqlIfStatements {
2261-
/// A single statement.
2262-
Single(Box<Statement>),
2263-
/// ```sql
2264-
/// A logical block of statements.
2265-
///
2266-
/// BEGIN
2267-
/// <statement>;
2268-
/// <statement>;
2269-
/// ...
2270-
/// END
2271-
/// ```
2272-
Block {
2273-
begin_token: AttachedToken,
2274-
statements: Vec<Statement>,
2275-
end_token: AttachedToken,
2276-
},
2277-
}
2213+
if let Some(else_block) = else_block {
2214+
write!(f, " {else_block}")?;
2215+
}
22782216

2279-
impl fmt::Display for MsSqlIfStatements {
2280-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2281-
match self {
2282-
MsSqlIfStatements::Single(stmt) => stmt.fmt(f),
2283-
MsSqlIfStatements::Block { statements, .. } => {
2284-
write!(f, "BEGIN ")?;
2285-
format_statement_list(f, statements)?;
2286-
write!(f, " END")
2287-
}
2217+
if let Some(AttachedToken(end_token)) = end_token {
2218+
write!(f, " END {end_token}")?;
22882219
}
2220+
2221+
Ok(())
22892222
}
22902223
}
22912224

@@ -2308,40 +2241,88 @@ impl fmt::Display for MsSqlIfStatements {
23082241
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
23092242
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
23102243
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2311-
pub struct ConditionalStatements {
2312-
/// The start token of the conditional (`WHEN`, `IF`, `ELSEIF` or `ELSE`).
2244+
pub struct ConditionalStatementBlock {
23132245
pub start_token: AttachedToken,
2314-
/// The condition expression. `None` for `ELSE` statements.
23152246
pub condition: Option<Expr>,
2316-
/// Statement list of the `THEN` clause.
2317-
pub statements: Vec<Statement>,
2247+
pub then_token: Option<AttachedToken>,
2248+
pub conditional_statements: ConditionalStatements,
23182249
}
23192250

2320-
impl fmt::Display for ConditionalStatements {
2251+
impl ConditionalStatementBlock {
2252+
pub fn statements(&self) -> &Vec<Statement> {
2253+
self.conditional_statements.statements()
2254+
}
2255+
}
2256+
2257+
impl fmt::Display for ConditionalStatementBlock {
23212258
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2322-
let ConditionalStatements {
2323-
start_token: AttachedToken(start),
2259+
let ConditionalStatementBlock {
2260+
start_token: AttachedToken(start_token),
23242261
condition,
2325-
statements,
2262+
then_token,
2263+
conditional_statements,
23262264
} = self;
23272265

2328-
let keyword = &start.token;
2266+
write!(f, "{start_token}")?;
23292267

2330-
if let Some(expr) = condition {
2331-
write!(f, "{keyword} {expr} THEN")?;
2332-
} else {
2333-
write!(f, "{keyword}")?;
2268+
if let Some(condition) = condition {
2269+
write!(f, " {condition}")?;
2270+
}
2271+
2272+
if then_token.is_some() {
2273+
write!(f, " THEN")?;
23342274
}
23352275

2336-
if !statements.is_empty() {
2337-
write!(f, " ")?;
2338-
format_statement_list(f, statements)?;
2276+
if conditional_statements.statements().len() > 0 {
2277+
write!(f, " {conditional_statements}")?;
23392278
}
23402279

23412280
Ok(())
23422281
}
23432282
}
23442283

2284+
/// A list of statements in a [ConditionalStatementBlock].
2285+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2286+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2287+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2288+
pub enum ConditionalStatements {
2289+
/// SELECT 1; SELECT 2; SELECT 3; ...
2290+
Sequence { statements: Vec<Statement> },
2291+
/// BEGIN SELECT 1; SELECT 2; SELECT 3; ... END
2292+
BeginEnd {
2293+
begin_token: AttachedToken,
2294+
statements: Vec<Statement>,
2295+
end_token: AttachedToken,
2296+
},
2297+
}
2298+
2299+
impl ConditionalStatements {
2300+
pub fn statements(&self) -> &Vec<Statement> {
2301+
match self {
2302+
ConditionalStatements::Sequence { statements } => statements,
2303+
ConditionalStatements::BeginEnd { statements, .. } => statements,
2304+
}
2305+
}
2306+
}
2307+
2308+
impl fmt::Display for ConditionalStatements {
2309+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2310+
match self {
2311+
ConditionalStatements::Sequence { statements } => {
2312+
if statements.len() > 0 {
2313+
format_statement_list(f, statements)?;
2314+
}
2315+
Ok(())
2316+
}
2317+
ConditionalStatements::BeginEnd { statements, .. } => {
2318+
write!(f, "BEGIN ")?;
2319+
format_statement_list(f, statements)?;
2320+
write!(f, " END")
2321+
}
2322+
}
2323+
}
2324+
}
2325+
23452326
/// A `RAISE` statement.
23462327
///
23472328
/// Examples:

0 commit comments

Comments
 (0)