Skip to content

Commit ff29dd2

Browse files
Fix CASE expression spans (#1874)
1 parent e2b1ae3 commit ff29dd2

File tree

5 files changed

+43
-9
lines changed

5 files changed

+43
-9
lines changed

src/ast/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,8 @@ pub enum Expr {
967967
/// not `< 0` nor `1, 2, 3` as allowed in a `<simple when clause>` per
968968
/// <https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#simple-when-clause>
969969
Case {
970+
case_token: AttachedToken,
971+
end_token: AttachedToken,
970972
operand: Option<Box<Expr>>,
971973
conditions: Vec<CaseWhen>,
972974
else_result: Option<Box<Expr>>,
@@ -1675,6 +1677,8 @@ impl fmt::Display for Expr {
16751677
}
16761678
Expr::Function(fun) => fun.fmt(f),
16771679
Expr::Case {
1680+
case_token: _,
1681+
end_token: _,
16781682
operand,
16791683
conditions,
16801684
else_result,

src/ast/spans.rs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,18 +1567,24 @@ impl Spanned for Expr {
15671567
),
15681568
Expr::Prefixed { value, .. } => value.span(),
15691569
Expr::Case {
1570+
case_token,
1571+
end_token,
15701572
operand,
15711573
conditions,
15721574
else_result,
15731575
} => union_spans(
1574-
operand
1575-
.as_ref()
1576-
.map(|i| i.span())
1577-
.into_iter()
1578-
.chain(conditions.iter().flat_map(|case_when| {
1579-
[case_when.condition.span(), case_when.result.span()]
1580-
}))
1581-
.chain(else_result.as_ref().map(|i| i.span())),
1576+
iter::once(case_token.0.span)
1577+
.chain(
1578+
operand
1579+
.as_ref()
1580+
.map(|i| i.span())
1581+
.into_iter()
1582+
.chain(conditions.iter().flat_map(|case_when| {
1583+
[case_when.condition.span(), case_when.result.span()]
1584+
}))
1585+
.chain(else_result.as_ref().map(|i| i.span())),
1586+
)
1587+
.chain(iter::once(end_token.0.span)),
15821588
),
15831589
Expr::Exists { subquery, .. } => subquery.span(),
15841590
Expr::Subquery(query) => query.span(),
@@ -2464,4 +2470,16 @@ pub mod tests {
24642470

24652471
assert_eq!(test.get_source(body_span), "SELECT cte.* FROM cte");
24662472
}
2473+
2474+
#[test]
2475+
fn test_case_expr_span() {
2476+
let dialect = &GenericDialect;
2477+
let mut test = SpanTest::new(dialect, "CASE 1 WHEN 2 THEN 3 ELSE 4 END");
2478+
let expr = test.0.parse_expr().unwrap();
2479+
let expr_span = expr.span();
2480+
assert_eq!(
2481+
test.get_source(expr_span),
2482+
"CASE 1 WHEN 2 THEN 3 ELSE 4 END"
2483+
);
2484+
}
24672485
}

src/parser/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2274,6 +2274,7 @@ impl<'a> Parser<'a> {
22742274
}
22752275

22762276
pub fn parse_case_expr(&mut self) -> Result<Expr, ParserError> {
2277+
let case_token = AttachedToken(self.get_current_token().clone());
22772278
let mut operand = None;
22782279
if !self.parse_keyword(Keyword::WHEN) {
22792280
operand = Some(Box::new(self.parse_expr()?));
@@ -2294,8 +2295,10 @@ impl<'a> Parser<'a> {
22942295
} else {
22952296
None
22962297
};
2297-
self.expect_keyword_is(Keyword::END)?;
2298+
let end_token = AttachedToken(self.expect_keyword(Keyword::END)?);
22982299
Ok(Expr::Case {
2300+
case_token,
2301+
end_token,
22992302
operand,
23002303
conditions,
23012304
else_result,

tests/sqlparser_common.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6869,6 +6869,8 @@ fn parse_searched_case_expr() {
68696869
let select = verified_only_select(sql);
68706870
assert_eq!(
68716871
&Case {
6872+
case_token: AttachedToken::empty(),
6873+
end_token: AttachedToken::empty(),
68726874
operand: None,
68736875
conditions: vec![
68746876
CaseWhen {
@@ -6908,6 +6910,8 @@ fn parse_simple_case_expr() {
69086910
use self::Expr::{Case, Identifier};
69096911
assert_eq!(
69106912
&Case {
6913+
case_token: AttachedToken::empty(),
6914+
end_token: AttachedToken::empty(),
69116915
operand: Some(Box::new(Identifier(Ident::new("foo")))),
69126916
conditions: vec![CaseWhen {
69136917
condition: Expr::value(number("1")),
@@ -14650,6 +14654,8 @@ fn test_lambdas() {
1465014654
Expr::Lambda(LambdaFunction {
1465114655
params: OneOrManyWithParens::Many(vec![Ident::new("p1"), Ident::new("p2")]),
1465214656
body: Box::new(Expr::Case {
14657+
case_token: AttachedToken::empty(),
14658+
end_token: AttachedToken::empty(),
1465314659
operand: None,
1465414660
conditions: vec![
1465514661
CaseWhen {

tests/sqlparser_databricks.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18+
use sqlparser::ast::helpers::attached_token::AttachedToken;
1819
use sqlparser::ast::*;
1920
use sqlparser::dialect::{DatabricksDialect, GenericDialect};
2021
use sqlparser::parser::ParserError;
@@ -108,6 +109,8 @@ fn test_databricks_lambdas() {
108109
Expr::Lambda(LambdaFunction {
109110
params: OneOrManyWithParens::Many(vec![Ident::new("p1"), Ident::new("p2")]),
110111
body: Box::new(Expr::Case {
112+
case_token: AttachedToken::empty(),
113+
end_token: AttachedToken::empty(),
111114
operand: None,
112115
conditions: vec![
113116
CaseWhen {

0 commit comments

Comments
 (0)