@@ -56,15 +56,6 @@ macro_rules! parser_err {
5656 } ;
5757}
5858
59- // Returns a successful result if the optional expression is some
60- macro_rules! return_ok_if_some {
61- ( $e: expr) => { {
62- if let Some ( v) = $e {
63- return Ok ( v) ;
64- }
65- } } ;
66- }
67-
6859#[ cfg( feature = "std" ) ]
6960/// Implementation [`RecursionCounter`] if std is available
7061mod recursion {
@@ -928,35 +919,6 @@ impl<'a> Parser<'a> {
928919 Ok ( expr)
929920 }
930921
931- pub fn parse_interval_expr ( & mut self ) -> Result < Expr , ParserError > {
932- let precedence = self . dialect . prec_unknown ( ) ;
933- let mut expr = self . parse_prefix ( ) ?;
934-
935- loop {
936- let next_precedence = self . get_next_interval_precedence ( ) ?;
937-
938- if precedence >= next_precedence {
939- break ;
940- }
941-
942- expr = self . parse_infix ( expr, next_precedence) ?;
943- }
944-
945- Ok ( expr)
946- }
947-
948- /// Get the precedence of the next token, with AND, OR, and XOR.
949- pub fn get_next_interval_precedence ( & self ) -> Result < u8 , ParserError > {
950- let token = self . peek_token ( ) ;
951-
952- match token. token {
953- Token :: Word ( w) if w. keyword == Keyword :: AND => Ok ( self . dialect . prec_unknown ( ) ) ,
954- Token :: Word ( w) if w. keyword == Keyword :: OR => Ok ( self . dialect . prec_unknown ( ) ) ,
955- Token :: Word ( w) if w. keyword == Keyword :: XOR => Ok ( self . dialect . prec_unknown ( ) ) ,
956- _ => self . get_next_precedence ( ) ,
957- }
958- }
959-
960922 pub fn parse_assert ( & mut self ) -> Result < Statement , ParserError > {
961923 let condition = self . parse_expr ( ) ?;
962924 let message = if self . parse_keyword ( Keyword :: AS ) {
@@ -1004,7 +966,7 @@ impl<'a> Parser<'a> {
1004966 // name is not followed by a string literal, but in fact in PostgreSQL it is a valid
1005967 // expression that should parse as the column name "date".
1006968 let loc = self . peek_token ( ) . location ;
1007- return_ok_if_some ! ( self . maybe_parse( |parser| {
969+ let opt_expr = self . maybe_parse ( |parser| {
1008970 match parser. parse_data_type ( ) ? {
1009971 DataType :: Interval => parser. parse_interval ( ) ,
1010972 // PostgreSQL allows almost any identifier to be used as custom data type name,
@@ -1020,7 +982,11 @@ impl<'a> Parser<'a> {
1020982 value : parser. parse_literal_string ( ) ?,
1021983 } ) ,
1022984 }
1023- } ) ) ;
985+ } ) ;
986+
987+ if let Some ( expr) = opt_expr {
988+ return Ok ( expr) ;
989+ }
1024990
1025991 let next_token = self . next_token ( ) ;
1026992 let expr = match next_token. token {
@@ -2110,52 +2076,32 @@ impl<'a> Parser<'a> {
21102076 // don't currently try to parse it. (The sign can instead be included
21112077 // inside the value string.)
21122078
2113- // The first token in an interval is a string literal which specifies
2114- // the duration of the interval.
2115- let value = self . parse_interval_expr ( ) ?;
2079+ // to match the different flavours of INTERVAL syntax, we only allow expressions
2080+ // if the dialect requires an interval qualifier,
2081+ // see https://github.com/sqlparser-rs/sqlparser-rs/pull/1398 for more details
2082+ let value = if self . dialect . require_interval_qualifier ( ) {
2083+ // parse a whole expression so `INTERVAL 1 + 1 DAY` is valid
2084+ self . parse_expr ( ) ?
2085+ } else {
2086+ // parse a prefix expression so `INTERVAL 1 DAY` is valid, but `INTERVAL 1 + 1 DAY` is not
2087+ // this also means that `INTERVAL '5 days' > INTERVAL '1 day'` treated properly
2088+ self . parse_prefix ( ) ?
2089+ } ;
21162090
21172091 // Following the string literal is a qualifier which indicates the units
21182092 // of the duration specified in the string literal.
21192093 //
21202094 // Note that PostgreSQL allows omitting the qualifier, so we provide
21212095 // this more general implementation.
2122- let leading_field = match self . peek_token ( ) . token {
2123- Token :: Word ( kw)
2124- if [
2125- Keyword :: YEAR ,
2126- Keyword :: MONTH ,
2127- Keyword :: WEEK ,
2128- Keyword :: DAY ,
2129- Keyword :: HOUR ,
2130- Keyword :: MINUTE ,
2131- Keyword :: SECOND ,
2132- Keyword :: CENTURY ,
2133- Keyword :: DECADE ,
2134- Keyword :: DOW ,
2135- Keyword :: DOY ,
2136- Keyword :: EPOCH ,
2137- Keyword :: ISODOW ,
2138- Keyword :: ISOYEAR ,
2139- Keyword :: JULIAN ,
2140- Keyword :: MICROSECOND ,
2141- Keyword :: MICROSECONDS ,
2142- Keyword :: MILLENIUM ,
2143- Keyword :: MILLENNIUM ,
2144- Keyword :: MILLISECOND ,
2145- Keyword :: MILLISECONDS ,
2146- Keyword :: NANOSECOND ,
2147- Keyword :: NANOSECONDS ,
2148- Keyword :: QUARTER ,
2149- Keyword :: TIMEZONE ,
2150- Keyword :: TIMEZONE_HOUR ,
2151- Keyword :: TIMEZONE_MINUTE ,
2152- ]
2153- . iter ( )
2154- . any ( |d| kw. keyword == * d) =>
2155- {
2156- Some ( self . parse_date_time_field ( ) ?)
2157- }
2158- _ => None ,
2096+ let leading_field = if self . next_token_is_temporal_unit ( ) {
2097+ Some ( self . parse_date_time_field ( ) ?)
2098+ } else if self . dialect . require_interval_qualifier ( ) {
2099+ return parser_err ! (
2100+ "INTERVAL requires a unit after the literal value" ,
2101+ self . peek_token( ) . location
2102+ ) ;
2103+ } else {
2104+ None
21592105 } ;
21602106
21612107 let ( leading_precision, last_field, fsec_precision) =
@@ -2192,6 +2138,45 @@ impl<'a> Parser<'a> {
21922138 } ) )
21932139 }
21942140
2141+ /// Peek at the next token and determine if it is a temporal unit
2142+ /// like `second`.
2143+ pub fn next_token_is_temporal_unit ( & mut self ) -> bool {
2144+ if let Token :: Word ( word) = self . peek_token ( ) . token {
2145+ matches ! (
2146+ word. keyword,
2147+ Keyword :: YEAR
2148+ | Keyword :: MONTH
2149+ | Keyword :: WEEK
2150+ | Keyword :: DAY
2151+ | Keyword :: HOUR
2152+ | Keyword :: MINUTE
2153+ | Keyword :: SECOND
2154+ | Keyword :: CENTURY
2155+ | Keyword :: DECADE
2156+ | Keyword :: DOW
2157+ | Keyword :: DOY
2158+ | Keyword :: EPOCH
2159+ | Keyword :: ISODOW
2160+ | Keyword :: ISOYEAR
2161+ | Keyword :: JULIAN
2162+ | Keyword :: MICROSECOND
2163+ | Keyword :: MICROSECONDS
2164+ | Keyword :: MILLENIUM
2165+ | Keyword :: MILLENNIUM
2166+ | Keyword :: MILLISECOND
2167+ | Keyword :: MILLISECONDS
2168+ | Keyword :: NANOSECOND
2169+ | Keyword :: NANOSECONDS
2170+ | Keyword :: QUARTER
2171+ | Keyword :: TIMEZONE
2172+ | Keyword :: TIMEZONE_HOUR
2173+ | Keyword :: TIMEZONE_MINUTE
2174+ )
2175+ } else {
2176+ false
2177+ }
2178+ }
2179+
21952180 /// Bigquery specific: Parse a struct literal
21962181 /// Syntax
21972182 /// ```sql
0 commit comments