@@ -38,6 +38,7 @@ use crate::ast::*;
3838use crate::dialect::*;
3939use crate::keywords::{Keyword, ALL_KEYWORDS};
4040use crate::tokenizer::*;
41+ use sqlparser::parser::ParserState::ColumnDefinition;
4142
4243mod alter;
4344
@@ -275,6 +276,12 @@ enum ParserState {
275276 /// PRIOR expressions while still allowing prior as an identifier name
276277 /// in other contexts.
277278 ConnectBy,
279+ /// The state when parsing column definitions. This state prohibits
280+ /// NOT NULL as an alias for IS NOT NULL. For example:
281+ /// ```sql
282+ /// CREATE TABLE foo (abc BIGINT NOT NULL);
283+ /// ```
284+ ColumnDefinition,
278285}
279286
280287/// A SQL Parser
@@ -3578,6 +3585,11 @@ impl<'a> Parser<'a> {
35783585 let negated = self.parse_keyword(Keyword::NOT);
35793586 let regexp = self.parse_keyword(Keyword::REGEXP);
35803587 let rlike = self.parse_keyword(Keyword::RLIKE);
3588+ let null = if !self.in_column_definition_state() {
3589+ self.parse_keyword(Keyword::NULL)
3590+ } else {
3591+ false
3592+ };
35813593 if regexp || rlike {
35823594 Ok(Expr::RLike {
35833595 negated,
@@ -3587,6 +3599,8 @@ impl<'a> Parser<'a> {
35873599 ),
35883600 regexp,
35893601 })
3602+ } else if negated && null {
3603+ Ok(Expr::IsNotNull(Box::new(expr)))
35903604 } else if self.parse_keyword(Keyword::IN) {
35913605 self.parse_in(expr, negated)
35923606 } else if self.parse_keyword(Keyword::BETWEEN) {
@@ -3624,6 +3638,9 @@ impl<'a> Parser<'a> {
36243638 self.expected("IN or BETWEEN after NOT", self.peek_token())
36253639 }
36263640 }
3641+ Keyword::NOTNULL if dialect.supports_notnull_operator() => {
3642+ Ok(Expr::IsNotNull(Box::new(expr)))
3643+ }
36273644 Keyword::MEMBER => {
36283645 if self.parse_keyword(Keyword::OF) {
36293646 self.expect_token(&Token::LParen)?;
@@ -7773,6 +7790,15 @@ impl<'a> Parser<'a> {
77737790 return option;
77747791 }
77757792
7793+ self.with_state(
7794+ ColumnDefinition,
7795+ |parser| -> Result<Option<ColumnOption>, ParserError> {
7796+ parser.parse_optional_column_option_inner()
7797+ },
7798+ )
7799+ }
7800+
7801+ fn parse_optional_column_option_inner(&mut self) -> Result<Option<ColumnOption>, ParserError> {
77767802 if self.parse_keywords(&[Keyword::CHARACTER, Keyword::SET]) {
77777803 Ok(Some(ColumnOption::CharacterSet(
77787804 self.parse_object_name(false)?,
@@ -7788,15 +7814,19 @@ impl<'a> Parser<'a> {
77887814 } else if self.parse_keyword(Keyword::NULL) {
77897815 Ok(Some(ColumnOption::Null))
77907816 } else if self.parse_keyword(Keyword::DEFAULT) {
7791- Ok(Some(ColumnOption::Default(self.parse_expr()?)))
7817+ Ok(Some(ColumnOption::Default(
7818+ self.parse_column_option_expr()?,
7819+ )))
77927820 } else if dialect_of!(self is ClickHouseDialect| GenericDialect)
77937821 && self.parse_keyword(Keyword::MATERIALIZED)
77947822 {
7795- Ok(Some(ColumnOption::Materialized(self.parse_expr()?)))
7823+ Ok(Some(ColumnOption::Materialized(
7824+ self.parse_column_option_expr()?,
7825+ )))
77967826 } else if dialect_of!(self is ClickHouseDialect| GenericDialect)
77977827 && self.parse_keyword(Keyword::ALIAS)
77987828 {
7799- Ok(Some(ColumnOption::Alias(self.parse_expr ()?)))
7829+ Ok(Some(ColumnOption::Alias(self.parse_column_option_expr ()?)))
78007830 } else if dialect_of!(self is ClickHouseDialect| GenericDialect)
78017831 && self.parse_keyword(Keyword::EPHEMERAL)
78027832 {
@@ -7805,7 +7835,9 @@ impl<'a> Parser<'a> {
78057835 if matches!(self.peek_token().token, Token::Comma | Token::RParen) {
78067836 Ok(Some(ColumnOption::Ephemeral(None)))
78077837 } else {
7808- Ok(Some(ColumnOption::Ephemeral(Some(self.parse_expr()?))))
7838+ Ok(Some(ColumnOption::Ephemeral(Some(
7839+ self.parse_column_option_expr()?,
7840+ ))))
78097841 }
78107842 } else if self.parse_keywords(&[Keyword::PRIMARY, Keyword::KEY]) {
78117843 let characteristics = self.parse_constraint_characteristics()?;
@@ -7848,7 +7880,8 @@ impl<'a> Parser<'a> {
78487880 }))
78497881 } else if self.parse_keyword(Keyword::CHECK) {
78507882 self.expect_token(&Token::LParen)?;
7851- let expr = self.parse_expr()?;
7883+ // since `CHECK` requires parentheses, we can parse the inner expression in ParserState::Normal
7884+ let expr: Expr = self.with_state(ParserState::Normal, |p| p.parse_expr())?;
78527885 self.expect_token(&Token::RParen)?;
78537886 Ok(Some(ColumnOption::Check(expr)))
78547887 } else if self.parse_keyword(Keyword::AUTO_INCREMENT)
@@ -7882,7 +7915,7 @@ impl<'a> Parser<'a> {
78827915 } else if self.parse_keywords(&[Keyword::ON, Keyword::UPDATE])
78837916 && dialect_of!(self is MySqlDialect | GenericDialect)
78847917 {
7885- let expr = self.parse_expr ()?;
7918+ let expr = self.parse_column_option_expr ()?;
78867919 Ok(Some(ColumnOption::OnUpdate(expr)))
78877920 } else if self.parse_keyword(Keyword::GENERATED) {
78887921 self.parse_optional_column_option_generated()
@@ -7900,7 +7933,9 @@ impl<'a> Parser<'a> {
79007933 } else if self.parse_keyword(Keyword::SRID)
79017934 && dialect_of!(self is MySqlDialect | GenericDialect)
79027935 {
7903- Ok(Some(ColumnOption::Srid(Box::new(self.parse_expr()?))))
7936+ Ok(Some(ColumnOption::Srid(Box::new(
7937+ self.parse_column_option_expr()?,
7938+ ))))
79047939 } else if self.parse_keyword(Keyword::IDENTITY)
79057940 && dialect_of!(self is MsSqlDialect | GenericDialect)
79067941 {
@@ -7940,6 +7975,31 @@ impl<'a> Parser<'a> {
79407975 }
79417976 }
79427977
7978+ /// When parsing some column option expressions we need to revert to [ParserState::Normal] since
7979+ /// `NOT NULL` is allowed as an alias for `IS NOT NULL`.
7980+ /// In those cases we use this helper instead of calling [Parser::parse_expr] directly.
7981+ ///
7982+ /// For example, consider these `CREATE TABLE` statements:
7983+ /// ```sql
7984+ /// CREATE TABLE foo (abc BOOL DEFAULT (42 NOT NULL) NOT NULL);
7985+ /// ```
7986+ /// vs
7987+ /// ```sql
7988+ /// CREATE TABLE foo (abc BOOL NOT NULL);
7989+ /// ```
7990+ ///
7991+ /// In the first we should parse the inner portion of `(42 NOT NULL)` as [Expr::IsNotNull],
7992+ /// whereas is both statements that trailing `NOT NULL` should only be parsed as a
7993+ /// [ColumnOption::NotNull].
7994+ fn parse_column_option_expr(&mut self) -> Result<Expr, ParserError> {
7995+ if self.peek_token_ref().token == Token::LParen {
7996+ let expr: Expr = self.with_state(ParserState::Normal, |p| p.parse_prefix())?;
7997+ Ok(expr)
7998+ } else {
7999+ Ok(self.parse_expr()?)
8000+ }
8001+ }
8002+
79438003 pub(crate) fn parse_tag(&mut self) -> Result<Tag, ParserError> {
79448004 let name = self.parse_object_name(false)?;
79458005 self.expect_token(&Token::Eq)?;
@@ -7984,7 +8044,7 @@ impl<'a> Parser<'a> {
79848044 }))
79858045 } else if self.parse_keywords(&[Keyword::ALWAYS, Keyword::AS]) {
79868046 if self.expect_token(&Token::LParen).is_ok() {
7987- let expr = self.parse_expr()?;
8047+ let expr: Expr = self.with_state(ParserState::Normal, |p| p. parse_expr() )?;
79888048 self.expect_token(&Token::RParen)?;
79898049 let (gen_as, expr_mode) = if self.parse_keywords(&[Keyword::STORED]) {
79908050 Ok((
@@ -16564,6 +16624,10 @@ impl<'a> Parser<'a> {
1656416624 Ok(None)
1656516625 }
1656616626 }
16627+
16628+ pub(crate) fn in_column_definition_state(&self) -> bool {
16629+ matches!(self.state, ColumnDefinition)
16630+ }
1656716631}
1656816632
1656916633fn maybe_prefixed_expr(expr: Expr, prefix: Option<Ident>) -> Expr {
@@ -17299,4 +17363,28 @@ mod tests {
1729917363
1730017364 assert!(Parser::parse_sql(&MySqlDialect {}, sql).is_err());
1730117365 }
17366+
17367+ #[test]
17368+ fn test_parse_not_null_in_column_options() {
17369+ let canonical = concat!(
17370+ "CREATE TABLE foo (",
17371+ "abc INT DEFAULT (42 IS NOT NULL) NOT NULL,",
17372+ " def INT,",
17373+ " def_null BOOL GENERATED ALWAYS AS (def IS NOT NULL) STORED,",
17374+ " CHECK (abc IS NOT NULL)",
17375+ ")"
17376+ );
17377+ all_dialects().verified_stmt(canonical);
17378+ all_dialects().one_statement_parses_to(
17379+ concat!(
17380+ "CREATE TABLE foo (",
17381+ "abc INT DEFAULT (42 NOT NULL) NOT NULL,",
17382+ " def INT,",
17383+ " def_null BOOL GENERATED ALWAYS AS (def NOT NULL) STORED,",
17384+ " CHECK (abc NOT NULL)",
17385+ ")"
17386+ ),
17387+ canonical,
17388+ );
17389+ }
1730217390}
0 commit comments