Skip to content

Commit 7f746c5

Browse files
committed
New approach to handle at parenthesis boundary
1 parent 2f20af6 commit 7f746c5

3 files changed

Lines changed: 20 additions & 54 deletions

File tree

src/parser/mod.rs

Lines changed: 14 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1818,7 +1818,14 @@ impl<'a> Parser<'a> {
18181818
} else if let Some(lambda) = self.try_parse_lambda()? {
18191819
return Ok(lambda);
18201820
} else {
1821-
let exprs = self.parse_comma_separated(Parser::parse_expr)?;
1821+
// Parentheses create a normal expression context.
1822+
// This ensures that e.g. `NOT NULL` inside parens is parsed
1823+
// as `IS NOT NULL` (for dialects that support it), while
1824+
// `NOT NULL` outside parens in a column definition context
1825+
// remains a column constraint.
1826+
let exprs = self.with_state(ParserState::Normal, |p| {
1827+
p.parse_comma_separated(Parser::parse_expr)
1828+
})?;
18221829
match exprs.len() {
18231830
0 => return Err(ParserError::ParserError(
18241831
"Internal parser error: parse_comma_separated returned empty list"
@@ -8786,19 +8793,15 @@ impl<'a> Parser<'a> {
87868793
} else if self.parse_keyword(Keyword::NULL) {
87878794
Ok(Some(ColumnOption::Null))
87888795
} else if self.parse_keyword(Keyword::DEFAULT) {
8789-
Ok(Some(ColumnOption::Default(
8790-
self.parse_column_option_expr()?,
8791-
)))
8796+
Ok(Some(ColumnOption::Default(self.parse_expr()?)))
87928797
} else if dialect_of!(self is ClickHouseDialect| GenericDialect)
87938798
&& self.parse_keyword(Keyword::MATERIALIZED)
87948799
{
8795-
Ok(Some(ColumnOption::Materialized(
8796-
self.parse_column_option_expr()?,
8797-
)))
8800+
Ok(Some(ColumnOption::Materialized(self.parse_expr()?)))
87988801
} else if dialect_of!(self is ClickHouseDialect| GenericDialect)
87998802
&& self.parse_keyword(Keyword::ALIAS)
88008803
{
8801-
Ok(Some(ColumnOption::Alias(self.parse_column_option_expr()?)))
8804+
Ok(Some(ColumnOption::Alias(self.parse_expr()?)))
88028805
} else if dialect_of!(self is ClickHouseDialect| GenericDialect)
88038806
&& self.parse_keyword(Keyword::EPHEMERAL)
88048807
{
@@ -8807,9 +8810,7 @@ impl<'a> Parser<'a> {
88078810
if matches!(self.peek_token().token, Token::Comma | Token::RParen) {
88088811
Ok(Some(ColumnOption::Ephemeral(None)))
88098812
} else {
8810-
Ok(Some(ColumnOption::Ephemeral(Some(
8811-
self.parse_column_option_expr()?,
8812-
))))
8813+
Ok(Some(ColumnOption::Ephemeral(Some(self.parse_expr()?))))
88138814
}
88148815
} else if self.parse_keywords(&[Keyword::PRIMARY, Keyword::KEY]) {
88158816
let characteristics = self.parse_constraint_characteristics()?;
@@ -8922,7 +8923,7 @@ impl<'a> Parser<'a> {
89228923
} else if self.parse_keywords(&[Keyword::ON, Keyword::UPDATE])
89238924
&& dialect_of!(self is MySqlDialect | GenericDialect)
89248925
{
8925-
let expr = self.parse_column_option_expr()?;
8926+
let expr = self.parse_expr()?;
89268927
Ok(Some(ColumnOption::OnUpdate(expr)))
89278928
} else if self.parse_keyword(Keyword::GENERATED) {
89288929
self.parse_optional_column_option_generated()
@@ -8940,9 +8941,7 @@ impl<'a> Parser<'a> {
89408941
} else if self.parse_keyword(Keyword::SRID)
89418942
&& dialect_of!(self is MySqlDialect | GenericDialect)
89428943
{
8943-
Ok(Some(ColumnOption::Srid(Box::new(
8944-
self.parse_column_option_expr()?,
8945-
))))
8944+
Ok(Some(ColumnOption::Srid(Box::new(self.parse_expr()?))))
89468945
} else if self.parse_keyword(Keyword::IDENTITY)
89478946
&& dialect_of!(self is MsSqlDialect | GenericDialect)
89488947
{
@@ -8984,39 +8983,6 @@ impl<'a> Parser<'a> {
89848983
}
89858984
}
89868985

8987-
/// When parsing some column option expressions we need to revert to [ParserState::Normal] since
8988-
/// `NOT NULL` is allowed as an alias for `IS NOT NULL`.
8989-
/// In those cases we use this helper instead of calling [Parser::parse_expr] directly.
8990-
///
8991-
/// For example, consider these `CREATE TABLE` statements:
8992-
/// ```sql
8993-
/// CREATE TABLE foo (abc BOOL DEFAULT (42 NOT NULL) NOT NULL);
8994-
/// ```
8995-
/// vs
8996-
/// ```sql
8997-
/// CREATE TABLE foo (abc BOOL NOT NULL);
8998-
/// ```
8999-
///
9000-
/// In the first we should parse the inner portion of `(42 NOT NULL)` as [Expr::IsNotNull],
9001-
/// whereas is both statements that trailing `NOT NULL` should only be parsed as a
9002-
/// [ColumnOption::NotNull].
9003-
fn parse_column_option_expr(&mut self) -> Result<Expr, ParserError> {
9004-
if self.peek_token_ref().token == Token::LParen {
9005-
let mut expr = self.with_state(ParserState::Normal, |p| p.parse_prefix())?;
9006-
expr = self.parse_compound_expr(expr, vec![])?;
9007-
loop {
9008-
let next_precedence = self.get_next_precedence()?;
9009-
if next_precedence == 0 || self.peek_token_ref().token == Token::Period {
9010-
break;
9011-
}
9012-
expr = self.parse_infix(expr, next_precedence)?;
9013-
}
9014-
Ok(expr)
9015-
} else {
9016-
Ok(self.parse_expr()?)
9017-
}
9018-
}
9019-
90208986
pub(crate) fn parse_tag(&mut self) -> Result<Tag, ParserError> {
90218987
let name = self.parse_object_name(false)?;
90228988
self.expect_token(&Token::Eq)?;

tests/sqlparser_common.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17302,6 +17302,11 @@ fn test_parse_not_null_in_column_options() {
1730217302
);
1730317303
}
1730417304

17305+
#[test]
17306+
fn test_parse_default_expr_with_operators() {
17307+
all_dialects().verified_stmt("CREATE TABLE t (c INT DEFAULT (1 + 2) + 3)");
17308+
}
17309+
1730517310
#[test]
1730617311
fn test_parse_default_with_collate_column_option() {
1730717312
let sql = "CREATE TABLE foo (abc TEXT DEFAULT 'foo' COLLATE 'en_US')";

tests/sqlparser_postgres.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -513,14 +513,9 @@ fn parse_create_table_with_defaults() {
513513
}
514514

515515
#[test]
516-
fn parse_infix_after_parenthesized_column_option() {
517-
// Cast
516+
fn parse_cast_in_default_expr() {
518517
pg().verified_stmt("CREATE TABLE t (c TEXT DEFAULT (foo())::TEXT)");
519-
// Chained casts
520518
pg().verified_stmt("CREATE TABLE t (c TEXT DEFAULT (foo())::INT::TEXT)");
521-
// Other infix operators
522-
pg().verified_stmt("CREATE TABLE t (c INT DEFAULT (foo()) + 1)");
523-
// Cast with NOT NULL constraint
524519
pg().verified_stmt("CREATE TABLE t (c TEXT DEFAULT (foo())::TEXT NOT NULL)");
525520
}
526521

0 commit comments

Comments
 (0)