Skip to content

Commit 862e7a6

Browse files
MazterQyoumcheshkov
authored andcommitted
fix: Correct INTERVAL + INTERVAL expression parsing
Recheck this after rebase on commit 57083a0 "Fix interval parsing logic and precedence (apache#705)", first released in 0.28.0
1 parent f342d66 commit 862e7a6

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

src/parser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1095,7 +1095,7 @@ impl<'a> Parser<'a> {
10951095

10961096
// The first token in an interval is a string literal which specifies
10971097
// the duration of the interval.
1098-
let value = self.parse_expr()?;
1098+
let value = self.parse_subexpr(Self::PLUS_MINUS_PREC)?;
10991099

11001100
// Following the string literal is a qualifier which indicates the units
11011101
// of the duration specified in the string literal.

tests/sqlparser_common.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2863,6 +2863,59 @@ fn parse_literal_interval() {
28632863
);
28642864
}
28652865

2866+
#[test]
2867+
fn parse_interval_math() {
2868+
let sql = "SELECT INTERVAL '1 DAY' + INTERVAL '2 DAY'";
2869+
let select = verified_only_select(sql);
2870+
assert_eq!(
2871+
&Expr::BinaryOp {
2872+
left: Box::new(Expr::Value(Value::Interval {
2873+
value: Box::new(Expr::Value(Value::SingleQuotedString("1 DAY".to_string()))),
2874+
leading_field: None,
2875+
leading_precision: None,
2876+
last_field: None,
2877+
fractional_seconds_precision: None,
2878+
})),
2879+
op: BinaryOperator::Plus,
2880+
right: Box::new(Expr::Value(Value::Interval {
2881+
value: Box::new(Expr::Value(Value::SingleQuotedString("2 DAY".to_string()))),
2882+
leading_field: None,
2883+
leading_precision: None,
2884+
last_field: None,
2885+
fractional_seconds_precision: None,
2886+
})),
2887+
},
2888+
expr_from_projection(only(&select.projection)),
2889+
);
2890+
2891+
let sql = "SELECT INTERVAL '1' || ' DAY' + INTERVAL '2 DAY'";
2892+
let select = verified_only_select(sql);
2893+
assert_eq!(
2894+
&Expr::BinaryOp {
2895+
left: Box::new(Expr::Value(Value::Interval {
2896+
value: Box::new(Expr::BinaryOp {
2897+
left: Box::new(Expr::Value(Value::SingleQuotedString("1".to_string()))),
2898+
op: BinaryOperator::StringConcat,
2899+
right: Box::new(Expr::Value(Value::SingleQuotedString(" DAY".to_string()))),
2900+
}),
2901+
leading_field: None,
2902+
leading_precision: None,
2903+
last_field: None,
2904+
fractional_seconds_precision: None,
2905+
})),
2906+
op: BinaryOperator::Plus,
2907+
right: Box::new(Expr::Value(Value::Interval {
2908+
value: Box::new(Expr::Value(Value::SingleQuotedString("2 DAY".to_string()))),
2909+
leading_field: None,
2910+
leading_precision: None,
2911+
last_field: None,
2912+
fractional_seconds_precision: None,
2913+
})),
2914+
},
2915+
expr_from_projection(only(&select.projection)),
2916+
);
2917+
}
2918+
28662919
#[test]
28672920
fn parse_at_timezone() {
28682921
let zero = Expr::Value(number("0"));

0 commit comments

Comments
 (0)