diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 8d920b2ce..e2f4dd508 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -7411,6 +7411,7 @@ impl<'a> Parser<'a> { } } + /// Parse an unsigned numeric literal pub fn parse_number_value(&mut self) -> Result { match self.parse_value()? { v @ Value::Number(_, _) => Ok(v), @@ -7422,6 +7423,26 @@ impl<'a> Parser<'a> { } } + /// Parse a numeric literal as an expression. Returns a [`Expr::UnaryOp`] if the number is signed, + /// otherwise returns a [`Expr::Value`] + pub fn parse_number(&mut self) -> Result { + let next_token = self.next_token(); + match next_token.token { + Token::Plus => Ok(Expr::UnaryOp { + op: UnaryOperator::Plus, + expr: Box::new(Expr::Value(self.parse_number_value()?)), + }), + Token::Minus => Ok(Expr::UnaryOp { + op: UnaryOperator::Minus, + expr: Box::new(Expr::Value(self.parse_number_value()?)), + }), + _ => { + self.prev_token(); + Ok(Expr::Value(self.parse_number_value()?)) + } + } + } + fn parse_introduced_string_value(&mut self) -> Result { let next_token = self.next_token(); let location = next_token.location; @@ -11741,30 +11762,20 @@ impl<'a> Parser<'a> { //[ INCREMENT [ BY ] increment ] if self.parse_keywords(&[Keyword::INCREMENT]) { if self.parse_keywords(&[Keyword::BY]) { - sequence_options.push(SequenceOptions::IncrementBy( - Expr::Value(self.parse_number_value()?), - true, - )); + sequence_options.push(SequenceOptions::IncrementBy(self.parse_number()?, true)); } else { - sequence_options.push(SequenceOptions::IncrementBy( - Expr::Value(self.parse_number_value()?), - false, - )); + sequence_options.push(SequenceOptions::IncrementBy(self.parse_number()?, false)); } } //[ MINVALUE minvalue | NO MINVALUE ] if self.parse_keyword(Keyword::MINVALUE) { - sequence_options.push(SequenceOptions::MinValue(Some(Expr::Value( - self.parse_number_value()?, - )))); + sequence_options.push(SequenceOptions::MinValue(Some(self.parse_number()?))); } else if self.parse_keywords(&[Keyword::NO, Keyword::MINVALUE]) { sequence_options.push(SequenceOptions::MinValue(None)); } //[ MAXVALUE maxvalue | NO MAXVALUE ] if self.parse_keywords(&[Keyword::MAXVALUE]) { - sequence_options.push(SequenceOptions::MaxValue(Some(Expr::Value( - self.parse_number_value()?, - )))); + sequence_options.push(SequenceOptions::MaxValue(Some(self.parse_number()?))); } else if self.parse_keywords(&[Keyword::NO, Keyword::MAXVALUE]) { sequence_options.push(SequenceOptions::MaxValue(None)); } @@ -11772,22 +11783,14 @@ impl<'a> Parser<'a> { //[ START [ WITH ] start ] if self.parse_keywords(&[Keyword::START]) { if self.parse_keywords(&[Keyword::WITH]) { - sequence_options.push(SequenceOptions::StartWith( - Expr::Value(self.parse_number_value()?), - true, - )); + sequence_options.push(SequenceOptions::StartWith(self.parse_number()?, true)); } else { - sequence_options.push(SequenceOptions::StartWith( - Expr::Value(self.parse_number_value()?), - false, - )); + sequence_options.push(SequenceOptions::StartWith(self.parse_number()?, false)); } } //[ CACHE cache ] if self.parse_keywords(&[Keyword::CACHE]) { - sequence_options.push(SequenceOptions::Cache(Expr::Value( - self.parse_number_value()?, - ))); + sequence_options.push(SequenceOptions::Cache(self.parse_number()?)); } // [ [ NO ] CYCLE ] if self.parse_keywords(&[Keyword::NO, Keyword::CYCLE]) { diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index ff45d7b6e..5525650f2 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -2819,6 +2819,18 @@ fn parse_window_function_null_treatment_arg() { ); } +#[test] +fn parse_negative_value() { + let sql1 = "SELECT -1"; + one_statement_parses_to(sql1, "SELECT -1"); + + let sql2 = "CREATE SEQUENCE name INCREMENT -10 MINVALUE -1000 MAXVALUE 15 START -100;"; + one_statement_parses_to( + sql2, + "CREATE SEQUENCE name INCREMENT -10 MINVALUE -1000 MAXVALUE 15 START -100", + ); +} + #[test] fn parse_create_table() { let sql = "CREATE TABLE uk_cities (\ diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index ec1311f2c..91d365692 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -277,6 +277,26 @@ fn parse_create_sequence() { "CREATE TEMPORARY SEQUENCE IF NOT EXISTS name3 INCREMENT 1 NO MINVALUE MAXVALUE 20 OWNED BY NONE", ); + let sql7 = "CREATE SEQUENCE name4 + AS BIGINT + INCREMENT -15 + MINVALUE - 2000 MAXVALUE -50 + START WITH - 60"; + pg().one_statement_parses_to( + sql7, + "CREATE SEQUENCE name4 AS BIGINT INCREMENT -15 MINVALUE -2000 MAXVALUE -50 START WITH -60", + ); + + let sql8 = "CREATE SEQUENCE name5 + AS BIGINT + INCREMENT +10 + MINVALUE + 30 MAXVALUE +5000 + START WITH + 45"; + pg().one_statement_parses_to( + sql8, + "CREATE SEQUENCE name5 AS BIGINT INCREMENT +10 MINVALUE +30 MAXVALUE +5000 START WITH +45", + ); + assert!(matches!( pg().parse_sql_statements("CREATE SEQUENCE foo INCREMENT 1 NO MINVALUE NO"), Err(ParserError::ParserError(_))