Skip to content

Commit bf299ca

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 394a534 commit bf299ca

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
@@ -1026,10 +1026,13 @@ pub enum TableConstraint {
10261026
on_update: Option<ReferentialAction>,
10271027
characteristics: Option<ConstraintCharacteristics>,
10281028
},
1029-
/// `[ CONSTRAINT <name> ] CHECK (<expr>)`
1029+
/// `[ CONSTRAINT <name> ] CHECK (<expr>) [[NOT] ENFORCED]`
10301030
Check {
10311031
name: Option<Ident>,
10321032
expr: Box<Expr>,
1033+
/// MySQL-specific syntax
1034+
/// https://dev.mysql.com/doc/refman/8.4/en/create-table.html
1035+
enforced: Option<bool>,
10331036
},
10341037
/// MySQLs [index definition][1] for index creation. Not present on ANSI so, for now, the usage
10351038
/// is restricted to MySQL, as no other dialects that support this syntax were found.
@@ -1157,8 +1160,17 @@ impl fmt::Display for TableConstraint {
11571160
}
11581161
Ok(())
11591162
}
1160-
TableConstraint::Check { name, expr } => {
1161-
write!(f, "{}CHECK ({})", display_constraint_name(name), expr)
1163+
TableConstraint::Check {
1164+
name,
1165+
expr,
1166+
enforced,
1167+
} => {
1168+
write!(f, "{}CHECK ({})", display_constraint_name(name), expr)?;
1169+
if let Some(b) = enforced {
1170+
write!(f, " {}", if *b { "ENFORCED" } else { "NOT ENFORCED" })
1171+
} else {
1172+
Ok(())
1173+
}
11621174
}
11631175
TableConstraint::Index {
11641176
display_as_key,

src/ast/spans.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -685,9 +685,11 @@ impl Spanned for TableConstraint {
685685
.chain(on_update.iter().map(|i| i.span()))
686686
.chain(characteristics.iter().map(|i| i.span())),
687687
),
688-
TableConstraint::Check { name, expr } => {
689-
expr.span().union_opt(&name.as_ref().map(|i| i.span))
690-
}
688+
TableConstraint::Check {
689+
name,
690+
expr,
691+
enforced: _,
692+
} => expr.span().union_opt(&name.as_ref().map(|i| i.span)),
691693
TableConstraint::Index {
692694
display_as_key: _,
693695
name,

src/parser/mod.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8134,7 +8134,19 @@ impl<'a> Parser<'a> {
81348134
self.expect_token(&Token::LParen)?;
81358135
let expr = Box::new(self.parse_expr()?);
81368136
self.expect_token(&Token::RParen)?;
8137-
Ok(Some(TableConstraint::Check { name, expr }))
8137+
8138+
let enforced = match dialect_of!(self is GenericDialect | MySqlDialect) {
8139+
true if self.parse_keywords(&[Keyword::NOT, Keyword::ENFORCED]) => Some(false),
8140+
true if self.parse_keyword(Keyword::ENFORCED) => Some(true),
8141+
// not MySQL, or is MySQL but not specified
8142+
_ => None,
8143+
};
8144+
8145+
Ok(Some(TableConstraint::Check {
8146+
name,
8147+
expr,
8148+
enforced,
8149+
}))
81388150
}
81398151
Token::Word(w)
81408152
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
@@ -4018,3 +4018,10 @@ fn parse_drop_index() {
40184018
_ => unreachable!(),
40194019
}
40204020
}
4021+
4022+
#[test]
4023+
fn check_enforced() {
4024+
mysql().verified_stmt(
4025+
"CREATE TABLE t (a INT, b INT, c INT, CHECK (a > 0) NOT ENFORCED, CHECK (b > 0) ENFORCED, CHECK (c > 0))",
4026+
);
4027+
}

tests/sqlparser_postgres.rs

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

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

@@ -5415,6 +5417,7 @@ fn parse_create_domain() {
54155417
op: BinaryOperator::Gt,
54165418
right: Box::new(Expr::Value(test_utils::number("0").into())),
54175419
}),
5420+
enforced: None,
54185421
}],
54195422
});
54205423

@@ -5433,6 +5436,7 @@ fn parse_create_domain() {
54335436
op: BinaryOperator::Gt,
54345437
right: Box::new(Expr::Value(test_utils::number("0").into())),
54355438
}),
5439+
enforced: None,
54365440
}],
54375441
});
54385442

@@ -5451,6 +5455,7 @@ fn parse_create_domain() {
54515455
op: BinaryOperator::Gt,
54525456
right: Box::new(Expr::Value(test_utils::number("0").into())),
54535457
}),
5458+
enforced: None,
54545459
}],
54555460
});
54565461

0 commit comments

Comments
 (0)