Support CEIL(expr TO DateTimeField) and FLOOR(expr TO DateTimeField) (#635)

* support ceil/floor to datetime

* Update mod.rs

* Update parser.rs

* murphys law

* Update sqlparser_common.rs

* possible fix?

* remove question mark

* ceil to floor

* Update mod.rs

* Apply suggestions from code review

Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>

* refactor into parse_ceil_floor_expr

Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
Sarah Yurick 2022-10-06 12:21:25 -07:00 committed by GitHub
parent f7f14df4b1
commit cb397d19f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 134 additions and 6 deletions

View file

@ -450,6 +450,8 @@ impl<'a> Parser<'a> {
Keyword::SAFE_CAST => self.parse_safe_cast_expr(),
Keyword::EXISTS => self.parse_exists_expr(false),
Keyword::EXTRACT => self.parse_extract_expr(),
Keyword::CEIL => self.parse_ceil_floor_expr(true),
Keyword::FLOOR => self.parse_ceil_floor_expr(false),
Keyword::POSITION => self.parse_position_expr(),
Keyword::SUBSTRING => self.parse_substring_expr(),
Keyword::OVERLAY => self.parse_overlay_expr(),
@ -848,6 +850,30 @@ impl<'a> Parser<'a> {
})
}
pub fn parse_ceil_floor_expr(&mut self, is_ceil: bool) -> Result<Expr, ParserError> {
self.expect_token(&Token::LParen)?;
let expr = self.parse_expr()?;
// Parse `CEIL/FLOOR(expr)`
let mut field = DateTimeField::NoDateTime;
let keyword_to = self.parse_keyword(Keyword::TO);
if keyword_to {
// Parse `CEIL/FLOOR(expr TO DateTimeField)`
field = self.parse_date_time_field()?;
}
self.expect_token(&Token::RParen)?;
if is_ceil {
Ok(Expr::Ceil {
expr: Box::new(expr),
field,
})
} else {
Ok(Expr::Floor {
expr: Box::new(expr),
field,
})
}
}
pub fn parse_position_expr(&mut self) -> Result<Expr, ParserError> {
// PARSE SELECT POSITION('@' in field)
self.expect_token(&Token::LParen)?;
@ -1040,10 +1066,10 @@ impl<'a> Parser<'a> {
}))
}
// This function parses date/time fields for both the EXTRACT function-like
// operator and interval qualifiers. EXTRACT supports a wider set of
// date/time fields than interval qualifiers, so this function may need to
// be split in two.
// This function parses date/time fields for the EXTRACT function-like
// operator, interval qualifiers, and the ceil/floor operations.
// EXTRACT supports a wider set of date/time fields than interval qualifiers,
// so this function may need to be split in two.
pub fn parse_date_time_field(&mut self) -> Result<DateTimeField, ParserError> {
match self.next_token() {
Token::Word(w) => match w.keyword {
@ -1062,9 +1088,11 @@ impl<'a> Parser<'a> {
Keyword::ISODOW => Ok(DateTimeField::Isodow),
Keyword::ISOYEAR => Ok(DateTimeField::Isoyear),
Keyword::JULIAN => Ok(DateTimeField::Julian),
Keyword::MICROSECOND => Ok(DateTimeField::Microsecond),
Keyword::MICROSECONDS => Ok(DateTimeField::Microseconds),
Keyword::MILLENIUM => Ok(DateTimeField::Millenium),
Keyword::MILLENNIUM => Ok(DateTimeField::Millennium),
Keyword::MILLISECOND => Ok(DateTimeField::Millisecond),
Keyword::MILLISECONDS => Ok(DateTimeField::Milliseconds),
Keyword::QUARTER => Ok(DateTimeField::Quarter),
Keyword::TIMEZONE => Ok(DateTimeField::Timezone),
@ -1142,9 +1170,11 @@ impl<'a> Parser<'a> {
Keyword::ISODOW,
Keyword::ISOYEAR,
Keyword::JULIAN,
Keyword::MICROSECOND,
Keyword::MICROSECONDS,
Keyword::MILLENIUM,
Keyword::MILLENNIUM,
Keyword::MILLISECOND,
Keyword::MILLISECONDS,
Keyword::QUARTER,
Keyword::TIMEZONE,