diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java index fba504ae44..96669f9e2f 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java @@ -15,15 +15,20 @@ */ package com.alibaba.druid.sql.dialect.mysql.ast.statement; +import java.util.ArrayList; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; +import com.alibaba.druid.sql.ast.SQLCommentHint; import com.alibaba.druid.sql.ast.SQLPartitioningClause; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLSelect; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; @SuppressWarnings("serial") -public class MySqlCreateTableStatement extends SQLCreateTableStatement { +public class MySqlCreateTableStatement extends SQLCreateTableStatement implements MySqlStatement { private boolean ifNotExiists = false; @@ -37,6 +42,20 @@ public class MySqlCreateTableStatement extends SQLCreateTableStatement { } + private List hints = new ArrayList(); + + public List getHints() { + return hints; + } + + public void setHints(List hints) { + this.hints = hints; + } + + public void setTableOptions(Map tableOptions) { + this.tableOptions = tableOptions; + } + public SQLPartitioningClause getPartitioning() { return partitioning; } @@ -94,4 +113,21 @@ public class MySqlCreateTableStatement extends SQLCreateTableStatement { this.ifNotExiists = ifNotExiists; } + @Override + protected void accept0(SQLASTVisitor visitor) { + if (visitor instanceof MySqlASTVisitor) { + accept0((MySqlASTVisitor) visitor); + } else { + throw new IllegalArgumentException("not support visitor type : " + visitor.getClass().getName()); + } + } + + public void accept0(MySqlASTVisitor visitor) { + if (visitor.visit(this)) { + this.acceptChild(visitor, getHints()); + this.acceptChild(visitor, getTableSource()); + this.acceptChild(visitor, getTableElementList()); + } + visitor.endVisit(this); + } } 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 6b7b970a43..4772c9f797 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 @@ -46,7 +46,7 @@ public class MySqlCreateTableParser extends SQLCreateTableParser { return parseCrateTable(true); } - public SQLCreateTableStatement parseCrateTable(boolean acceptCreate) throws ParserException { + public MySqlCreateTableStatement parseCrateTable(boolean acceptCreate) throws ParserException { if (acceptCreate) { accept(Token.CREATE); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java index 501a568d07..5b883c9b54 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java @@ -15,11 +15,7 @@ */ package com.alibaba.druid.sql.dialect.mysql.parser; -import java.util.List; - -import com.alibaba.druid.sql.ast.SQLCommentHint; import com.alibaba.druid.sql.ast.SQLExpr; -import com.alibaba.druid.sql.ast.SQLHint; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; @@ -611,10 +607,4 @@ public class MySqlExprParser extends SQLExprParser { return null; } - public void parseHints(List hints) { - if (lexer.token() == Token.HINT) { - hints.add(new SQLCommentHint(lexer.stringVal())); - 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 68b1970be8..ef61a4258d 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 @@ -17,6 +17,7 @@ package com.alibaba.druid.sql.dialect.mysql.parser; import java.util.List; +import com.alibaba.druid.sql.ast.SQLCommentHint; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLOrderBy; @@ -48,6 +49,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatemen import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateIndexStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDescribeStatement; @@ -265,9 +267,13 @@ public class MySqlStatementParser extends SQLStatementParser { public SQLStatement parseCreate() throws ParserException { accept(Token.CREATE); + List hints = this.exprParser.parseHints(); + if (lexer.token() == Token.TABLE || identifierEquals("TEMPORARY")) { MySqlCreateTableParser parser = new MySqlCreateTableParser(lexer); - return parser.parseCrateTable(false); + MySqlCreateTableStatement stmt = parser.parseCrateTable(false); + stmt.setHints(hints); + return stmt; } if (lexer.token() == Token.UNIQUE || lexer.token() == Token.INDEX || identifierEquals("FULLTEXT") 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 101802a554..f48fc9bc90 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 @@ -37,6 +37,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatemen import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateIndexStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDescribeStatement; @@ -495,4 +496,8 @@ public interface MySqlASTVisitor extends SQLASTVisitor { boolean visit(MySqlAlterTableOption x); void endVisit(MySqlAlterTableOption x); + + boolean visit(MySqlCreateTableStatement x); + + void endVisit(MySqlCreateTableStatement x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java index 59564c039f..32adaf97fb 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java @@ -22,6 +22,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatemen import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateIndexStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement.UserSpecification; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; @@ -1079,4 +1080,14 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements public void endVisit(MySqlAlterTableOption x) { } + + @Override + public boolean visit(MySqlCreateTableStatement x) { + return true; + } + + @Override + public void endVisit(MySqlCreateTableStatement 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 32e359870d..acb35ec2b9 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 @@ -17,6 +17,7 @@ package com.alibaba.druid.sql.dialect.mysql.visitor; import java.util.Map; +import com.alibaba.druid.sql.ast.SQLCommentHint; import com.alibaba.druid.sql.ast.SQLDataType; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLSetQuantifier; @@ -359,20 +360,22 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV return false; } - public boolean visit(SQLCreateTableStatement x) { + public boolean visit(MySqlCreateTableStatement x) { - MySqlCreateTableStatement mysqlCreateTableStatement = null; - if (x instanceof MySqlCreateTableStatement) { - mysqlCreateTableStatement = (MySqlCreateTableStatement) x; + print("CREATE "); + + for (SQLCommentHint hint : x.getHints()) { + hint.accept(this); + print(' '); } if (SQLCreateTableStatement.Type.GLOBAL_TEMPORARY.equals(x.getType())) { - print("CREATE TEMPORARY TABLE "); + print("TEMPORARY TABLE "); } else { - print("CREATE TABLE "); + print("TABLE "); } - if (mysqlCreateTableStatement != null && mysqlCreateTableStatement.isIfNotExiists()) { + if (x.isIfNotExiists()) { print("IF NOT EXISTS "); } @@ -391,20 +394,18 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV println(); print(")"); - if (mysqlCreateTableStatement != null) { - for (Map.Entry option : mysqlCreateTableStatement.getTableOptions().entrySet()) { - print(" "); - print(option.getKey()); - print(" = "); - print(option.getValue()); - } + for (Map.Entry option : x.getTableOptions().entrySet()) { + print(" "); + print(option.getKey()); + print(" = "); + print(option.getValue()); } - if (mysqlCreateTableStatement != null && mysqlCreateTableStatement.getQuery() != null) { + if (x.getQuery() != null) { print(" "); incrementIndent(); println(); - mysqlCreateTableStatement.getQuery().accept(this); + x.getQuery().accept(this); decrementIndent(); } @@ -2525,12 +2526,12 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV public boolean visit(MySqlAlterTableCharacter x) { print("CHARACTER SET = "); x.getCharacterSet().accept(this); - + if (x.getCollate() != null) { print(", COLLATE = "); x.getCollate().accept(this); } - + return false; } @@ -2563,7 +2564,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV @Override public void endVisit(MySqlAlterTableAddIndex x) { - + } @Override @@ -2576,6 +2577,11 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV @Override public void endVisit(MySqlAlterTableOption x) { - + + } + + @Override + public void endVisit(MySqlCreateTableStatement x) { + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java index d261bb4e99..dd04eae6c5 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java @@ -4,6 +4,7 @@ import java.util.Map; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; @@ -32,6 +33,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatemen import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateIndexStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement.UserSpecification; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; @@ -1143,4 +1145,14 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS public void endVisit(MySqlAlterTableOption x) { } + + @Override + public boolean visit(MySqlCreateTableStatement x) { + return super.visit((SQLCreateTableStatement) x); + } + + @Override + public void endVisit(MySqlCreateTableStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectQueryBlock.java index 3c24b2e9b6..8641801335 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectQueryBlock.java @@ -18,7 +18,7 @@ package com.alibaba.druid.sql.dialect.oracle.ast.stmt; import java.util.ArrayList; import java.util.List; -import com.alibaba.druid.sql.ast.SQLHint; +import com.alibaba.druid.sql.ast.SQLCommentHint; import com.alibaba.druid.sql.ast.SQLSetQuantifier; import com.alibaba.druid.sql.ast.statement.SQLSelectItem; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; @@ -30,7 +30,7 @@ public class OracleSelectQueryBlock extends SQLSelectQueryBlock { private static final long serialVersionUID = 1L; - private final List hints = new ArrayList(1); + private final List hints = new ArrayList(1); private OracleSelectHierachicalQueryClause hierachicalQueryClause; private ModelClause modelClause; @@ -55,7 +55,7 @@ public class OracleSelectQueryBlock extends SQLSelectQueryBlock { this.hierachicalQueryClause = hierachicalQueryClause; } - public List getHints() { + public List getHints() { return this.hints; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java index 0391cded3e..d36d120b78 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java @@ -17,7 +17,6 @@ package com.alibaba.druid.sql.dialect.oracle.visitor; import java.util.List; -import com.alibaba.druid.sql.ast.SQLCommentHint; import com.alibaba.druid.sql.ast.SQLDataType; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLHint; @@ -906,11 +905,6 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } - @Override - public void endVisit(SQLCommentHint x) { - - } - @Override public void endVisit(OracleIntervalExpr x) { @@ -2181,7 +2175,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print(x.getType()); print(" "); } - + print("INDEX "); x.getName().accept(this); diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index 6f49c1df02..201be488f0 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -16,6 +16,7 @@ package com.alibaba.druid.sql.parser; import java.math.BigInteger; +import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -23,7 +24,6 @@ import com.alibaba.druid.sql.ast.SQLCommentHint; import com.alibaba.druid.sql.ast.SQLDataType; import com.alibaba.druid.sql.ast.SQLDataTypeImpl; import com.alibaba.druid.sql.ast.SQLExpr; -import com.alibaba.druid.sql.ast.SQLHint; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLOrderBy; import com.alibaba.druid.sql.ast.SQLOrderingSpecification; @@ -1199,7 +1199,15 @@ public class SQLExprParser extends SQLParser { return item; } - public void parseHints(List hints) { + public List parseHints() { + List hints = new ArrayList(); + parseHints(hints); + return hints; + } + + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void parseHints(List hints) { if (lexer.token() == Token.HINT) { hints.add(new SQLCommentHint(lexer.stringVal())); lexer.nextToken(); diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index 62eff614b3..ce562d9e52 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -1092,7 +1092,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { } public boolean visit(SQLCommentHint x) { + print("/*"); print(x.getText()); + print("*/"); return false; } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/cobar/HintsTest.java b/src/test/java/com/alibaba/druid/bvt/sql/cobar/HintsTest.java index 96fd534653..ff983c9ac2 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/cobar/HintsTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/cobar/HintsTest.java @@ -17,6 +17,6 @@ public class HintsTest extends TestCase { SQLStatement stmt = parser.parseStatementList().get(0); parser.match(Token.EOF); String output = SQLUtils.toMySqlString(stmt); - Assert.assertEquals("CREATE TABLE t (\n\ta INT\n)", output); + Assert.assertEquals("CREATE /*!32302 TEMPORARY*/ TABLE t (\n\ta INT\n)", output); } }