Skip to content

Commit 34ae859

Browse files
ovrmcheshkov
authored andcommitted
feat: Support INTERVAL with EXPR
Can drop this after rebase on commit d981f70 "fix: Support expr instead of string for argument to interval (apache#517)", first released in 0.19.0
1 parent 85d9e6f commit 34ae859

File tree

3 files changed

+49
-12
lines changed

3 files changed

+49
-12
lines changed

src/ast/value.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ use bigdecimal::BigDecimal;
1919
#[cfg(feature = "serde")]
2020
use serde::{Deserialize, Serialize};
2121

22+
use super::Expr;
23+
2224
/// Primitive SQL values such as number and string
2325
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2426
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
@@ -50,7 +52,7 @@ pub enum Value {
5052
/// that the `<leading_field>` units >= the units in `<last_field>`,
5153
/// so the user will have to reject intervals like `HOUR TO YEAR`.
5254
Interval {
53-
value: String,
55+
value: Box<Expr>,
5456
leading_field: Option<DateTimeField>,
5557
leading_precision: Option<u64>,
5658
last_field: Option<DateTimeField>,
@@ -88,8 +90,8 @@ impl fmt::Display for Value {
8890
assert!(last_field.is_none());
8991
write!(
9092
f,
91-
"INTERVAL '{}' SECOND ({}, {})",
92-
escape_single_quote_string(value),
93+
"INTERVAL {} SECOND ({}, {})",
94+
value.to_string(),
9395
leading_precision,
9496
fractional_seconds_precision
9597
)
@@ -101,7 +103,8 @@ impl fmt::Display for Value {
101103
last_field,
102104
fractional_seconds_precision,
103105
} => {
104-
write!(f, "INTERVAL '{}'", escape_single_quote_string(value))?;
106+
write!(f, "INTERVAL {}", value.to_string())?;
107+
105108
if let Some(leading_field) = leading_field {
106109
write!(f, " {}", leading_field)?;
107110
}

src/parser.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,7 +1003,7 @@ impl<'a> Parser<'a> {
10031003

10041004
// The first token in an interval is a string literal which specifies
10051005
// the duration of the interval.
1006-
let value = self.parse_literal_string()?;
1006+
let value = self.parse_expr()?;
10071007

10081008
// Following the string literal is a qualifier which indicates the units
10091009
// of the duration specified in the string literal.
@@ -1070,7 +1070,7 @@ impl<'a> Parser<'a> {
10701070
};
10711071

10721072
Ok(Expr::Value(Value::Interval {
1073-
value,
1073+
value: Box::new(value),
10741074
leading_field,
10751075
leading_precision,
10761076
last_field,

tests/sqlparser_common.rs

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2573,13 +2573,45 @@ fn parse_literal_timestamp() {
25732573
);
25742574
}
25752575

2576+
#[test]
2577+
fn parse_expr_interval() {
2578+
let sql = "SELECT INTERVAL HOUR(order_date) HOUR";
2579+
let select = verified_only_select(sql);
2580+
2581+
let value = Expr::Function(Function {
2582+
name: ObjectName(vec![Ident {
2583+
value: "HOUR".to_string(),
2584+
quote_style: None,
2585+
}]),
2586+
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
2587+
Expr::Identifier(Ident {
2588+
value: "order_date".to_string(),
2589+
quote_style: None,
2590+
}),
2591+
))],
2592+
over: None,
2593+
distinct: false,
2594+
});
2595+
2596+
assert_eq!(
2597+
&Expr::Value(Value::Interval {
2598+
value: Box::new(value),
2599+
leading_field: Some(DateTimeField::Hour),
2600+
leading_precision: None,
2601+
last_field: None,
2602+
fractional_seconds_precision: None,
2603+
}),
2604+
expr_from_projection(only(&select.projection)),
2605+
);
2606+
}
2607+
25762608
#[test]
25772609
fn parse_literal_interval() {
25782610
let sql = "SELECT INTERVAL '1-1' YEAR TO MONTH";
25792611
let select = verified_only_select(sql);
25802612
assert_eq!(
25812613
&Expr::Value(Value::Interval {
2582-
value: "1-1".into(),
2614+
value: Box::new(Expr::Value(Value::SingleQuotedString("1-1".to_string()))),
25832615
leading_field: Some(DateTimeField::Year),
25842616
leading_precision: None,
25852617
last_field: Some(DateTimeField::Month),
@@ -2592,7 +2624,9 @@ fn parse_literal_interval() {
25922624
let select = verified_only_select(sql);
25932625
assert_eq!(
25942626
&Expr::Value(Value::Interval {
2595-
value: "01:01.01".into(),
2627+
value: Box::new(Expr::Value(Value::SingleQuotedString(
2628+
"01:01.01".to_string()
2629+
))),
25962630
leading_field: Some(DateTimeField::Minute),
25972631
leading_precision: Some(5),
25982632
last_field: Some(DateTimeField::Second),
@@ -2605,7 +2639,7 @@ fn parse_literal_interval() {
26052639
let select = verified_only_select(sql);
26062640
assert_eq!(
26072641
&Expr::Value(Value::Interval {
2608-
value: "1".into(),
2642+
value: Box::new(Expr::Value(Value::SingleQuotedString("1".to_string()))),
26092643
leading_field: Some(DateTimeField::Second),
26102644
leading_precision: Some(5),
26112645
last_field: None,
@@ -2618,7 +2652,7 @@ fn parse_literal_interval() {
26182652
let select = verified_only_select(sql);
26192653
assert_eq!(
26202654
&Expr::Value(Value::Interval {
2621-
value: "10".into(),
2655+
value: Box::new(Expr::Value(Value::SingleQuotedString("10".to_string()))),
26222656
leading_field: Some(DateTimeField::Hour),
26232657
leading_precision: None,
26242658
last_field: None,
@@ -2631,7 +2665,7 @@ fn parse_literal_interval() {
26312665
let select = verified_only_select(sql);
26322666
assert_eq!(
26332667
&Expr::Value(Value::Interval {
2634-
value: "10".into(),
2668+
value: Box::new(Expr::Value(Value::SingleQuotedString("10".to_string()))),
26352669
leading_field: Some(DateTimeField::Hour),
26362670
leading_precision: Some(1),
26372671
last_field: None,
@@ -2644,7 +2678,7 @@ fn parse_literal_interval() {
26442678
let select = verified_only_select(sql);
26452679
assert_eq!(
26462680
&Expr::Value(Value::Interval {
2647-
value: "1 DAY".into(),
2681+
value: Box::new(Expr::Value(Value::SingleQuotedString("1 DAY".to_string()))),
26482682
leading_field: None,
26492683
leading_precision: None,
26502684
last_field: None,

0 commit comments

Comments
 (0)