Skip to content

Commit 28fef8b

Browse files
committed
Add support for unnamed CONSTRAINT CHECK syntax
Fixes parsing of `CONSTRAINT CHECK (expr)` without a constraint name, which is valid in MySQL and nom-sql. Previously, the parser would consume the CHECK keyword as the constraint name, then fail when it encountered the opening parenthesis. The fix checks if the next token after CONSTRAINT is a constraint keyword (PRIMARY, UNIQUE, FOREIGN, or CHECK). If so, it treats the constraint as unnamed rather than trying to parse the keyword as an identifier. Examples that now parse correctly: - CREATE TABLE t (x INT, CONSTRAINT CHECK (x > 1)) - ALTER TABLE t ADD CONSTRAINT PRIMARY KEY (id) - ALTER TABLE t ADD CONSTRAINT UNIQUE (email) These canonicalize to their forms without the CONSTRAINT keyword when no name is provided.
1 parent 982f766 commit 28fef8b

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

src/parser/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8825,7 +8825,15 @@ impl<'a> Parser<'a> {
88258825
&mut self,
88268826
) -> Result<Option<TableConstraint>, ParserError> {
88278827
let name = if self.parse_keyword(Keyword::CONSTRAINT) {
8828-
Some(self.parse_identifier()?)
8828+
if self.peek_keyword(Keyword::PRIMARY)
8829+
|| self.peek_keyword(Keyword::UNIQUE)
8830+
|| self.peek_keyword(Keyword::FOREIGN)
8831+
|| self.peek_keyword(Keyword::CHECK)
8832+
{
8833+
None
8834+
} else {
8835+
Some(self.parse_identifier()?)
8836+
}
88298837
} else {
88308838
None
88318839
};

tests/sqlparser_common.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5088,6 +5088,33 @@ fn parse_alter_table_constraints() {
50885088
}
50895089
}
50905090

5091+
#[test]
5092+
fn parse_alter_table_constraint_check_without_name() {
5093+
// CONSTRAINT CHECK without a name should parse and canonicalize to just CHECK
5094+
one_statement_parses_to(
5095+
"ALTER TABLE tab ADD CONSTRAINT CHECK (x > 1)",
5096+
"ALTER TABLE tab ADD CHECK (x > 1)",
5097+
);
5098+
one_statement_parses_to(
5099+
"CREATE TABLE t (x INT, CONSTRAINT CHECK (x > 1))",
5100+
"CREATE TABLE t (x INT, CHECK (x > 1))",
5101+
);
5102+
5103+
// Other constraint types should also work without names
5104+
one_statement_parses_to(
5105+
"ALTER TABLE tab ADD CONSTRAINT PRIMARY KEY (id)",
5106+
"ALTER TABLE tab ADD PRIMARY KEY (id)",
5107+
);
5108+
one_statement_parses_to(
5109+
"ALTER TABLE tab ADD CONSTRAINT UNIQUE (email)",
5110+
"ALTER TABLE tab ADD UNIQUE (email)",
5111+
);
5112+
one_statement_parses_to(
5113+
"ALTER TABLE tab ADD CONSTRAINT FOREIGN KEY (user_id) REFERENCES users(id)",
5114+
"ALTER TABLE tab ADD FOREIGN KEY (user_id) REFERENCES users(id)",
5115+
);
5116+
}
5117+
50915118
#[test]
50925119
fn parse_alter_table_drop_column() {
50935120
check_one("DROP COLUMN IF EXISTS is_active");

0 commit comments

Comments
 (0)