@@ -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 ) ) ]
@@ -2080,6 +2089,173 @@ pub enum Password {
2080
2089
NullPassword ,
2081
2090
}
2082
2091
2092
+ /// A `CASE` statement.
2093
+ ///
2094
+ /// Examples:
2095
+ /// ```sql
2096
+ /// CASE
2097
+ /// WHEN EXISTS(SELECT 1)
2098
+ /// THEN SELECT 1 FROM T;
2099
+ /// WHEN EXISTS(SELECT 2)
2100
+ /// THEN SELECT 1 FROM U;
2101
+ /// ELSE
2102
+ /// SELECT 1 FROM V;
2103
+ /// END CASE;
2104
+ /// ```
2105
+ ///
2106
+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#case_search_expression)
2107
+ /// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/case)
2108
+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2109
+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2110
+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2111
+ pub struct CaseStatement {
2112
+ pub match_expr : Option < Expr > ,
2113
+ pub when_blocks : Vec < ConditionalStatements > ,
2114
+ pub else_block : Option < Vec < Statement > > ,
2115
+ /// TRUE if the statement ends with `END CASE` (vs `END`).
2116
+ pub has_end_case : bool ,
2117
+ }
2118
+
2119
+ impl fmt:: Display for CaseStatement {
2120
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2121
+ let CaseStatement {
2122
+ match_expr,
2123
+ when_blocks,
2124
+ else_block,
2125
+ has_end_case,
2126
+ } = self ;
2127
+
2128
+ write ! ( f, "CASE" ) ?;
2129
+
2130
+ if let Some ( expr) = match_expr {
2131
+ write ! ( f, " {expr}" ) ?;
2132
+ }
2133
+
2134
+ if !when_blocks. is_empty ( ) {
2135
+ write ! ( f, " {}" , display_separated( when_blocks, " " ) ) ?;
2136
+ }
2137
+
2138
+ if let Some ( else_block) = else_block {
2139
+ write ! ( f, " ELSE " ) ?;
2140
+ format_statement_list ( f, else_block) ?;
2141
+ }
2142
+
2143
+ write ! ( f, " END" ) ?;
2144
+ if * has_end_case {
2145
+ write ! ( f, " CASE" ) ?;
2146
+ }
2147
+
2148
+ Ok ( ( ) )
2149
+ }
2150
+ }
2151
+
2152
+ /// An `IF` statement.
2153
+ ///
2154
+ /// Examples:
2155
+ /// ```sql
2156
+ /// IF TRUE THEN
2157
+ /// SELECT 1;
2158
+ /// SELECT 2;
2159
+ /// ELSEIF TRUE THEN
2160
+ /// SELECT 3;
2161
+ /// ELSE
2162
+ /// SELECT 4;
2163
+ /// END IF
2164
+ /// ```
2165
+ ///
2166
+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2167
+ /// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/if)
2168
+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2169
+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2170
+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2171
+ pub struct IfStatement {
2172
+ pub if_block : ConditionalStatements ,
2173
+ pub elseif_blocks : Vec < ConditionalStatements > ,
2174
+ pub else_block : Option < Vec < Statement > > ,
2175
+ }
2176
+
2177
+ impl fmt:: Display for IfStatement {
2178
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2179
+ let IfStatement {
2180
+ if_block,
2181
+ elseif_blocks,
2182
+ else_block,
2183
+ } = self ;
2184
+
2185
+ write ! ( f, "{if_block}" ) ?;
2186
+
2187
+ if !elseif_blocks. is_empty ( ) {
2188
+ write ! ( f, " {}" , display_separated( elseif_blocks, " " ) ) ?;
2189
+ }
2190
+
2191
+ if let Some ( else_block) = else_block {
2192
+ write ! ( f, " ELSE " ) ?;
2193
+ format_statement_list ( f, else_block) ?;
2194
+ }
2195
+
2196
+ write ! ( f, " END IF" ) ?;
2197
+
2198
+ Ok ( ( ) )
2199
+ }
2200
+ }
2201
+
2202
+ /// Represents a type of [ConditionalStatements]
2203
+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2204
+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2205
+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2206
+ pub enum ConditionalStatementKind {
2207
+ /// `WHEN <condition> THEN <statements>`
2208
+ When ,
2209
+ /// `IF <condition> THEN <statements>`
2210
+ If ,
2211
+ /// `ELSEIF <condition> THEN <statements>`
2212
+ ElseIf ,
2213
+ }
2214
+
2215
+ /// A block within a [Statement::Case] or [Statement::If]-like statement
2216
+ ///
2217
+ /// Examples:
2218
+ /// ```sql
2219
+ /// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2220
+ ///
2221
+ /// IF TRUE THEN SELECT 1; SELECT 2;
2222
+ /// ```
2223
+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2224
+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2225
+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2226
+ pub struct ConditionalStatements {
2227
+ /// The condition expression.
2228
+ pub condition : Expr ,
2229
+ /// Statement list of the `THEN` clause.
2230
+ pub statements : Vec < Statement > ,
2231
+ pub kind : ConditionalStatementKind ,
2232
+ }
2233
+
2234
+ impl fmt:: Display for ConditionalStatements {
2235
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2236
+ let ConditionalStatements {
2237
+ condition : expr,
2238
+ statements,
2239
+ kind,
2240
+ } = self ;
2241
+
2242
+ let kind = match kind {
2243
+ ConditionalStatementKind :: When => "WHEN" ,
2244
+ ConditionalStatementKind :: If => "IF" ,
2245
+ ConditionalStatementKind :: ElseIf => "ELSEIF" ,
2246
+ } ;
2247
+
2248
+ write ! ( f, "{kind} {expr} THEN" ) ?;
2249
+
2250
+ if !statements. is_empty ( ) {
2251
+ write ! ( f, " " ) ?;
2252
+ format_statement_list ( f, statements) ?;
2253
+ }
2254
+
2255
+ Ok ( ( ) )
2256
+ }
2257
+ }
2258
+
2083
2259
/// Represents an expression assignment within a variable `DECLARE` statement.
2084
2260
///
2085
2261
/// Examples:
@@ -2647,6 +2823,10 @@ pub enum Statement {
2647
2823
file_format : Option < FileFormat > ,
2648
2824
source : Box < Query > ,
2649
2825
} ,
2826
+ /// A `CASE` statement.
2827
+ Case ( CaseStatement ) ,
2828
+ /// An `IF` statement.
2829
+ If ( IfStatement ) ,
2650
2830
/// ```sql
2651
2831
/// CALL <function>
2652
2832
/// ```
@@ -3940,6 +4120,12 @@ impl fmt::Display for Statement {
3940
4120
}
3941
4121
Ok ( ( ) )
3942
4122
}
4123
+ Statement :: Case ( stmt) => {
4124
+ write ! ( f, "{stmt}" )
4125
+ }
4126
+ Statement :: If ( stmt) => {
4127
+ write ! ( f, "{stmt}" )
4128
+ }
3943
4129
Statement :: AttachDatabase {
3944
4130
schema_name,
3945
4131
database_file_name,
@@ -4942,18 +5128,14 @@ impl fmt::Display for Statement {
4942
5128
write ! ( f, " {}" , display_comma_separated( modes) ) ?;
4943
5129
}
4944
5130
if !statements. is_empty ( ) {
4945
- write ! ( f, " {}" , display_separated( statements, "; " ) ) ?;
4946
- // We manually insert semicolon for the last statement,
4947
- // since display_separated doesn't handle that case.
4948
- write ! ( f, ";" ) ?;
5131
+ write ! ( f, " " ) ?;
5132
+ format_statement_list ( f, statements) ?;
4949
5133
}
4950
5134
if let Some ( exception_statements) = exception_statements {
4951
5135
write ! ( f, " EXCEPTION WHEN ERROR THEN" ) ?;
4952
5136
if !exception_statements. is_empty ( ) {
4953
- write ! ( f, " {}" , display_separated( exception_statements, "; " ) ) ?;
4954
- // We manually insert semicolon for the last statement,
4955
- // since display_separated doesn't handle that case.
4956
- write ! ( f, ";" ) ?;
5137
+ write ! ( f, " " ) ?;
5138
+ format_statement_list ( f, exception_statements) ?;
4957
5139
}
4958
5140
}
4959
5141
if * has_end_keyword {
0 commit comments