From fcc50128a75c2423c1da5dc184825c433fb8c951 Mon Sep 17 00:00:00 2001 From: wenshao Date: Mon, 15 Jul 2013 16:48:34 +0800 Subject: [PATCH] add support UNIQUE --- .../druid/sql/ast/statement/SQLUnique.java | 42 +++++++++ .../druid/sql/dialect/mysql/ast/MySqlKey.java | 16 +--- .../oracle/visitor/OracleOutputVisitor.java | 14 +++ .../sql/parser/SQLCreateTableParser.java | 4 + .../druid/sql/parser/SQLExprParser.java | 12 +++ .../druid/sql/visitor/SQLASTVisitor.java | 5 ++ .../sql/visitor/SQLASTVisitorAdapter.java | 11 +++ .../sql/oracle/OracleCreateTableTest17.java | 90 +++++++++++++++++++ 8 files changed, 181 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest17.java diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java new file mode 100644 index 0000000000..d9253df609 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java @@ -0,0 +1,42 @@ +/* + * Copyright 1999-2011 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.sql.ast.statement; + +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +@SuppressWarnings("serial") +public class SQLUnique extends SQLConstaintImpl implements SQLUniqueConstraint, SQLTableElement { + + private final List columns = new ArrayList(); + + public List getColumns() { + return columns; + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, this.getName()); + acceptChild(visitor, this.getColumns()); + } + visitor.endVisit(this); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlKey.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlKey.java index c51575ea76..ab589d8f6b 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlKey.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlKey.java @@ -15,21 +15,16 @@ */ package com.alibaba.druid.sql.dialect.mysql.ast; -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.druid.sql.ast.SQLExpr; -import com.alibaba.druid.sql.ast.statement.SQLConstaintImpl; import com.alibaba.druid.sql.ast.statement.SQLTableConstaint; +import com.alibaba.druid.sql.ast.statement.SQLUnique; import com.alibaba.druid.sql.ast.statement.SQLUniqueConstraint; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @SuppressWarnings("serial") -public class MySqlKey extends SQLConstaintImpl implements SQLUniqueConstraint, SQLTableConstaint { +public class MySqlKey extends SQLUnique implements SQLUniqueConstraint, SQLTableConstaint { - private List columns = new ArrayList(); - private String indexType; + private String indexType; public MySqlKey(){ @@ -50,11 +45,6 @@ public class MySqlKey extends SQLConstaintImpl implements SQLUniqueConstraint, S visitor.endVisit(this); } - @Override - public List getColumns() { - return columns; - } - public String getIndexType() { return indexType; } 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 710eea3c53..3392d310d5 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 @@ -36,6 +36,7 @@ import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType; import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +import com.alibaba.druid.sql.ast.statement.SQLUnique; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeTimestamp; @@ -2332,6 +2333,19 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public void endVisit(OraclePrimaryKey x) { } + + @Override + public boolean visit(SQLUnique x) { + if (x.getName() != null) { + print("CONSTRAINT "); + x.getName().accept(this); + print(" "); + } + print("UNIQUE ("); + printAndAccept(x.getColumns(), ", "); + print(")"); + return false; + } @Override public boolean visit(OracleCreateTableStatement x) { diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java index f1dc8691ad..8016300a11 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java @@ -18,6 +18,7 @@ package com.alibaba.druid.sql.parser; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLPrimaryKey; +import com.alibaba.druid.sql.ast.statement.SQLUnique; public class SQLCreateTableParser extends SQLDDLParser { @@ -73,6 +74,9 @@ public class SQLCreateTableParser extends SQLDDLParser { } else if (lexer.token() == Token.PRIMARY) { SQLPrimaryKey primaryKey = exprParser.parsePrimaryKey(); createTable.getTableElementList().add(primaryKey); + } else if (lexer.token == Token.UNIQUE) { + SQLUnique unique = exprParser.parseUnique(); + createTable.getTableElementList().add(unique); } else { throw new ParserException("TODO " + lexer.token()); } 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 925786c581..bd100aa8d8 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -68,6 +68,7 @@ import com.alibaba.druid.sql.ast.statement.SQLColumnPrimaryKey; import com.alibaba.druid.sql.ast.statement.SQLPrimaryKey; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem; +import com.alibaba.druid.sql.ast.statement.SQLUnique; public class SQLExprParser extends SQLParser { @@ -1297,6 +1298,17 @@ public class SQLExprParser extends SQLParser { throw new ParserException("TODO"); } + public SQLUnique parseUnique() { + accept(Token.UNIQUE); + + SQLUnique unique = new SQLUnique(); + accept(Token.LPAREN); + exprList(unique.getColumns()); + accept(Token.RPAREN); + + return unique; + } + public SQLAssignItem parseAssignItem() { SQLAssignItem item = new SQLAssignItem(); diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java index 1495188265..57630c7d3b 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java @@ -95,6 +95,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSetStatement; import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource; import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; +import com.alibaba.druid.sql.ast.statement.SQLUnique; import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; import com.alibaba.druid.sql.ast.statement.SQLUseStatement; @@ -449,4 +450,8 @@ public interface SQLASTVisitor { boolean visit(SQLAlterTableDropConstraint x); void endVisit(SQLAlterTableDropConstraint x); + + boolean visit(SQLUnique x); + + void endVisit(SQLUnique x); } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java index ec778d5987..bc1e6ad847 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -96,6 +96,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSetStatement; import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource; import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; +import com.alibaba.druid.sql.ast.statement.SQLUnique; import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; import com.alibaba.druid.sql.ast.statement.SQLUseStatement; @@ -850,4 +851,14 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { public void endVisit(SQLAlterTableDropConstraint x) { } + + @Override + public boolean visit(SQLUnique x) { + return true; + } + + @Override + public void endVisit(SQLUnique x) { + + } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest17.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest17.java new file mode 100644 index 0000000000..cfed6448f2 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest17.java @@ -0,0 +1,90 @@ +/* + * Copyright 1999-2011 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle; + +import java.util.List; + +import org.junit.Assert; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; + +public class OracleCreateTableTest17 extends OracleTest { + + public void test_types() throws Exception { + String sql = // + "create table ACT_HI_PROCINST ( "// + + "ID_ NVARCHAR2(64) not null, "// + + "PROC_INST_ID_ NVARCHAR2(64) not null, "// + + "BUSINESS_KEY_ NVARCHAR2(255), "// + + "PROC_DEF_ID_ NVARCHAR2(64) not null, "// + + "START_TIME_ TIMESTAMP(6) not null, "// + + "END_TIME_ TIMESTAMP(6), "// + + "DURATION_ NUMBER(19,0), "// + + "START_USER_ID_ NVARCHAR2(255), "// + + "START_ACT_ID_ NVARCHAR2(255), "// + + "END_ACT_ID_ NVARCHAR2(255), "// + + "SUPER_PROCESS_INSTANCE_ID_ NVARCHAR2(64), "// + + "DELETE_REASON_ NVARCHAR2(2000), "// + + "primary key (ID_), "// + + "unique (PROC_INST_ID_) "// + + ")"; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statement = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + Assert.assertEquals("CREATE TABLE ACT_HI_PROCINST (" + + "\n\tID_ NVARCHAR2(64) NOT NULL," + + "\n\tPROC_INST_ID_ NVARCHAR2(64) NOT NULL," + + "\n\tBUSINESS_KEY_ NVARCHAR2(255)," + + "\n\tPROC_DEF_ID_ NVARCHAR2(64) NOT NULL," + + "\n\tSTART_TIME_ TIMESTAMP(6) NOT NULL," + + "\n\tEND_TIME_ TIMESTAMP(6)," + + "\n\tDURATION_ NUMBER(19, 0)," + + "\n\tSTART_USER_ID_ NVARCHAR2(255)," + + "\n\tSTART_ACT_ID_ NVARCHAR2(255)," + + "\n\tEND_ACT_ID_ NVARCHAR2(255)," + + "\n\tSUPER_PROCESS_INSTANCE_ID_ NVARCHAR2(64)," + + "\n\tDELETE_REASON_ NVARCHAR2(2000)," + + "\n\tPRIMARY KEY (ID_)," + + "\n\tUNIQUE (PROC_INST_ID_)" + + "\n)", SQLUtils.toSQLString(statement, JdbcConstants.ORACLE)); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + statement.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(1, visitor.getTables().size()); + + Assert.assertEquals(12, visitor.getColumns().size()); + + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("ACT_HI_PROCINST", "ID_"))); + } +}