From a0873caced61afd4402e71c9f89cf5d98e419a82 Mon Sep 17 00:00:00 2001 From: Agaev Huseyn Date: Mon, 9 Sep 2024 14:01:23 +0300 Subject: [PATCH 1/6] Fix parsing of negative values --- src/parser/mod.rs | 10 ++++++++++ tests/sqlparser_postgres.rs | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 413f5a690..d05c097f7 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -7274,6 +7274,16 @@ impl<'a> Parser<'a> { let placeholder = tok.to_string() + &ident.value; Ok(Value::Placeholder(placeholder)) } + tok @ Token::Minus => { + let next_token = self.next_token(); + match next_token.token { + Token::Number(n, l) => Ok(Value::Number( + Self::parse::(tok.to_string() + &n, location)?, + l, + )), + _ => self.expected("number", next_token), + } + } unexpected => self.expected( "a value", TokenWithLocation { diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 1ebb5d54c..ecd47616b 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -277,6 +277,16 @@ 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 -10 + MINVALUE - 2000 MAXVALUE -5 + START WITH - 20"; + pg().one_statement_parses_to( + sql7, + "CREATE SEQUENCE name4 AS BIGINT INCREMENT -10 MINVALUE -2000 MAXVALUE -5 START WITH -20", + ); + assert!(matches!( pg().parse_sql_statements("CREATE SEQUENCE foo INCREMENT 1 NO MINVALUE NO"), Err(ParserError::ParserError(_)) From 216d72167cc6a0202077ec905db259446dd383a3 Mon Sep 17 00:00:00 2001 From: Agaev Huseyn Date: Tue, 10 Sep 2024 14:23:20 +0300 Subject: [PATCH 2/6] Move tests to a common module and add a handler for '+' --- src/parser/mod.rs | 2 +- tests/sqlparser_common.rs | 23 +++++++++++++++++++++++ tests/sqlparser_postgres.rs | 10 ---------- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index d05c097f7..664688cc1 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -7274,7 +7274,7 @@ impl<'a> Parser<'a> { let placeholder = tok.to_string() + &ident.value; Ok(Value::Placeholder(placeholder)) } - tok @ Token::Minus => { + tok @ Token::Minus | tok @ Token::Plus => { let next_token = self.next_token(); match next_token.token { Token::Number(n, l) => Ok(Value::Number( diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 0f7a88d74..183729ba0 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -2819,6 +2819,29 @@ fn parse_window_function_null_treatment_arg() { ); } +#[test] +fn parse_signed_value() { + let sql1 = "CREATE SEQUENCE name1 + AS BIGINT + INCREMENT -15 + MINVALUE - 2000 MAXVALUE -50 + START WITH - 60"; + one_statement_parses_to( + sql1, + "CREATE SEQUENCE name1 AS BIGINT INCREMENT -15 MINVALUE -2000 MAXVALUE -50 START WITH -60", + ); + + let sql2 = "CREATE SEQUENCE name2 + AS BIGINT + INCREMENT +10 + MINVALUE + 30 MAXVALUE +5000 + START WITH + 45"; + one_statement_parses_to( + sql2, + "CREATE SEQUENCE name2 AS BIGINT INCREMENT +10 MINVALUE +30 MAXVALUE +5000 START WITH +45", + ); +} + #[test] fn parse_create_table() { let sql = "CREATE TABLE uk_cities (\ diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index ecd47616b..1ebb5d54c 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -277,16 +277,6 @@ 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 -10 - MINVALUE - 2000 MAXVALUE -5 - START WITH - 20"; - pg().one_statement_parses_to( - sql7, - "CREATE SEQUENCE name4 AS BIGINT INCREMENT -10 MINVALUE -2000 MAXVALUE -5 START WITH -20", - ); - assert!(matches!( pg().parse_sql_statements("CREATE SEQUENCE foo INCREMENT 1 NO MINVALUE NO"), Err(ParserError::ParserError(_)) From 99b98ca86cf0591a89a644e06742758a70aa04ea Mon Sep 17 00:00:00 2001 From: Agaev Huseyn Date: Tue, 10 Sep 2024 15:37:00 +0300 Subject: [PATCH 3/6] Fix parser for BigDecimal values --- src/parser/mod.rs | 14 ++++++++++---- tests/sqlparser_common.rs | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 664688cc1..0e4bfc5bf 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -7277,10 +7277,16 @@ impl<'a> Parser<'a> { tok @ Token::Minus | tok @ Token::Plus => { let next_token = self.next_token(); match next_token.token { - Token::Number(n, l) => Ok(Value::Number( - Self::parse::(tok.to_string() + &n, location)?, - l, - )), + Token::Number(n, l) => { + if tok == Token::Minus { + Ok(Value::Number( + Self::parse(tok.to_string() + &n, location)?, + l, + )) + } else { + Ok(Value::Number(Self::parse(n, location)?, l)) + } + } _ => self.expected("number", next_token), } } diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 183729ba0..592486de6 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -2838,7 +2838,7 @@ fn parse_signed_value() { START WITH + 45"; one_statement_parses_to( sql2, - "CREATE SEQUENCE name2 AS BIGINT INCREMENT +10 MINVALUE +30 MAXVALUE +5000 START WITH +45", + "CREATE SEQUENCE name2 AS BIGINT INCREMENT 10 MINVALUE 30 MAXVALUE 5000 START WITH 45", ); } From accee6d70a6155b76e66a77a8c977abb74c3bee4 Mon Sep 17 00:00:00 2001 From: Agaev Huseyn Date: Wed, 11 Sep 2024 13:39:02 +0300 Subject: [PATCH 4/6] Add new tests --- tests/sqlparser_common.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 592486de6..4a4ecbc24 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -2840,6 +2840,15 @@ fn parse_signed_value() { sql2, "CREATE SEQUENCE name2 AS BIGINT INCREMENT 10 MINVALUE 30 MAXVALUE 5000 START WITH 45", ); + + let sql3 = "CREATE SEQUENCE name3 INCREMENT -10 MINVALUE -1000 MAXVALUE 1 START -100;"; + one_statement_parses_to( + sql3, + "CREATE SEQUENCE name3 INCREMENT -10 MINVALUE -1000 MAXVALUE 1 START -100", + ); + + let sql4 = "SELECT -1"; + one_statement_parses_to(sql4, "SELECT -1"); } #[test] From 4eef71beea79a11b568eb9693b816d19eaec26dc Mon Sep 17 00:00:00 2001 From: Agaev Huseyn Date: Wed, 11 Sep 2024 15:34:00 +0300 Subject: [PATCH 5/6] Fix parsing of negative values --- src/parser/mod.rs | 61 +++++++++++++++++++------------------ tests/sqlparser_common.rs | 30 +++--------------- tests/sqlparser_postgres.rs | 20 ++++++++++++ 3 files changed, 57 insertions(+), 54 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 0e4bfc5bf..d6e1f50f3 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -7274,22 +7274,6 @@ impl<'a> Parser<'a> { let placeholder = tok.to_string() + &ident.value; Ok(Value::Placeholder(placeholder)) } - tok @ Token::Minus | tok @ Token::Plus => { - let next_token = self.next_token(); - match next_token.token { - Token::Number(n, l) => { - if tok == Token::Minus { - Ok(Value::Number( - Self::parse(tok.to_string() + &n, location)?, - l, - )) - } else { - Ok(Value::Number(Self::parse(n, location)?, l)) - } - } - _ => self.expected("number", next_token), - } - } unexpected => self.expected( "a value", TokenWithLocation { @@ -7300,6 +7284,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), @@ -7311,6 +7296,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_value_with_sign(&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; @@ -11625,29 +11630,29 @@ impl<'a> Parser<'a> { if self.parse_keywords(&[Keyword::INCREMENT]) { if self.parse_keywords(&[Keyword::BY]) { sequence_options.push(SequenceOptions::IncrementBy( - Expr::Value(self.parse_number_value()?), + self.parse_number_value_with_sign()?, true, )); } else { sequence_options.push(SequenceOptions::IncrementBy( - Expr::Value(self.parse_number_value()?), + self.parse_number_value_with_sign()?, 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_value_with_sign()?, + ))); } 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_value_with_sign()?, + ))); } else if self.parse_keywords(&[Keyword::NO, Keyword::MAXVALUE]) { sequence_options.push(SequenceOptions::MaxValue(None)); } @@ -11656,21 +11661,19 @@ impl<'a> Parser<'a> { if self.parse_keywords(&[Keyword::START]) { if self.parse_keywords(&[Keyword::WITH]) { sequence_options.push(SequenceOptions::StartWith( - Expr::Value(self.parse_number_value()?), + self.parse_number_value_with_sign()?, true, )); } else { sequence_options.push(SequenceOptions::StartWith( - Expr::Value(self.parse_number_value()?), + self.parse_number_value_with_sign()?, 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_value_with_sign()?)); } // [ [ NO ] CYCLE ] if self.parse_keywords(&[Keyword::NO, Keyword::CYCLE]) { diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 4a4ecbc24..6aca4b47c 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -2820,35 +2820,15 @@ fn parse_window_function_null_treatment_arg() { } #[test] -fn parse_signed_value() { - let sql1 = "CREATE SEQUENCE name1 - AS BIGINT - INCREMENT -15 - MINVALUE - 2000 MAXVALUE -50 - START WITH - 60"; - one_statement_parses_to( - sql1, - "CREATE SEQUENCE name1 AS BIGINT INCREMENT -15 MINVALUE -2000 MAXVALUE -50 START WITH -60", - ); +fn parse_negative_value() { + let sql1 = "SELECT -1"; + one_statement_parses_to(sql1, "SELECT -1"); - let sql2 = "CREATE SEQUENCE name2 - AS BIGINT - INCREMENT +10 - MINVALUE + 30 MAXVALUE +5000 - START WITH + 45"; + let sql2 = "CREATE SEQUENCE name INCREMENT -10 MINVALUE -1000 MAXVALUE 15 START -100;"; one_statement_parses_to( sql2, - "CREATE SEQUENCE name2 AS BIGINT INCREMENT 10 MINVALUE 30 MAXVALUE 5000 START WITH 45", - ); - - let sql3 = "CREATE SEQUENCE name3 INCREMENT -10 MINVALUE -1000 MAXVALUE 1 START -100;"; - one_statement_parses_to( - sql3, - "CREATE SEQUENCE name3 INCREMENT -10 MINVALUE -1000 MAXVALUE 1 START -100", + "CREATE SEQUENCE name INCREMENT -10 MINVALUE -1000 MAXVALUE 15 START -100", ); - - let sql4 = "SELECT -1"; - one_statement_parses_to(sql4, "SELECT -1"); } #[test] diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 1ebb5d54c..623577e62 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(_)) From 826fb60ec10634fe703f83bf8580335f4da4f157 Mon Sep 17 00:00:00 2001 From: Agaev Huseyn Date: Mon, 16 Sep 2024 13:22:00 +0300 Subject: [PATCH 6/6] Fix function name --- src/parser/mod.rs | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index d6e1f50f3..97129ced5 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -7298,7 +7298,7 @@ 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_value_with_sign(&mut self) -> Result { + pub fn parse_number(&mut self) -> Result { let next_token = self.next_token(); match next_token.token { Token::Plus => Ok(Expr::UnaryOp { @@ -11629,30 +11629,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( - self.parse_number_value_with_sign()?, - true, - )); + sequence_options.push(SequenceOptions::IncrementBy(self.parse_number()?, true)); } else { - sequence_options.push(SequenceOptions::IncrementBy( - self.parse_number_value_with_sign()?, - 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( - self.parse_number_value_with_sign()?, - ))); + 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( - self.parse_number_value_with_sign()?, - ))); + sequence_options.push(SequenceOptions::MaxValue(Some(self.parse_number()?))); } else if self.parse_keywords(&[Keyword::NO, Keyword::MAXVALUE]) { sequence_options.push(SequenceOptions::MaxValue(None)); } @@ -11660,20 +11650,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( - self.parse_number_value_with_sign()?, - true, - )); + sequence_options.push(SequenceOptions::StartWith(self.parse_number()?, true)); } else { - sequence_options.push(SequenceOptions::StartWith( - self.parse_number_value_with_sign()?, - false, - )); + sequence_options.push(SequenceOptions::StartWith(self.parse_number()?, false)); } } //[ CACHE cache ] if self.parse_keywords(&[Keyword::CACHE]) { - sequence_options.push(SequenceOptions::Cache(self.parse_number_value_with_sign()?)); + sequence_options.push(SequenceOptions::Cache(self.parse_number()?)); } // [ [ NO ] CYCLE ] if self.parse_keywords(&[Keyword::NO, Keyword::CYCLE]) {