@@ -151,6 +151,15 @@ where
151
151
DisplaySeparated { slice, sep : ", " }
152
152
}
153
153
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
+
154
163
/// An identifier, decomposed into its value or character data and the quote style.
155
164
#[ derive( Debug , Clone , PartialOrd , Ord ) ]
156
165
#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
@@ -2098,6 +2107,173 @@ pub enum Password {
2098
2107
NullPassword ,
2099
2108
}
2100
2109
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
+
2101
2277
/// Represents an expression assignment within a variable `DECLARE` statement.
2102
2278
///
2103
2279
/// Examples:
@@ -2665,6 +2841,10 @@ pub enum Statement {
2665
2841
file_format : Option < FileFormat > ,
2666
2842
source : Box < Query > ,
2667
2843
} ,
2844
+ /// A `CASE` statement.
2845
+ Case ( CaseStatement ) ,
2846
+ /// An `IF` statement.
2847
+ If ( IfStatement ) ,
2668
2848
/// ```sql
2669
2849
/// CALL <function>
2670
2850
/// ```
@@ -3958,6 +4138,12 @@ impl fmt::Display for Statement {
3958
4138
}
3959
4139
Ok ( ( ) )
3960
4140
}
4141
+ Statement :: Case ( stmt) => {
4142
+ write ! ( f, "{stmt}" )
4143
+ }
4144
+ Statement :: If ( stmt) => {
4145
+ write ! ( f, "{stmt}" )
4146
+ }
3961
4147
Statement :: AttachDatabase {
3962
4148
schema_name,
3963
4149
database_file_name,
@@ -4960,18 +5146,14 @@ impl fmt::Display for Statement {
4960
5146
write ! ( f, " {}" , display_comma_separated( modes) ) ?;
4961
5147
}
4962
5148
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) ?;
4967
5151
}
4968
5152
if let Some ( exception_statements) = exception_statements {
4969
5153
write ! ( f, " EXCEPTION WHEN ERROR THEN" ) ?;
4970
5154
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) ?;
4975
5157
}
4976
5158
}
4977
5159
if * has_end_keyword {
0 commit comments