@@ -37,7 +37,8 @@ use serde::{Deserialize, Serialize};
3737#[ cfg( feature = "visitor" ) ]
3838use sqlparser_derive:: { Visit , VisitMut } ;
3939
40- use crate :: tokenizer:: Span ;
40+ use crate :: keywords:: Keyword ;
41+ use crate :: tokenizer:: { Span , Token } ;
4142
4243pub use self :: data_type:: {
4344 ArrayElemTypeDef , BinaryLength , CharLengthUnits , CharacterLength , DataType , EnumMember ,
@@ -2136,20 +2137,23 @@ pub enum Password {
21362137#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
21372138#[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
21382139pub struct CaseStatement {
2140+ /// The `CASE` token that starts the statement.
2141+ pub case_token : AttachedToken ,
21392142 pub match_expr : Option < Expr > ,
2140- pub when_blocks : Vec < ConditionalStatements > ,
2141- pub else_block : Option < Vec < Statement > > ,
2142- /// TRUE if the statement ends with `END CASE` (vs `END `).
2143- pub has_end_case : bool ,
2143+ pub when_blocks : Vec < ConditionalStatementBlock > ,
2144+ pub else_block : Option < ConditionalStatementBlock > ,
2145+ /// The last token of the statement ( `END` or `CASE `).
2146+ pub end_case_token : AttachedToken ,
21442147}
21452148
21462149impl fmt:: Display for CaseStatement {
21472150 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
21482151 let CaseStatement {
2152+ case_token : _,
21492153 match_expr,
21502154 when_blocks,
21512155 else_block,
2152- has_end_case ,
2156+ end_case_token : AttachedToken ( end ) ,
21532157 } = self ;
21542158
21552159 write ! ( f, "CASE" ) ?;
@@ -2163,13 +2167,15 @@ impl fmt::Display for CaseStatement {
21632167 }
21642168
21652169 if let Some ( else_block) = else_block {
2166- write ! ( f, " ELSE " ) ?;
2167- format_statement_list ( f, else_block) ?;
2170+ write ! ( f, " {else_block}" ) ?;
21682171 }
21692172
21702173 write ! ( f, " END" ) ?;
2171- if * has_end_case {
2172- write ! ( f, " CASE" ) ?;
2174+
2175+ if let Token :: Word ( w) = & end. token {
2176+ if w. keyword == Keyword :: CASE {
2177+ write ! ( f, " CASE" ) ?;
2178+ }
21732179 }
21742180
21752181 Ok ( ( ) )
@@ -2178,7 +2184,7 @@ impl fmt::Display for CaseStatement {
21782184
21792185/// An `IF` statement.
21802186///
2181- /// Examples :
2187+ /// Example (BigQuery or Snowflake) :
21822188/// ```sql
21832189/// IF TRUE THEN
21842190/// SELECT 1;
@@ -2189,16 +2195,22 @@ impl fmt::Display for CaseStatement {
21892195/// SELECT 4;
21902196/// END IF
21912197/// ```
2192- ///
21932198/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
21942199/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2200+ ///
2201+ /// Example (MSSQL):
2202+ /// ```sql
2203+ /// IF 1=1 SELECT 1 ELSE SELECT 2
2204+ /// ```
2205+ /// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql?view=sql-server-ver16)
21952206#[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
21962207#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
21972208#[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
21982209pub struct IfStatement {
2199- pub if_block : ConditionalStatements ,
2200- pub elseif_blocks : Vec < ConditionalStatements > ,
2201- pub else_block : Option < Vec < Statement > > ,
2210+ pub if_block : ConditionalStatementBlock ,
2211+ pub elseif_blocks : Vec < ConditionalStatementBlock > ,
2212+ pub else_block : Option < ConditionalStatementBlock > ,
2213+ pub end_token : Option < AttachedToken > ,
22022214}
22032215
22042216impl fmt:: Display for IfStatement {
@@ -2207,82 +2219,128 @@ impl fmt::Display for IfStatement {
22072219 if_block,
22082220 elseif_blocks,
22092221 else_block,
2222+ end_token,
22102223 } = self ;
22112224
22122225 write ! ( f, "{if_block}" ) ?;
22132226
2214- if ! elseif_blocks. is_empty ( ) {
2215- write ! ( f, " {}" , display_separated ( elseif_blocks , " " ) ) ?;
2227+ for elseif_block in elseif_blocks {
2228+ write ! ( f, " {elseif_block}" ) ?;
22162229 }
22172230
22182231 if let Some ( else_block) = else_block {
2219- write ! ( f, " ELSE " ) ?;
2220- format_statement_list ( f, else_block) ?;
2232+ write ! ( f, " {else_block}" ) ?;
22212233 }
22222234
2223- write ! ( f, " END IF" ) ?;
2235+ if let Some ( AttachedToken ( end_token) ) = end_token {
2236+ write ! ( f, " END {end_token}" ) ?;
2237+ }
22242238
22252239 Ok ( ( ) )
22262240 }
22272241}
22282242
2229- /// Represents a type of [ConditionalStatements]
2230- #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2231- #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2232- #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2233- pub enum ConditionalStatementKind {
2234- /// `WHEN <condition> THEN <statements>`
2235- When ,
2236- /// `IF <condition> THEN <statements>`
2237- If ,
2238- /// `ELSEIF <condition> THEN <statements>`
2239- ElseIf ,
2240- }
2241-
22422243/// A block within a [Statement::Case] or [Statement::If]-like statement
22432244///
2244- /// Examples :
2245+ /// Example 1 :
22452246/// ```sql
22462247/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2248+ /// ```
22472249///
2250+ /// Example 2:
2251+ /// ```sql
22482252/// IF TRUE THEN SELECT 1; SELECT 2;
22492253/// ```
2254+ ///
2255+ /// Example 3:
2256+ /// ```sql
2257+ /// ELSE SELECT 1; SELECT 2;
2258+ /// ```
22502259#[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
22512260#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
22522261#[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2253- pub struct ConditionalStatements {
2254- /// The condition expression.
2255- pub condition : Expr ,
2256- /// Statement list of the `THEN` clause.
2257- pub statements : Vec < Statement > ,
2258- pub kind : ConditionalStatementKind ,
2262+ pub struct ConditionalStatementBlock {
2263+ pub start_token : AttachedToken ,
2264+ pub condition : Option < Expr > ,
2265+ pub then_token : Option < AttachedToken > ,
2266+ pub conditional_statements : ConditionalStatements ,
22592267}
22602268
2261- impl fmt:: Display for ConditionalStatements {
2269+ impl ConditionalStatementBlock {
2270+ pub fn statements ( & self ) -> & Vec < Statement > {
2271+ self . conditional_statements . statements ( )
2272+ }
2273+ }
2274+
2275+ impl fmt:: Display for ConditionalStatementBlock {
22622276 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2263- let ConditionalStatements {
2264- condition : expr,
2265- statements,
2266- kind,
2277+ let ConditionalStatementBlock {
2278+ start_token : AttachedToken ( start_token) ,
2279+ condition,
2280+ then_token,
2281+ conditional_statements,
22672282 } = self ;
22682283
2269- let kind = match kind {
2270- ConditionalStatementKind :: When => "WHEN" ,
2271- ConditionalStatementKind :: If => "IF" ,
2272- ConditionalStatementKind :: ElseIf => "ELSEIF" ,
2273- } ;
2284+ write ! ( f , "{start_token}" ) ? ;
2285+
2286+ if let Some ( condition ) = condition {
2287+ write ! ( f , " {condition}" ) ? ;
2288+ }
22742289
2275- write ! ( f, "{kind} {expr} THEN" ) ?;
2290+ if then_token. is_some ( ) {
2291+ write ! ( f, " THEN" ) ?;
2292+ }
22762293
2277- if !statements. is_empty ( ) {
2278- write ! ( f, " " ) ?;
2279- format_statement_list ( f, statements) ?;
2294+ if !conditional_statements. statements ( ) . is_empty ( ) {
2295+ write ! ( f, " {conditional_statements}" ) ?;
22802296 }
22812297
22822298 Ok ( ( ) )
22832299 }
22842300}
22852301
2302+ /// A list of statements in a [ConditionalStatementBlock].
2303+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2304+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2305+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2306+ pub enum ConditionalStatements {
2307+ /// SELECT 1; SELECT 2; SELECT 3; ...
2308+ Sequence { statements : Vec < Statement > } ,
2309+ /// BEGIN SELECT 1; SELECT 2; SELECT 3; ... END
2310+ BeginEnd {
2311+ begin_token : AttachedToken ,
2312+ statements : Vec < Statement > ,
2313+ end_token : AttachedToken ,
2314+ } ,
2315+ }
2316+
2317+ impl ConditionalStatements {
2318+ pub fn statements ( & self ) -> & Vec < Statement > {
2319+ match self {
2320+ ConditionalStatements :: Sequence { statements } => statements,
2321+ ConditionalStatements :: BeginEnd { statements, .. } => statements,
2322+ }
2323+ }
2324+ }
2325+
2326+ impl fmt:: Display for ConditionalStatements {
2327+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2328+ match self {
2329+ ConditionalStatements :: Sequence { statements } => {
2330+ if !statements. is_empty ( ) {
2331+ format_statement_list ( f, statements) ?;
2332+ }
2333+ Ok ( ( ) )
2334+ }
2335+ ConditionalStatements :: BeginEnd { statements, .. } => {
2336+ write ! ( f, "BEGIN " ) ?;
2337+ format_statement_list ( f, statements) ?;
2338+ write ! ( f, " END" )
2339+ }
2340+ }
2341+ }
2342+ }
2343+
22862344/// A `RAISE` statement.
22872345///
22882346/// Examples:
0 commit comments