@@ -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 ,
@@ -2118,20 +2119,23 @@ pub enum Password {
21182119#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
21192120#[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
21202121pub struct CaseStatement {
2122+ /// The `CASE` token that starts the statement.
2123+ pub case_token : AttachedToken ,
21212124 pub match_expr : Option < Expr > ,
2122- pub when_blocks : Vec < ConditionalStatements > ,
2123- pub else_block : Option < Vec < Statement > > ,
2124- /// TRUE if the statement ends with `END CASE` (vs `END `).
2125- pub has_end_case : bool ,
2125+ pub when_blocks : Vec < ConditionalStatementBlock > ,
2126+ pub else_block : Option < ConditionalStatementBlock > ,
2127+ /// The last token of the statement ( `END` or `CASE `).
2128+ pub end_case_token : AttachedToken ,
21262129}
21272130
21282131impl fmt:: Display for CaseStatement {
21292132 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
21302133 let CaseStatement {
2134+ case_token : _,
21312135 match_expr,
21322136 when_blocks,
21332137 else_block,
2134- has_end_case ,
2138+ end_case_token : AttachedToken ( end ) ,
21352139 } = self ;
21362140
21372141 write ! ( f, "CASE" ) ?;
@@ -2145,13 +2149,15 @@ impl fmt::Display for CaseStatement {
21452149 }
21462150
21472151 if let Some ( else_block) = else_block {
2148- write ! ( f, " ELSE " ) ?;
2149- format_statement_list ( f, else_block) ?;
2152+ write ! ( f, " {else_block}" ) ?;
21502153 }
21512154
21522155 write ! ( f, " END" ) ?;
2153- if * has_end_case {
2154- write ! ( f, " CASE" ) ?;
2156+
2157+ if let Token :: Word ( w) = & end. token {
2158+ if w. keyword == Keyword :: CASE {
2159+ write ! ( f, " CASE" ) ?;
2160+ }
21552161 }
21562162
21572163 Ok ( ( ) )
@@ -2160,7 +2166,7 @@ impl fmt::Display for CaseStatement {
21602166
21612167/// An `IF` statement.
21622168///
2163- /// Examples :
2169+ /// Example (BigQuery or Snowflake) :
21642170/// ```sql
21652171/// IF TRUE THEN
21662172/// SELECT 1;
@@ -2171,16 +2177,22 @@ impl fmt::Display for CaseStatement {
21712177/// SELECT 4;
21722178/// END IF
21732179/// ```
2174- ///
21752180/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
21762181/// [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)
21772188#[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
21782189#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
21792190#[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
21802191pub struct IfStatement {
2181- pub if_block : ConditionalStatements ,
2182- pub elseif_blocks : Vec < ConditionalStatements > ,
2183- pub else_block : Option < Vec < Statement > > ,
2192+ pub if_block : ConditionalStatementBlock ,
2193+ pub elseif_blocks : Vec < ConditionalStatementBlock > ,
2194+ pub else_block : Option < ConditionalStatementBlock > ,
2195+ pub end_token : Option < AttachedToken > ,
21842196}
21852197
21862198impl fmt:: Display for IfStatement {
@@ -2189,82 +2201,128 @@ impl fmt::Display for IfStatement {
21892201 if_block,
21902202 elseif_blocks,
21912203 else_block,
2204+ end_token,
21922205 } = self ;
21932206
21942207 write ! ( f, "{if_block}" ) ?;
21952208
2196- if ! elseif_blocks. is_empty ( ) {
2197- write ! ( f, " {}" , display_separated ( elseif_blocks , " " ) ) ?;
2209+ for elseif_block in elseif_blocks {
2210+ write ! ( f, " {elseif_block}" ) ?;
21982211 }
21992212
22002213 if let Some ( else_block) = else_block {
2201- write ! ( f, " ELSE " ) ?;
2202- format_statement_list ( f, else_block) ?;
2214+ write ! ( f, " {else_block}" ) ?;
22032215 }
22042216
2205- write ! ( f, " END IF" ) ?;
2217+ if let Some ( AttachedToken ( end_token) ) = end_token {
2218+ write ! ( f, " END {end_token}" ) ?;
2219+ }
22062220
22072221 Ok ( ( ) )
22082222 }
22092223}
22102224
2211- /// Represents a type of [ConditionalStatements]
2212- #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2213- #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2214- #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2215- pub enum ConditionalStatementKind {
2216- /// `WHEN <condition> THEN <statements>`
2217- When ,
2218- /// `IF <condition> THEN <statements>`
2219- If ,
2220- /// `ELSEIF <condition> THEN <statements>`
2221- ElseIf ,
2222- }
2223-
22242225/// A block within a [Statement::Case] or [Statement::If]-like statement
22252226///
2226- /// Examples :
2227+ /// Example 1 :
22272228/// ```sql
22282229/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2230+ /// ```
22292231///
2232+ /// Example 2:
2233+ /// ```sql
22302234/// IF TRUE THEN SELECT 1; SELECT 2;
22312235/// ```
2236+ ///
2237+ /// Example 3:
2238+ /// ```sql
2239+ /// ELSE SELECT 1; SELECT 2;
2240+ /// ```
22322241#[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
22332242#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
22342243#[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2235- pub struct ConditionalStatements {
2236- /// The condition expression.
2237- pub condition : Expr ,
2238- /// Statement list of the `THEN` clause.
2239- pub statements : Vec < Statement > ,
2240- pub kind : ConditionalStatementKind ,
2244+ pub struct ConditionalStatementBlock {
2245+ pub start_token : AttachedToken ,
2246+ pub condition : Option < Expr > ,
2247+ pub then_token : Option < AttachedToken > ,
2248+ pub conditional_statements : ConditionalStatements ,
22412249}
22422250
2243- 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 {
22442258 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2245- let ConditionalStatements {
2246- condition : expr,
2247- statements,
2248- kind,
2259+ let ConditionalStatementBlock {
2260+ start_token : AttachedToken ( start_token) ,
2261+ condition,
2262+ then_token,
2263+ conditional_statements,
22492264 } = self ;
22502265
2251- let kind = match kind {
2252- ConditionalStatementKind :: When => "WHEN" ,
2253- ConditionalStatementKind :: If => "IF" ,
2254- ConditionalStatementKind :: ElseIf => "ELSEIF" ,
2255- } ;
2266+ write ! ( f , "{start_token}" ) ? ;
2267+
2268+ if let Some ( condition ) = condition {
2269+ write ! ( f , " {condition}" ) ? ;
2270+ }
22562271
2257- write ! ( f, "{kind} {expr} THEN" ) ?;
2272+ if then_token. is_some ( ) {
2273+ write ! ( f, " THEN" ) ?;
2274+ }
22582275
2259- if !statements. is_empty ( ) {
2260- write ! ( f, " " ) ?;
2261- format_statement_list ( f, statements) ?;
2276+ if !conditional_statements. statements ( ) . is_empty ( ) {
2277+ write ! ( f, " {conditional_statements}" ) ?;
22622278 }
22632279
22642280 Ok ( ( ) )
22652281 }
22662282}
22672283
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. is_empty ( ) {
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+
22682326/// A `RAISE` statement.
22692327///
22702328/// Examples:
0 commit comments