Skip to content

Commit

Permalink
Feat(mysql): add support for the UNIQUE KEY constraint (#1708)
Browse files Browse the repository at this point in the history
* Feat(mysql): add support for the UNIQUE KEY constraint

* Cleanup
  • Loading branch information
georgesittas authored May 31, 2023
1 parent dd5457c commit 1b1d9f2
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 18 deletions.
6 changes: 1 addition & 5 deletions sqlglot/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1285,7 +1285,7 @@ class TitleColumnConstraint(ColumnConstraintKind):


class UniqueColumnConstraint(ColumnConstraintKind):
arg_types: t.Dict[str, t.Any] = {}
arg_types = {"this": False}


class UppercaseColumnConstraint(ColumnConstraintKind):
Expand Down Expand Up @@ -1450,10 +1450,6 @@ class PrimaryKey(Expression):
arg_types = {"expressions": True, "options": False}


class Unique(Expression):
arg_types = {"expressions": True}


# https://www.postgresql.org/docs/9.1/sql-selectinto.html
# https://docs.aws.amazon.com/redshift/latest/dg/r_SELECT_INTO.html#r_SELECT_INTO-examples
class Into(Expression):
Expand Down
10 changes: 4 additions & 6 deletions sqlglot/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -629,8 +629,10 @@ def primarykeycolumnconstraint_sql(self, expression: exp.PrimaryKeyColumnConstra
return f"PRIMARY KEY{' DESC' if desc else ' ASC'}"
return f"PRIMARY KEY"

def uniquecolumnconstraint_sql(self, _) -> str:
return "UNIQUE"
def uniquecolumnconstraint_sql(self, expression: exp.UniqueColumnConstraint) -> str:
this = self.sql(expression, "this")
this = f" {this}" if this else ""
return f"UNIQUE{this}"

def create_sql(self, expression: exp.Create) -> str:
kind = self.sql(expression, "kind").upper()
Expand Down Expand Up @@ -1771,10 +1773,6 @@ def primarykey_sql(self, expression: exp.ForeignKey) -> str:
options = f" {options}" if options else ""
return f"PRIMARY KEY ({expressions}){options}"

def unique_sql(self, expression: exp.Unique) -> str:
columns = self.expressions(expression, key="expressions")
return f"UNIQUE ({columns})"

def if_sql(self, expression: exp.If) -> str:
return self.case_sql(
exp.Case(ifs=[expression.copy()], default=expression.args.get("false"))
Expand Down
7 changes: 4 additions & 3 deletions sqlglot/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3371,9 +3371,10 @@ def _parse_unnamed_constraint(
return self.CONSTRAINT_PARSERS[constraint](self)

def _parse_unique(self) -> exp.Expression:
if not self._match(TokenType.L_PAREN, advance=False):
return self.expression(exp.UniqueColumnConstraint)
return self.expression(exp.Unique, expressions=self._parse_wrapped_id_vars())
self._match_text_seq("KEY")
return self.expression(
exp.UniqueColumnConstraint, this=self._parse_schema(self._parse_id_var(any_token=False))
)

def _parse_key_constraint_options(self) -> t.List[str]:
options = []
Expand Down
14 changes: 10 additions & 4 deletions tests/dialects/test_mysql.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ class TestMySQL(Validator):
dialect = "mysql"

def test_ddl(self):
self.validate_identity(
"INSERT INTO x VALUES (1, 'a', 2.0) ON DUPLICATE KEY UPDATE SET x.id = 1"
)

self.validate_all(
"CREATE TABLE z (a INT) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARACTER SET=utf8 COLLATE=utf8_bin COMMENT='x'",
write={
Expand All @@ -21,10 +25,6 @@ def test_ddl(self):
"mysql": "CREATE TABLE t (c DATETIME DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP()) DEFAULT CHARACTER SET=utf8 ROW_FORMAT=DYNAMIC",
},
)
self.validate_identity(
"INSERT INTO x VALUES (1, 'a', 2.0) ON DUPLICATE KEY UPDATE SET x.id = 1"
)

self.validate_all(
"CREATE TABLE x (id int not null auto_increment, primary key (id))",
write={
Expand All @@ -37,6 +37,12 @@ def test_ddl(self):
"sqlite": "CREATE TABLE x (id INTEGER NOT NULL)",
},
)
self.validate_all(
"CREATE TABLE `foo` (`id` char(36) NOT NULL DEFAULT (uuid()), PRIMARY KEY (`id`), UNIQUE KEY `id` (`id`))",
write={
"mysql": "CREATE TABLE `foo` (`id` CHAR(36) NOT NULL DEFAULT (UUID()), PRIMARY KEY (`id`), UNIQUE `id` (`id`))",
},
)

def test_identity(self):
self.validate_identity("SELECT CURRENT_TIMESTAMP(6)")
Expand Down

1 comment on commit 1b1d9f2

@georgesittas
Copy link
Collaborator Author

@georgesittas georgesittas commented on 1b1d9f2 May 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this is a breaking commit because exp.Unique was removed. Forgot to rename the commit / PR title accordingly..

Please sign in to comment.