@@ -38,6 +38,7 @@ use crate::ast::*;
38
38
use crate::dialect::*;
39
39
use crate::keywords::{Keyword, ALL_KEYWORDS};
40
40
use crate::tokenizer::*;
41
+ use sqlparser::parser::ParserState::ColumnDefinition;
41
42
42
43
mod alter;
43
44
@@ -275,6 +276,12 @@ enum ParserState {
275
276
/// PRIOR expressions while still allowing prior as an identifier name
276
277
/// in other contexts.
277
278
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,
278
285
}
279
286
280
287
/// A SQL Parser
@@ -3578,6 +3585,11 @@ impl<'a> Parser<'a> {
3578
3585
let negated = self.parse_keyword(Keyword::NOT);
3579
3586
let regexp = self.parse_keyword(Keyword::REGEXP);
3580
3587
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
+ };
3581
3593
if regexp || rlike {
3582
3594
Ok(Expr::RLike {
3583
3595
negated,
@@ -3587,6 +3599,8 @@ impl<'a> Parser<'a> {
3587
3599
),
3588
3600
regexp,
3589
3601
})
3602
+ } else if negated && null {
3603
+ Ok(Expr::IsNotNull(Box::new(expr)))
3590
3604
} else if self.parse_keyword(Keyword::IN) {
3591
3605
self.parse_in(expr, negated)
3592
3606
} else if self.parse_keyword(Keyword::BETWEEN) {
@@ -3624,6 +3638,9 @@ impl<'a> Parser<'a> {
3624
3638
self.expected("IN or BETWEEN after NOT", self.peek_token())
3625
3639
}
3626
3640
}
3641
+ Keyword::NOTNULL if dialect.supports_notnull_operator() => {
3642
+ Ok(Expr::IsNotNull(Box::new(expr)))
3643
+ }
3627
3644
Keyword::MEMBER => {
3628
3645
if self.parse_keyword(Keyword::OF) {
3629
3646
self.expect_token(&Token::LParen)?;
@@ -7742,6 +7759,15 @@ impl<'a> Parser<'a> {
7742
7759
return option;
7743
7760
}
7744
7761
7762
+ self.with_state(
7763
+ ColumnDefinition,
7764
+ |parser| -> Result<Option<ColumnOption>, ParserError> {
7765
+ parser.parse_optional_column_option_inner()
7766
+ },
7767
+ )
7768
+ }
7769
+
7770
+ fn parse_optional_column_option_inner(&mut self) -> Result<Option<ColumnOption>, ParserError> {
7745
7771
if self.parse_keywords(&[Keyword::CHARACTER, Keyword::SET]) {
7746
7772
Ok(Some(ColumnOption::CharacterSet(
7747
7773
self.parse_object_name(false)?,
@@ -7757,15 +7783,19 @@ impl<'a> Parser<'a> {
7757
7783
} else if self.parse_keyword(Keyword::NULL) {
7758
7784
Ok(Some(ColumnOption::Null))
7759
7785
} else if self.parse_keyword(Keyword::DEFAULT) {
7760
- Ok(Some(ColumnOption::Default(self.parse_expr()?)))
7786
+ Ok(Some(ColumnOption::Default(
7787
+ self.parse_column_option_expr()?,
7788
+ )))
7761
7789
} else if dialect_of!(self is ClickHouseDialect| GenericDialect)
7762
7790
&& self.parse_keyword(Keyword::MATERIALIZED)
7763
7791
{
7764
- Ok(Some(ColumnOption::Materialized(self.parse_expr()?)))
7792
+ Ok(Some(ColumnOption::Materialized(
7793
+ self.parse_column_option_expr()?,
7794
+ )))
7765
7795
} else if dialect_of!(self is ClickHouseDialect| GenericDialect)
7766
7796
&& self.parse_keyword(Keyword::ALIAS)
7767
7797
{
7768
- Ok(Some(ColumnOption::Alias(self.parse_expr ()?)))
7798
+ Ok(Some(ColumnOption::Alias(self.parse_column_option_expr ()?)))
7769
7799
} else if dialect_of!(self is ClickHouseDialect| GenericDialect)
7770
7800
&& self.parse_keyword(Keyword::EPHEMERAL)
7771
7801
{
@@ -7774,7 +7804,9 @@ impl<'a> Parser<'a> {
7774
7804
if matches!(self.peek_token().token, Token::Comma | Token::RParen) {
7775
7805
Ok(Some(ColumnOption::Ephemeral(None)))
7776
7806
} else {
7777
- Ok(Some(ColumnOption::Ephemeral(Some(self.parse_expr()?))))
7807
+ Ok(Some(ColumnOption::Ephemeral(Some(
7808
+ self.parse_column_option_expr()?,
7809
+ ))))
7778
7810
}
7779
7811
} else if self.parse_keywords(&[Keyword::PRIMARY, Keyword::KEY]) {
7780
7812
let characteristics = self.parse_constraint_characteristics()?;
@@ -7817,7 +7849,8 @@ impl<'a> Parser<'a> {
7817
7849
}))
7818
7850
} else if self.parse_keyword(Keyword::CHECK) {
7819
7851
self.expect_token(&Token::LParen)?;
7820
- let expr = self.parse_expr()?;
7852
+ // since `CHECK` requires parentheses, we can parse the inner expression in ParserState::Normal
7853
+ let expr: Expr = self.with_state(ParserState::Normal, |p| p.parse_expr())?;
7821
7854
self.expect_token(&Token::RParen)?;
7822
7855
Ok(Some(ColumnOption::Check(expr)))
7823
7856
} else if self.parse_keyword(Keyword::AUTO_INCREMENT)
@@ -7851,7 +7884,7 @@ impl<'a> Parser<'a> {
7851
7884
} else if self.parse_keywords(&[Keyword::ON, Keyword::UPDATE])
7852
7885
&& dialect_of!(self is MySqlDialect | GenericDialect)
7853
7886
{
7854
- let expr = self.parse_expr ()?;
7887
+ let expr = self.parse_column_option_expr ()?;
7855
7888
Ok(Some(ColumnOption::OnUpdate(expr)))
7856
7889
} else if self.parse_keyword(Keyword::GENERATED) {
7857
7890
self.parse_optional_column_option_generated()
@@ -7869,7 +7902,9 @@ impl<'a> Parser<'a> {
7869
7902
} else if self.parse_keyword(Keyword::SRID)
7870
7903
&& dialect_of!(self is MySqlDialect | GenericDialect)
7871
7904
{
7872
- Ok(Some(ColumnOption::Srid(Box::new(self.parse_expr()?))))
7905
+ Ok(Some(ColumnOption::Srid(Box::new(
7906
+ self.parse_column_option_expr()?,
7907
+ ))))
7873
7908
} else if self.parse_keyword(Keyword::IDENTITY)
7874
7909
&& dialect_of!(self is MsSqlDialect | GenericDialect)
7875
7910
{
@@ -7909,6 +7944,31 @@ impl<'a> Parser<'a> {
7909
7944
}
7910
7945
}
7911
7946
7947
+ /// When parsing some column option expressions we need to revert to [ParserState::Normal] since
7948
+ /// `NOT NULL` is allowed as an alias for `IS NOT NULL`.
7949
+ /// In those cases we use this helper instead of calling [Parser::parse_expr] directly.
7950
+ ///
7951
+ /// For example, consider these `CREATE TABLE` statements:
7952
+ /// ```sql
7953
+ /// CREATE TABLE foo (abc BOOL DEFAULT (42 NOT NULL) NOT NULL);
7954
+ /// ```
7955
+ /// vs
7956
+ /// ```sql
7957
+ /// CREATE TABLE foo (abc BOOL NOT NULL);
7958
+ /// ```
7959
+ ///
7960
+ /// In the first we should parse the inner portion of `(42 NOT NULL)` as [Expr::IsNotNull],
7961
+ /// whereas is both statements that trailing `NOT NULL` should only be parsed as a
7962
+ /// [ColumnOption::NotNull].
7963
+ fn parse_column_option_expr(&mut self) -> Result<Expr, ParserError> {
7964
+ if self.peek_token_ref().token == Token::LParen {
7965
+ let expr: Expr = self.with_state(ParserState::Normal, |p| p.parse_prefix())?;
7966
+ Ok(expr)
7967
+ } else {
7968
+ Ok(self.parse_expr()?)
7969
+ }
7970
+ }
7971
+
7912
7972
pub(crate) fn parse_tag(&mut self) -> Result<Tag, ParserError> {
7913
7973
let name = self.parse_object_name(false)?;
7914
7974
self.expect_token(&Token::Eq)?;
@@ -7953,7 +8013,7 @@ impl<'a> Parser<'a> {
7953
8013
}))
7954
8014
} else if self.parse_keywords(&[Keyword::ALWAYS, Keyword::AS]) {
7955
8015
if self.expect_token(&Token::LParen).is_ok() {
7956
- let expr = self.parse_expr()?;
8016
+ let expr: Expr = self.with_state(ParserState::Normal, |p| p. parse_expr() )?;
7957
8017
self.expect_token(&Token::RParen)?;
7958
8018
let (gen_as, expr_mode) = if self.parse_keywords(&[Keyword::STORED]) {
7959
8019
Ok((
@@ -16532,6 +16592,10 @@ impl<'a> Parser<'a> {
16532
16592
Ok(None)
16533
16593
}
16534
16594
}
16595
+
16596
+ pub(crate) fn in_column_definition_state(&self) -> bool {
16597
+ matches!(self.state, ColumnDefinition)
16598
+ }
16535
16599
}
16536
16600
16537
16601
fn maybe_prefixed_expr(expr: Expr, prefix: Option<Ident>) -> Expr {
@@ -17267,4 +17331,28 @@ mod tests {
17267
17331
17268
17332
assert!(Parser::parse_sql(&MySqlDialect {}, sql).is_err());
17269
17333
}
17334
+
17335
+ #[test]
17336
+ fn test_parse_not_null_in_column_options() {
17337
+ let canonical = concat!(
17338
+ "CREATE TABLE foo (",
17339
+ "abc INT DEFAULT (42 IS NOT NULL) NOT NULL,",
17340
+ " def INT,",
17341
+ " def_null BOOL GENERATED ALWAYS AS (def IS NOT NULL) STORED,",
17342
+ " CHECK (abc IS NOT NULL)",
17343
+ ")"
17344
+ );
17345
+ all_dialects().verified_stmt(canonical);
17346
+ all_dialects().one_statement_parses_to(
17347
+ concat!(
17348
+ "CREATE TABLE foo (",
17349
+ "abc INT DEFAULT (42 NOT NULL) NOT NULL,",
17350
+ " def INT,",
17351
+ " def_null BOOL GENERATED ALWAYS AS (def NOT NULL) STORED,",
17352
+ " CHECK (abc NOT NULL)",
17353
+ ")"
17354
+ ),
17355
+ canonical,
17356
+ );
17357
+ }
17270
17358
}
0 commit comments