diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlAlterTableAlterCheck.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlAlterTableAlterCheck.java new file mode 100644 index 0000000000..ac5d04a022 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlAlterTableAlterCheck.java @@ -0,0 +1,38 @@ +package com.alibaba.druid.sql.dialect.mysql.ast.statement; + +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.statement.SQLAlterTableItem; +import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; + +public class MysqlAlterTableAlterCheck extends MySqlObjectImpl implements SQLAlterTableItem { + + private SQLName name; + private Boolean enforced; + + @Override + public void accept0(MySqlASTVisitor visitor) { + if (visitor.visit(this)) { + if (getName() != null) { + getName().accept(visitor); + } + } + visitor.endVisit(this); + } + + public SQLName getName() { + return name; + } + + public void setName(SQLName name) { + this.name = name; + } + + public Boolean getEnforced() { + return enforced; + } + + public void setEnforced(Boolean enforced) { + this.enforced = enforced; + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java index 29506ee4a8..6923bcc9fd 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java @@ -1550,6 +1550,9 @@ public class MySqlCreateTableParser extends SQLCreateTableParser { check.setExpr(expr); constraint = check; + boolean enforce = true; + //should find Token.NOT to recognize "NOT ENFORCED" + //but somehow Token.NOT eaten by "this.exprParser.expr()" in above code if (lexer.token() == Token.HINT) { String hintText = lexer.stringVal(); if (hintText != null) { @@ -1564,6 +1567,9 @@ public class MySqlCreateTableParser extends SQLCreateTableParser { } lexer.nextToken(); } + } else if (lexer.stringVal().equalsIgnoreCase("ENFORCED")) { + check.setEnforced(enforce); + lexer.nextToken(); } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index 31398febb2..f0dfc08b94 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -6021,13 +6021,14 @@ public class MySqlStatementParser extends SQLStatementParser { lexer.nextToken(); if (lexer.token() == Token.IDENTIFIER) { constraintSymbol = this.exprParser.name(); - if (lexer.token() != Token.PRIMARY && lexer.token() != Token.UNIQUE && lexer.token() != Token.FOREIGN) { + if (lexer.token() != Token.PRIMARY && lexer.token() != Token.UNIQUE && lexer.token() != Token.FOREIGN && lexer.token() != CHECK) { throw new ParserException("syntax error, expect PRIMARY, UNIQUE or FOREIGN, actual " + lexer.token() + ", " + lexer.info()); } } case PRIMARY: case UNIQUE: case FOREIGN: + case CHECK: // Constraint. if (lexer.token() == Token.FOREIGN) { MysqlForeignKey fk = this.getExprParser().parseForeignKey(); @@ -6054,21 +6055,29 @@ public class MySqlStatementParser extends SQLStatementParser { this.exprParser.parseIndex(uk.getIndexDefinition()); SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(uk); stmt.addItem(item); + } else if (lexer.token() == Token.CHECK) { // ADD CHECK (expr) + lexer.nextToken(); + accept(Token.LPAREN); + SQLCheck check = new SQLCheck(); + if (null != constraintSymbol) { + check.setName(constraintSymbol); + } + check.setExpr(this.exprParser.expr()); + accept(Token.RPAREN); + boolean enforce = true; + if (lexer.token() == Token.NOT) { + enforce = false; + lexer.nextToken(); + } + if (lexer.stringVal().equalsIgnoreCase("ENFORCED")) { + check.setEnforced(enforce); + lexer.nextToken(); + } + SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(check); + stmt.addItem(item); } return true; - // ADD CHECK (expr) - case CHECK: { - lexer.nextToken(); - accept(Token.LPAREN); - SQLCheck check = new SQLCheck(); - check.setExpr(this.exprParser.expr()); - accept(Token.RPAREN); - SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(check); - stmt.addItem(item); - return true; - } - // ADD PARTITION (partition_definition) case PARTITION: { lexer.nextToken(); @@ -6525,6 +6534,20 @@ public class MySqlStatementParser extends SQLStatementParser { alterIndex.setAnalyzerName(this.exprParser.name()); stmt.addItem(alterIndex); + } else if (lexer.token() == Token.CHECK || lexer.token() == Token.CONSTRAINT) { + lexer.nextToken(); + MysqlAlterTableAlterCheck check = new MysqlAlterTableAlterCheck(); + check.setName(this.exprParser.name()); + boolean enforce = true; + if (lexer.token() == Token.NOT) { + enforce = false; + lexer.nextToken(); + } + if (lexer.stringVal().equalsIgnoreCase("ENFORCED")) { + check.setEnforced(enforce); + lexer.nextToken(); + } + stmt.addItem(check); } else { // ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT} if (lexer.token() == Token.COLUMN) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java index aa128a231f..b656778ed9 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java @@ -1443,4 +1443,12 @@ public interface MySqlASTVisitor extends SQLASTVisitor { default void endVisit(MySqlJSONTableExpr.Column x) { } + + default boolean visit(MysqlAlterTableAlterCheck x) { + return true; + } + + default void endVisit(MysqlAlterTableAlterCheck x) { + + } } // diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index 57e757399e..b1e33500c9 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -5519,4 +5519,27 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV // return false; // } + public boolean visit(MysqlAlterTableAlterCheck x) { + print0(ucase ? "ALTER CONSTRAINT " : "alter constraint "); + + SQLName name = x.getName(); + if (name != null) { + name.accept(this); + print(' '); + } + + Boolean enforced = x.getEnforced(); + if (enforced != null) { + if (enforced) { + print0(ucase ? " ENFORCED" : " enforced"); + } else { + print0(ucase ? " NOT ENFORCED" : " not enforced"); + } + } + return false; + } + + public void endVisit(MysqlAlterTableAlterCheck x) { + + } } //