Skip to content

Commit 88b5875

Browse files
authored
feat(query): support date_between(date_part, startdate, enddate) (#17782)
* feat(query): support datesub(date_part, startdate, enddate) * rename to date_between * fix ci err: test_statement_error
1 parent 61bf3ef commit 88b5875

File tree

14 files changed

+1070
-34
lines changed

14 files changed

+1070
-34
lines changed

โ€Žsrc/query/ast/src/ast/expr.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,12 @@ pub enum Expr {
235235
date_start: Box<Expr>,
236236
date_end: Box<Expr>,
237237
},
238+
DateBetween {
239+
span: Span,
240+
unit: IntervalKind,
241+
date_start: Box<Expr>,
242+
date_end: Box<Expr>,
243+
},
238244
DateSub {
239245
span: Span,
240246
unit: IntervalKind,
@@ -302,6 +308,7 @@ impl Expr {
302308
| Expr::Interval { span, .. }
303309
| Expr::DateAdd { span, .. }
304310
| Expr::DateDiff { span, .. }
311+
| Expr::DateBetween { span, .. }
305312
| Expr::DateSub { span, .. }
306313
| Expr::DateTrunc { span, .. }
307314
| Expr::LastDay { span, .. }
@@ -443,6 +450,15 @@ impl Expr {
443450
merge_span(*span, date_start.whole_span()),
444451
date_end.whole_span(),
445452
),
453+
Expr::DateBetween {
454+
span,
455+
date_start,
456+
date_end,
457+
..
458+
} => merge_span(
459+
merge_span(*span, date_start.whole_span()),
460+
date_end.whole_span(),
461+
),
446462
Expr::DateSub {
447463
span,
448464
interval,
@@ -766,6 +782,14 @@ impl Display for Expr {
766782
} => {
767783
write!(f, "DATE_DIFF({unit}, {date_start}, {date_end})")?;
768784
}
785+
Expr::DateBetween {
786+
unit,
787+
date_start,
788+
date_end,
789+
..
790+
} => {
791+
write!(f, "DATE_BETWEEN({unit}, {date_start}, {date_end})")?;
792+
}
769793
Expr::DateSub {
770794
unit,
771795
interval,
@@ -2136,6 +2160,14 @@ impl ExprReplacer {
21362160
self.replace_expr(date_start);
21372161
self.replace_expr(date_end);
21382162
}
2163+
Expr::DateBetween {
2164+
date_start,
2165+
date_end,
2166+
..
2167+
} => {
2168+
self.replace_expr(date_start);
2169+
self.replace_expr(date_end);
2170+
}
21392171
Expr::DateSub { interval, date, .. } => {
21402172
self.replace_expr(interval);
21412173
self.replace_expr(date);

โ€Žsrc/query/ast/src/parser/expr.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,11 @@ pub enum ExprElement {
304304
date_start: Expr,
305305
date_end: Expr,
306306
},
307+
DateBetween {
308+
unit: IntervalKind,
309+
date_start: Expr,
310+
date_end: Expr,
311+
},
307312
DateSub {
308313
unit: IntervalKind,
309314
interval: Expr,
@@ -430,6 +435,7 @@ impl ExprElement {
430435
ExprElement::Interval { .. } => Affix::Nilfix,
431436
ExprElement::DateAdd { .. } => Affix::Nilfix,
432437
ExprElement::DateDiff { .. } => Affix::Nilfix,
438+
ExprElement::DateBetween { .. } => Affix::Nilfix,
433439
ExprElement::DateSub { .. } => Affix::Nilfix,
434440
ExprElement::DateTrunc { .. } => Affix::Nilfix,
435441
ExprElement::LastDay { .. } => Affix::Nilfix,
@@ -477,6 +483,7 @@ impl Expr {
477483
Expr::Interval { .. } => Affix::Nilfix,
478484
Expr::DateAdd { .. } => Affix::Nilfix,
479485
Expr::DateDiff { .. } => Affix::Nilfix,
486+
Expr::DateBetween { .. } => Affix::Nilfix,
480487
Expr::DateSub { .. } => Affix::Nilfix,
481488
Expr::DateTrunc { .. } => Affix::Nilfix,
482489
Expr::LastDay { .. } => Affix::Nilfix,
@@ -668,6 +675,16 @@ impl<'a, I: Iterator<Item = WithSpan<'a, ExprElement>>> PrattParser<I> for ExprP
668675
date_start: Box::new(date_start),
669676
date_end: Box::new(date_end),
670677
},
678+
ExprElement::DateBetween {
679+
unit,
680+
date_start,
681+
date_end,
682+
} => Expr::DateBetween {
683+
span: transform_span(elem.span.tokens),
684+
unit,
685+
date_start: Box::new(date_start),
686+
date_end: Box::new(date_end),
687+
},
671688
ExprElement::DateSub {
672689
unit,
673690
interval,
@@ -1255,14 +1272,26 @@ pub fn expr_element(i: Input) -> IResult<WithSpan<ExprElement>> {
12551272

12561273
let date_sub = map(
12571274
rule! {
1258-
(DATE_SUB | DATESUB) ~ "(" ~ #interval_kind ~ "," ~ #subexpr(0) ~ "," ~ #subexpr(0) ~ ")"
1275+
(DATESUB | DATE_SUB) ~ "(" ~ #interval_kind ~ "," ~ #subexpr(0) ~ "," ~ #subexpr(0) ~ ")"
12591276
},
12601277
|(_, _, unit, _, interval, _, date, _)| ExprElement::DateSub {
12611278
unit,
12621279
interval,
12631280
date,
12641281
},
12651282
);
1283+
1284+
let date_between = map(
1285+
rule! {
1286+
(DATEBETWEEN | DATE_BETWEEN) ~ "(" ~ #interval_kind ~ "," ~ #subexpr(0) ~ "," ~ #subexpr(0) ~ ")"
1287+
},
1288+
|(_, _, unit, _, date_start, _, date_end, _)| ExprElement::DateBetween {
1289+
unit,
1290+
date_start,
1291+
date_end,
1292+
},
1293+
);
1294+
12661295
let interval = map(
12671296
rule! {
12681297
INTERVAL ~ #subexpr(0) ~ #interval_kind
@@ -1381,6 +1410,7 @@ pub fn expr_element(i: Input) -> IResult<WithSpan<ExprElement>> {
13811410
#date_add : "`DATE_ADD(..., ..., (YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE | SECOND | DOY | DOW))`"
13821411
| #date_diff : "`DATE_DIFF(..., ..., (YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE | SECOND | DOY | DOW))`"
13831412
| #date_sub : "`DATE_SUB(..., ..., (YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE | SECOND | DOY | DOW))`"
1413+
| #date_between : "`DATE_BETWEEN((YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE | SECOND | DOY | DOW), ..., ...,)`"
13841414
| #date_trunc : "`DATE_TRUNC((YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE | SECOND), ...)`"
13851415
| #last_day : "`LAST_DAY(..., (YEAR | QUARTER | MONTH | WEEK)))`"
13861416
| #previous_day : "`PREVIOUS_DAY(..., (Sunday | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday))`"

โ€Žsrc/query/ast/src/parser/token.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,10 @@ pub enum TokenKind {
507507
DATEPART,
508508
#[token("DATE_SUB", ignore(ascii_case))]
509509
DATE_SUB,
510+
#[token("DATE_BETWEEN", ignore(ascii_case))]
511+
DATE_BETWEEN,
512+
#[token("DATEBETWEEN", ignore(ascii_case))]
513+
DATEBETWEEN,
510514
#[token("DATESUB", ignore(ascii_case))]
511515
DATESUB,
512516
#[token("DATE_TRUNC", ignore(ascii_case))]
@@ -1545,6 +1549,7 @@ impl TokenKind {
15451549
| TokenKind::DATEPART
15461550
| TokenKind::DATEDIFF
15471551
| TokenKind::DATESUB
1552+
| TokenKind::DATEBETWEEN
15481553
| TokenKind::FALSE
15491554
| TokenKind::FLOAT
15501555
// | TokenKind::FOREIGN
@@ -1653,6 +1658,7 @@ impl TokenKind {
16531658
| TokenKind::DATE_ADD
16541659
| TokenKind::DATE_DIFF
16551660
| TokenKind::DATE_SUB
1661+
| TokenKind::DATE_BETWEEN
16561662
| TokenKind::DATE_TRUNC
16571663
| TokenKind::LAST_DAY
16581664
| TokenKind::PREVIOUS_DAY

โ€Žsrc/query/ast/tests/it/parser.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1234,7 +1234,8 @@ fn test_expr() {
12341234
r#"date_part(year, d)"#,
12351235
r#"datepart(year, d)"#,
12361236
r#"DATEDIFF(SECOND, to_timestamp('2024-01-01 21:01:35.423179'), to_timestamp('2023-12-31 09:38:18.165575'))"#,
1237-
r#"datesub(QUARTER, 1, to_date('2018-01-02'))"#,
1237+
r#"date_sub(QUARTER, 1, to_date('2018-01-02'))"#,
1238+
r#"datebetween(QUARTER, to_date('2018-01-02'), to_date('2018-04-02'))"#,
12381239
r#"position('a' in str)"#,
12391240
r#"substring(a from b for c)"#,
12401241
r#"substring(a, b, c)"#,

โ€Žsrc/query/ast/tests/it/testdata/expr-error.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ error:
5252
--> SQL:1:10
5353
|
5454
1 | CAST(col1)
55-
| ---- ^ unexpected `)`, expecting `AS`, `,`, `(`, `IS`, `NOT`, `IN`, `EXISTS`, `BETWEEN`, `+`, `-`, `*`, `/`, `//`, `DIV`, `%`, `||`, `<->`, `>`, `<`, `>=`, `<=`, `=`, `<>`, `!=`, `^`, `AND`, `OR`, `XOR`, `LIKE`, `REGEXP`, `RLIKE`, `SOUNDS`, <BitWiseOr>, <BitWiseAnd>, <BitWiseXor>, <ShiftLeft>, <ShiftRight>, `->`, `->>`, `#>`, `#>>`, `?`, `?|`, `?&`, `@>`, `<@`, `@?`, `@@`, `#-`, <Factorial>, <SquareRoot>, <BitWiseNot>, <CubeRoot>, <Abs>, `CAST`, `TRY_CAST`, `::`, `POSITION`, `IdentVariable`, `DATE_ADD`, or 39 more ...
55+
| ---- ^ unexpected `)`, expecting `AS`, `,`, `(`, `IS`, `NOT`, `IN`, `EXISTS`, `BETWEEN`, `+`, `-`, `*`, `/`, `//`, `DIV`, `%`, `||`, `<->`, `>`, `<`, `>=`, `<=`, `=`, `<>`, `!=`, `^`, `AND`, `OR`, `XOR`, `LIKE`, `REGEXP`, `RLIKE`, `SOUNDS`, <BitWiseOr>, <BitWiseAnd>, <BitWiseXor>, <ShiftLeft>, <ShiftRight>, `->`, `->>`, `#>`, `#>>`, `?`, `?|`, `?&`, `@>`, `<@`, `@?`, `@@`, `#-`, <Factorial>, <SquareRoot>, <BitWiseNot>, <CubeRoot>, <Abs>, `CAST`, `TRY_CAST`, `::`, `POSITION`, `IdentVariable`, `DATE_ADD`, or 41 more ...
5656
| |
5757
| while parsing `CAST(... AS ...)`
5858
| while parsing expression
@@ -81,7 +81,7 @@ error:
8181
1 | $ abc + 3
8282
| ^
8383
| |
84-
| unexpected `$`, expecting `IS`, `IN`, `EXISTS`, `BETWEEN`, `+`, `-`, `*`, `/`, `//`, `DIV`, `%`, `||`, `<->`, `>`, `<`, `>=`, `<=`, `=`, `<>`, `!=`, `^`, `AND`, `OR`, `XOR`, `LIKE`, `NOT`, `REGEXP`, `RLIKE`, `SOUNDS`, <BitWiseOr>, <BitWiseAnd>, <BitWiseXor>, <ShiftLeft>, <ShiftRight>, `->`, `->>`, `#>`, `#>>`, `?`, `?|`, `?&`, `@>`, `<@`, `@?`, `@@`, `#-`, <Factorial>, <SquareRoot>, <BitWiseNot>, <CubeRoot>, <Abs>, `CAST`, `TRY_CAST`, `::`, `POSITION`, `IdentVariable`, `DATE_ADD`, `DATE_DIFF`, `DATEDIFF`, `DATE_SUB`, or 37 more ...
84+
| unexpected `$`, expecting `IS`, `IN`, `EXISTS`, `BETWEEN`, `+`, `-`, `*`, `/`, `//`, `DIV`, `%`, `||`, `<->`, `>`, `<`, `>=`, `<=`, `=`, `<>`, `!=`, `^`, `AND`, `OR`, `XOR`, `LIKE`, `NOT`, `REGEXP`, `RLIKE`, `SOUNDS`, <BitWiseOr>, <BitWiseAnd>, <BitWiseXor>, <ShiftLeft>, <ShiftRight>, `->`, `->>`, `#>`, `#>>`, `?`, `?|`, `?&`, `@>`, `<@`, `@?`, `@@`, `#-`, <Factorial>, <SquareRoot>, <BitWiseNot>, <CubeRoot>, <Abs>, `CAST`, `TRY_CAST`, `::`, `POSITION`, `IdentVariable`, `DATE_ADD`, `DATE_DIFF`, `DATEDIFF`, `DATESUB`, or 39 more ...
8585
| while parsing expression
8686

8787

โ€Žsrc/query/ast/tests/it/testdata/expr.txt

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,32 +1916,32 @@ DateDiff {
19161916

19171917

19181918
---------- Input ----------
1919-
datesub(QUARTER, 1, to_date('2018-01-02'))
1919+
date_sub(QUARTER, 1, to_date('2018-01-02'))
19201920
---------- Output ---------
19211921
DATE_SUB(QUARTER, 1, to_date('2018-01-02'))
19221922
---------- AST ------------
19231923
DateSub {
19241924
span: Some(
1925-
0..42,
1925+
0..43,
19261926
),
19271927
unit: Quarter,
19281928
interval: Literal {
19291929
span: Some(
1930-
17..18,
1930+
18..19,
19311931
),
19321932
value: UInt64(
19331933
1,
19341934
),
19351935
},
19361936
date: FunctionCall {
19371937
span: Some(
1938-
20..41,
1938+
21..42,
19391939
),
19401940
func: FunctionCall {
19411941
distinct: false,
19421942
name: Identifier {
19431943
span: Some(
1944-
20..27,
1944+
21..28,
19451945
),
19461946
name: "to_date",
19471947
quote: None,
@@ -1950,7 +1950,7 @@ DateSub {
19501950
args: [
19511951
Literal {
19521952
span: Some(
1953-
28..40,
1953+
29..41,
19541954
),
19551955
value: String(
19561956
"2018-01-02",
@@ -1966,6 +1966,79 @@ DateSub {
19661966
}
19671967

19681968

1969+
---------- Input ----------
1970+
datebetween(QUARTER, to_date('2018-01-02'), to_date('2018-04-02'))
1971+
---------- Output ---------
1972+
DATE_BETWEEN(QUARTER, to_date('2018-01-02'), to_date('2018-04-02'))
1973+
---------- AST ------------
1974+
DateBetween {
1975+
span: Some(
1976+
0..66,
1977+
),
1978+
unit: Quarter,
1979+
date_start: FunctionCall {
1980+
span: Some(
1981+
21..42,
1982+
),
1983+
func: FunctionCall {
1984+
distinct: false,
1985+
name: Identifier {
1986+
span: Some(
1987+
21..28,
1988+
),
1989+
name: "to_date",
1990+
quote: None,
1991+
ident_type: None,
1992+
},
1993+
args: [
1994+
Literal {
1995+
span: Some(
1996+
29..41,
1997+
),
1998+
value: String(
1999+
"2018-01-02",
2000+
),
2001+
},
2002+
],
2003+
params: [],
2004+
order_by: [],
2005+
window: None,
2006+
lambda: None,
2007+
},
2008+
},
2009+
date_end: FunctionCall {
2010+
span: Some(
2011+
44..65,
2012+
),
2013+
func: FunctionCall {
2014+
distinct: false,
2015+
name: Identifier {
2016+
span: Some(
2017+
44..51,
2018+
),
2019+
name: "to_date",
2020+
quote: None,
2021+
ident_type: None,
2022+
},
2023+
args: [
2024+
Literal {
2025+
span: Some(
2026+
52..64,
2027+
),
2028+
value: String(
2029+
"2018-04-02",
2030+
),
2031+
},
2032+
],
2033+
params: [],
2034+
order_by: [],
2035+
window: None,
2036+
lambda: None,
2037+
},
2038+
},
2039+
}
2040+
2041+
19692042
---------- Input ----------
19702043
position('a' in str)
19712044
---------- Output ---------

โ€Žsrc/query/ast/tests/it/testdata/stmt-error.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ error:
513513
--> SQL:1:41
514514
|
515515
1 | SELECT * FROM t GROUP BY GROUPING SETS ()
516-
| ------ ^ unexpected `)`, expecting `(`, `IS`, `IN`, `EXISTS`, `BETWEEN`, `+`, `-`, `*`, `/`, `//`, `DIV`, `%`, `||`, `<->`, `>`, `<`, `>=`, `<=`, `=`, `<>`, `!=`, `^`, `AND`, `OR`, `XOR`, `LIKE`, `NOT`, `REGEXP`, `RLIKE`, `SOUNDS`, <BitWiseOr>, <BitWiseAnd>, <BitWiseXor>, <ShiftLeft>, <ShiftRight>, `->`, `->>`, `#>`, `#>>`, `?`, `?|`, `?&`, `@>`, `<@`, `@?`, `@@`, `#-`, <Factorial>, <SquareRoot>, <BitWiseNot>, <CubeRoot>, <Abs>, `CAST`, `TRY_CAST`, `::`, `POSITION`, `IdentVariable`, `DATE_ADD`, `DATE_DIFF`, `DATEDIFF`, or 37 more ...
516+
| ------ ^ unexpected `)`, expecting `(`, `IS`, `IN`, `EXISTS`, `BETWEEN`, `+`, `-`, `*`, `/`, `//`, `DIV`, `%`, `||`, `<->`, `>`, `<`, `>=`, `<=`, `=`, `<>`, `!=`, `^`, `AND`, `OR`, `XOR`, `LIKE`, `NOT`, `REGEXP`, `RLIKE`, `SOUNDS`, <BitWiseOr>, <BitWiseAnd>, <BitWiseXor>, <ShiftLeft>, <ShiftRight>, `->`, `->>`, `#>`, `#>>`, `?`, `?|`, `?&`, `@>`, `<@`, `@?`, `@@`, `#-`, <Factorial>, <SquareRoot>, <BitWiseNot>, <CubeRoot>, <Abs>, `CAST`, `TRY_CAST`, `::`, `POSITION`, `IdentVariable`, `DATE_ADD`, `DATE_DIFF`, `DATEDIFF`, or 39 more ...
517517
| |
518518
| while parsing `SELECT ...`
519519

@@ -935,7 +935,7 @@ error:
935935
--> SQL:1:65
936936
|
937937
1 | CREATE FUNCTION IF NOT EXISTS isnotempty AS(p) -> not(is_null(p)
938-
| ------ -- ---- ^ unexpected end of input, expecting `)`, `IGNORE`, `RESPECT`, `OVER`, `WITHIN`, `(`, `IS`, `NOT`, `IN`, `EXISTS`, `BETWEEN`, `+`, `-`, `*`, `/`, `//`, `DIV`, `%`, `||`, `<->`, `>`, `<`, `>=`, `<=`, `=`, `<>`, `!=`, `^`, `AND`, `OR`, `XOR`, `LIKE`, `REGEXP`, `RLIKE`, `SOUNDS`, <BitWiseOr>, <BitWiseAnd>, <BitWiseXor>, <ShiftLeft>, <ShiftRight>, `->`, `->>`, `#>`, `#>>`, `?`, `?|`, `?&`, `@>`, `<@`, `@?`, `@@`, `#-`, <Factorial>, <SquareRoot>, <BitWiseNot>, <CubeRoot>, <Abs>, `CAST`, `TRY_CAST`, `::`, or 43 more ...
938+
| ------ -- ---- ^ unexpected end of input, expecting `)`, `IGNORE`, `RESPECT`, `OVER`, `WITHIN`, `(`, `IS`, `NOT`, `IN`, `EXISTS`, `BETWEEN`, `+`, `-`, `*`, `/`, `//`, `DIV`, `%`, `||`, `<->`, `>`, `<`, `>=`, `<=`, `=`, `<>`, `!=`, `^`, `AND`, `OR`, `XOR`, `LIKE`, `REGEXP`, `RLIKE`, `SOUNDS`, <BitWiseOr>, <BitWiseAnd>, <BitWiseXor>, <ShiftLeft>, <ShiftRight>, `->`, `->>`, `#>`, `#>>`, `?`, `?|`, `?&`, `@>`, `<@`, `@?`, `@@`, `#-`, <Factorial>, <SquareRoot>, <BitWiseNot>, <CubeRoot>, <Abs>, `CAST`, `TRY_CAST`, `::`, or 45 more ...
939939
| | | | |
940940
| | | | while parsing `(<expr> [, ...])`
941941
| | | while parsing expression

0 commit comments

Comments
ย (0)