@@ -37,7 +37,8 @@ use serde::{Deserialize, Serialize};
37
37
#[ cfg( feature = "visitor" ) ]
38
38
use sqlparser_derive:: { Visit , VisitMut } ;
39
39
40
- use crate :: tokenizer:: Span ;
40
+ use crate :: keywords:: Keyword ;
41
+ use crate :: tokenizer:: { Span , Token } ;
41
42
42
43
pub use self :: data_type:: {
43
44
ArrayElemTypeDef , BinaryLength , CharLengthUnits , CharacterLength , DataType , EnumMember ,
@@ -2118,20 +2119,23 @@ pub enum Password {
2118
2119
#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2119
2120
#[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2120
2121
pub struct CaseStatement {
2122
+ /// The `CASE` token that starts the statement.
2123
+ pub case_token : AttachedToken ,
2121
2124
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 ,
2126
2129
}
2127
2130
2128
2131
impl fmt:: Display for CaseStatement {
2129
2132
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2130
2133
let CaseStatement {
2134
+ case_token : _,
2131
2135
match_expr,
2132
2136
when_blocks,
2133
2137
else_block,
2134
- has_end_case ,
2138
+ end_case_token : AttachedToken ( end ) ,
2135
2139
} = self ;
2136
2140
2137
2141
write ! ( f, "CASE" ) ?;
@@ -2145,13 +2149,15 @@ impl fmt::Display for CaseStatement {
2145
2149
}
2146
2150
2147
2151
if let Some ( else_block) = else_block {
2148
- write ! ( f, " ELSE " ) ?;
2149
- format_statement_list ( f, else_block) ?;
2152
+ write ! ( f, " {else_block}" ) ?;
2150
2153
}
2151
2154
2152
2155
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
+ }
2155
2161
}
2156
2162
2157
2163
Ok ( ( ) )
@@ -2160,7 +2166,7 @@ impl fmt::Display for CaseStatement {
2160
2166
2161
2167
/// An `IF` statement.
2162
2168
///
2163
- /// Examples :
2169
+ /// Example (BigQuery or Snowflake) :
2164
2170
/// ```sql
2165
2171
/// IF TRUE THEN
2166
2172
/// SELECT 1;
@@ -2171,16 +2177,22 @@ impl fmt::Display for CaseStatement {
2171
2177
/// SELECT 4;
2172
2178
/// END IF
2173
2179
/// ```
2174
- ///
2175
2180
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#if)
2176
2181
/// [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)
2177
2188
#[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2178
2189
#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2179
2190
#[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2180
2191
pub 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 > ,
2184
2196
}
2185
2197
2186
2198
impl fmt:: Display for IfStatement {
@@ -2189,82 +2201,128 @@ impl fmt::Display for IfStatement {
2189
2201
if_block,
2190
2202
elseif_blocks,
2191
2203
else_block,
2204
+ end_token,
2192
2205
} = self ;
2193
2206
2194
2207
write ! ( f, "{if_block}" ) ?;
2195
2208
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}" ) ?;
2198
2211
}
2199
2212
2200
2213
if let Some ( else_block) = else_block {
2201
- write ! ( f, " ELSE " ) ?;
2202
- format_statement_list ( f, else_block) ?;
2214
+ write ! ( f, " {else_block}" ) ?;
2203
2215
}
2204
2216
2205
- write ! ( f, " END IF" ) ?;
2217
+ if let Some ( AttachedToken ( end_token) ) = end_token {
2218
+ write ! ( f, " END {end_token}" ) ?;
2219
+ }
2206
2220
2207
2221
Ok ( ( ) )
2208
2222
}
2209
2223
}
2210
2224
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
-
2224
2225
/// A block within a [Statement::Case] or [Statement::If]-like statement
2225
2226
///
2226
- /// Examples :
2227
+ /// Example 1 :
2227
2228
/// ```sql
2228
2229
/// WHEN EXISTS(SELECT 1) THEN SELECT 1;
2230
+ /// ```
2229
2231
///
2232
+ /// Example 2:
2233
+ /// ```sql
2230
2234
/// IF TRUE THEN SELECT 1; SELECT 2;
2231
2235
/// ```
2236
+ ///
2237
+ /// Example 3:
2238
+ /// ```sql
2239
+ /// ELSE SELECT 1; SELECT 2;
2240
+ /// ```
2232
2241
#[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2233
2242
#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2234
2243
#[ 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 ,
2241
2249
}
2242
2250
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 {
2244
2258
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,
2249
2264
} = self ;
2250
2265
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
+ }
2256
2271
2257
- write ! ( f, "{kind} {expr} THEN" ) ?;
2272
+ if then_token. is_some ( ) {
2273
+ write ! ( f, " THEN" ) ?;
2274
+ }
2258
2275
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}" ) ?;
2262
2278
}
2263
2279
2264
2280
Ok ( ( ) )
2265
2281
}
2266
2282
}
2267
2283
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
+
2268
2326
/// A `RAISE` statement.
2269
2327
///
2270
2328
/// Examples:
0 commit comments