Skip to content

Commit d3fda44

Browse files
MySQL: [[NOT] ENFORCED] in CHECK constraint
Add support for MySQL's `[[NOT] ENFORCED]` option for CHECK constraints. docs: https://dev.mysql.com/doc/refman/8.4/en/create-table.html
1 parent ff29dd2 commit d3fda44

File tree

5 files changed

+45
-7
lines changed

5 files changed

+45
-7
lines changed

src/ast/ddl.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,10 +1029,13 @@ pub enum TableConstraint {
10291029
on_update: Option<ReferentialAction>,
10301030
characteristics: Option<ConstraintCharacteristics>,
10311031
},
1032-
/// `[ CONSTRAINT <name> ] CHECK (<expr>)`
1032+
/// `[ CONSTRAINT <name> ] CHECK (<expr>) [[NOT] ENFORCED]`
10331033
Check {
10341034
name: Option<Ident>,
10351035
expr: Box<Expr>,
1036+
/// MySQL-specific syntax
1037+
/// https://dev.mysql.com/doc/refman/8.4/en/create-table.html
1038+
enforced: Option<bool>,
10361039
},
10371040
/// MySQLs [index definition][1] for index creation. Not present on ANSI so, for now, the usage
10381041
/// is restricted to MySQL, as no other dialects that support this syntax were found.
@@ -1162,8 +1165,17 @@ impl fmt::Display for TableConstraint {
11621165
}
11631166
Ok(())
11641167
}
1165-
TableConstraint::Check { name, expr } => {
1166-
write!(f, "{}CHECK ({})", display_constraint_name(name), expr)
1168+
TableConstraint::Check {
1169+
name,
1170+
expr,
1171+
enforced,
1172+
} => {
1173+
write!(f, "{}CHECK ({})", display_constraint_name(name), expr)?;
1174+
if let Some(b) = enforced {
1175+
write!(f, " {}", if *b { "ENFORCED" } else { "NOT ENFORCED" })
1176+
} else {
1177+
Ok(())
1178+
}
11671179
}
11681180
TableConstraint::Index {
11691181
display_as_key,

src/ast/spans.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -687,9 +687,11 @@ impl Spanned for TableConstraint {
687687
.chain(on_update.iter().map(|i| i.span()))
688688
.chain(characteristics.iter().map(|i| i.span())),
689689
),
690-
TableConstraint::Check { name, expr } => {
691-
expr.span().union_opt(&name.as_ref().map(|i| i.span))
692-
}
690+
TableConstraint::Check {
691+
name,
692+
expr,
693+
enforced: _,
694+
} => expr.span().union_opt(&name.as_ref().map(|i| i.span)),
693695
TableConstraint::Index {
694696
display_as_key: _,
695697
name,

src/parser/mod.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8139,7 +8139,19 @@ impl<'a> Parser<'a> {
81398139
self.expect_token(&Token::LParen)?;
81408140
let expr = Box::new(self.parse_expr()?);
81418141
self.expect_token(&Token::RParen)?;
8142-
Ok(Some(TableConstraint::Check { name, expr }))
8142+
8143+
let enforced = match dialect_of!(self is GenericDialect | MySqlDialect) {
8144+
true if self.parse_keywords(&[Keyword::NOT, Keyword::ENFORCED]) => Some(false),
8145+
true if self.parse_keyword(Keyword::ENFORCED) => Some(true),
8146+
// not MySQL, or is MySQL but not specified
8147+
_ => None,
8148+
};
8149+
8150+
Ok(Some(TableConstraint::Check {
8151+
name,
8152+
expr,
8153+
enforced,
8154+
}))
81438155
}
81448156
Token::Word(w)
81458157
if (w.keyword == Keyword::INDEX || w.keyword == Keyword::KEY)

tests/sqlparser_mysql.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4025,3 +4025,10 @@ fn parse_drop_index() {
40254025
_ => unreachable!(),
40264026
}
40274027
}
4028+
4029+
#[test]
4030+
fn check_enforced() {
4031+
mysql().verified_stmt(
4032+
"CREATE TABLE t (a INT, b INT, c INT, CHECK (a > 0) NOT ENFORCED, CHECK (b > 0) ENFORCED, CHECK (c > 0))",
4033+
);
4034+
}

tests/sqlparser_postgres.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5378,6 +5378,7 @@ fn parse_create_domain() {
53785378
op: BinaryOperator::Gt,
53795379
right: Box::new(Expr::Value(test_utils::number("0").into())),
53805380
}),
5381+
enforced: None,
53815382
}],
53825383
});
53835384

@@ -5396,6 +5397,7 @@ fn parse_create_domain() {
53965397
op: BinaryOperator::Gt,
53975398
right: Box::new(Expr::Value(test_utils::number("0").into())),
53985399
}),
5400+
enforced: None,
53995401
}],
54005402
});
54015403

@@ -5414,6 +5416,7 @@ fn parse_create_domain() {
54145416
op: BinaryOperator::Gt,
54155417
right: Box::new(Expr::Value(test_utils::number("0").into())),
54165418
}),
5419+
enforced: None,
54175420
}],
54185421
});
54195422

@@ -5432,6 +5435,7 @@ fn parse_create_domain() {
54325435
op: BinaryOperator::Gt,
54335436
right: Box::new(Expr::Value(test_utils::number("0").into())),
54345437
}),
5438+
enforced: None,
54355439
}],
54365440
});
54375441

@@ -5450,6 +5454,7 @@ fn parse_create_domain() {
54505454
op: BinaryOperator::Gt,
54515455
right: Box::new(Expr::Value(test_utils::number("0").into())),
54525456
}),
5457+
enforced: None,
54535458
}],
54545459
});
54555460

0 commit comments

Comments
 (0)