Skip to content

Commit

Permalink
Fix parsing of negative values (#1419)
Browse files Browse the repository at this point in the history
Co-authored-by: Agaev Huseyn <h.agaev@vkteam.ru>
  • Loading branch information
agscpp and Agaev Huseyn authored Sep 16, 2024
1 parent b9f6784 commit 246838a
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 25 deletions.
53 changes: 28 additions & 25 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7411,6 +7411,7 @@ impl<'a> Parser<'a> {
}
}

/// Parse an unsigned numeric literal
pub fn parse_number_value(&mut self) -> Result<Value, ParserError> {
match self.parse_value()? {
v @ Value::Number(_, _) => Ok(v),
Expand All @@ -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<Expr, ParserError> {
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<Value, ParserError> {
let next_token = self.next_token();
let location = next_token.location;
Expand Down Expand Up @@ -11741,53 +11762,35 @@ 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));
}

//[ 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]) {
Expand Down
12 changes: 12 additions & 0 deletions tests/sqlparser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 (\
Expand Down
20 changes: 20 additions & 0 deletions tests/sqlparser_postgres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(_))
Expand Down

0 comments on commit 246838a

Please sign in to comment.