@@ -151,6 +151,15 @@ where
151151 DisplaySeparated { slice, sep : ", " }
152152}
153153
154+ /// Writes the given statements to the formatter, each ending with
155+ /// a semicolon and space separated.
156+ fn format_statement_list ( f : & mut fmt:: Formatter , statements : & [ Statement ] ) -> fmt:: Result {
157+ write ! ( f, "{}" , display_separated( statements, "; " ) ) ?;
158+ // We manually insert semicolon for the last statement,
159+ // since display_separated doesn't handle that case.
160+ write ! ( f, ";" )
161+ }
162+
154163/// An identifier, decomposed into its value or character data and the quote style.
155164#[ derive( Debug , Clone , PartialOrd , Ord ) ]
156165#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
@@ -2098,6 +2107,173 @@ pub enum Password {
20982107 NullPassword ,
20992108}
21002109
2110+ /// A `CASE` statement.
2111+ ///
2112+ /// Examples:
2113+ /// ```sql
2114+ /// CASE
2115+ /// WHEN EXISTS(SELECT 1)
2116+ /// THEN SELECT 1 FROM T;
2117+ /// WHEN EXISTS(SELECT 2)
2118+ /// THEN SELECT 1 FROM U;
2119+ /// ELSE
2120+ /// SELECT 1 FROM V;
2121+ /// END CASE;
2122+ /// ```
2123+ ///
2124+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2125+ /// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2126+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2127+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2128+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2129+ pub struct CaseStatement {
2130+ pub match_expr : Option < Expr > ,
2131+ pub when_blocks : Vec < ConditionalStatements > ,
2132+ pub else_block : Option < Vec < Statement > > ,
2133+ /// TRUE if the statement ends with `END CASE` (vs `END`).
2134+ pub has_end_case : bool ,
2135+ }
2136+
2137+ impl fmt:: Display for CaseStatement {
2138+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2139+ let CaseStatement {
2140+ match_expr,
2141+ when_blocks,
2142+ else_block,
2143+ has_end_case,
2144+ } = self ;
2145+
2146+ write ! ( f, "CASE" ) ?;
2147+
2148+ if let Some ( expr) = match_expr {
2149+ write ! ( f, " {expr}" ) ?;
2150+ }
2151+
2152+ if !when_blocks. is_empty ( ) {
2153+ write ! ( f, " {}" , display_separated( when_blocks, " " ) ) ?;
2154+ }
2155+
2156+ if let Some ( else_block) = else_block {
2157+ write ! ( f, " ELSE " ) ?;
2158+ format_statement_list ( f, else_block) ?;
2159+ }
2160+
2161+ write ! ( f, " END" ) ?;
2162+ if * has_end_case {
2163+ write ! ( f, " CASE" ) ?;
2164+ }
2165+
2166+ Ok ( ( ) )
2167+ }
2168+ }
2169+
2170+ /// An `IF` statement.
2171+ ///
2172+ /// Examples:
2173+ /// ```sql
2174+ /// IF TRUE THEN
2175+ /// SELECT 1;
2176+ /// SELECT 2;
2177+ /// ELSEIF TRUE THEN
2178+ /// SELECT 3;
2179+ /// ELSE
2180+ /// SELECT 4;
2181+ /// END IF
2182+ /// ```
2183+ ///
2184+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2185+ /// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2186+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2187+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2188+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2189+ pub struct IfStatement {
2190+ pub if_block : ConditionalStatements ,
2191+ pub elseif_blocks : Vec < ConditionalStatements > ,
2192+ pub else_block : Option < Vec < Statement > > ,
2193+ }
2194+
2195+ impl fmt:: Display for IfStatement {
2196+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2197+ let IfStatement {
2198+ if_block,
2199+ elseif_blocks,
2200+ else_block,
2201+ } = self ;
2202+
2203+ write ! ( f, "{if_block}" ) ?;
2204+
2205+ if !elseif_blocks. is_empty ( ) {
2206+ write ! ( f, " {}" , display_separated( elseif_blocks, " " ) ) ?;
2207+ }
2208+
2209+ if let Some ( else_block) = else_block {
2210+ write ! ( f, " ELSE " ) ?;
2211+ format_statement_list ( f, else_block) ?;
2212+ }
2213+
2214+ write ! ( f, " END IF" ) ?;
2215+
2216+ Ok ( ( ) )
2217+ }
2218+ }
2219+
2220+ /// Represents a type of [ConditionalStatements]
2221+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2222+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2223+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2224+ pub enum ConditionalStatementKind {
2225+ /// `WHEN <condition> THEN <statements>`
2226+ When ,
2227+ /// `IF <condition> THEN <statements>`
2228+ If ,
2229+ /// `ELSEIF <condition> THEN <statements>`
2230+ ElseIf ,
2231+ }
2232+
2233+ /// A block within a [Statement::Case] or [Statement::If]-like statement
2234+ ///
2235+ /// Examples:
2236+ /// ```sql
2237+ /// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2238+ ///
2239+ /// IF TRUE THEN SELECT 1; SELECT 2;
2240+ /// ```
2241+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2242+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2243+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2244+ pub struct ConditionalStatements {
2245+ /// The condition expression.
2246+ pub condition : Expr ,
2247+ /// Statement list of the `THEN` clause.
2248+ pub statements : Vec < Statement > ,
2249+ pub kind : ConditionalStatementKind ,
2250+ }
2251+
2252+ impl fmt:: Display for ConditionalStatements {
2253+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2254+ let ConditionalStatements {
2255+ condition : expr,
2256+ statements,
2257+ kind,
2258+ } = self ;
2259+
2260+ let kind = match kind {
2261+ ConditionalStatementKind :: When => "WHEN" ,
2262+ ConditionalStatementKind :: If => "IF" ,
2263+ ConditionalStatementKind :: ElseIf => "ELSEIF" ,
2264+ } ;
2265+
2266+ write ! ( f, "{kind} {expr} THEN" ) ?;
2267+
2268+ if !statements. is_empty ( ) {
2269+ write ! ( f, " " ) ?;
2270+ format_statement_list ( f, statements) ?;
2271+ }
2272+
2273+ Ok ( ( ) )
2274+ }
2275+ }
2276+
21012277/// Represents an expression assignment within a variable `DECLARE` statement.
21022278///
21032279/// Examples:
@@ -2665,6 +2841,10 @@ pub enum Statement {
26652841 file_format : Option < FileFormat > ,
26662842 source : Box < Query > ,
26672843 } ,
2844+ /// A `CASE` statement.
2845+ Case ( CaseStatement ) ,
2846+ /// An `IF` statement.
2847+ If ( IfStatement ) ,
26682848 /// ```sql
26692849 /// CALL <function>
26702850 /// ```
@@ -3958,6 +4138,12 @@ impl fmt::Display for Statement {
39584138 }
39594139 Ok ( ( ) )
39604140 }
4141+ Statement :: Case ( stmt) => {
4142+ write ! ( f, "{stmt}" )
4143+ }
4144+ Statement :: If ( stmt) => {
4145+ write ! ( f, "{stmt}" )
4146+ }
39614147 Statement :: AttachDatabase {
39624148 schema_name,
39634149 database_file_name,
@@ -4960,18 +5146,14 @@ impl fmt::Display for Statement {
49605146 write ! ( f, " {}" , display_comma_separated( modes) ) ?;
49615147 }
49625148 if !statements. is_empty ( ) {
4963- write ! ( f, " {}" , display_separated( statements, "; " ) ) ?;
4964- // We manually insert semicolon for the last statement,
4965- // since display_separated doesn't handle that case.
4966- write ! ( f, ";" ) ?;
5149+ write ! ( f, " " ) ?;
5150+ format_statement_list ( f, statements) ?;
49675151 }
49685152 if let Some ( exception_statements) = exception_statements {
49695153 write ! ( f, " EXCEPTION WHEN ERROR THEN" ) ?;
49705154 if !exception_statements. is_empty ( ) {
4971- write ! ( f, " {}" , display_separated( exception_statements, "; " ) ) ?;
4972- // We manually insert semicolon for the last statement,
4973- // since display_separated doesn't handle that case.
4974- write ! ( f, ";" ) ?;
5155+ write ! ( f, " " ) ?;
5156+ format_statement_list ( f, exception_statements) ?;
49755157 }
49765158 }
49775159 if * has_end_keyword {
0 commit comments