diff --git a/src/main/java/com/alibaba/druid/sql/SQLUtils.java b/src/main/java/com/alibaba/druid/sql/SQLUtils.java index 4b8a915000..f8461ea7f0 100644 --- a/src/main/java/com/alibaba/druid/sql/SQLUtils.java +++ b/src/main/java/com/alibaba/druid/sql/SQLUtils.java @@ -902,5 +902,17 @@ public class SQLUtils { long hash = Utils.fnv_64_lower(tableName); return Utils.hex_t(hash); } + + /** + * 重新排序建表语句 + * @param sql + * @param dbType + * @return + */ + public static String sort(String sql, String dbType) { + List stmtList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + SQLCreateTableStatement.sort(stmtList); + return SQLUtils.toSQLString(stmtList, dbType); + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java b/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java index 169d86ecef..a62752e191 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java @@ -29,4 +29,6 @@ public interface SQLDataType extends SQLObject { void setWithTimeZone(Boolean value); boolean isWithLocalTimeZone(); + + SQLDataType clone(); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLDataTypeImpl.java b/src/main/java/com/alibaba/druid/sql/ast/SQLDataTypeImpl.java index 080f9cfa61..3326c964b3 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLDataTypeImpl.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLDataTypeImpl.java @@ -101,4 +101,23 @@ public class SQLDataTypeImpl extends SQLObjectImpl implements SQLDataType { public void setWithLocalTimeZone(boolean withLocalTimeZone) { this.withLocalTimeZone = withLocalTimeZone; } + + public SQLDataTypeImpl clone() { + SQLDataTypeImpl x = new SQLDataTypeImpl(); + + cloneTo(x); + + return x; + } + + public void cloneTo(SQLDataTypeImpl x) { + x.name = name; + + for (SQLExpr arg : arguments) { + x.addArgument(arg.clone()); + } + + x.withTimeZone = withTimeZone; + x.withLocalTimeZone = withLocalTimeZone; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCharacterDataType.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCharacterDataType.java index f6e0ee0c34..0c102c114d 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCharacterDataType.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCharacterDataType.java @@ -101,6 +101,20 @@ public class SQLCharacterDataType extends SQLDataTypeImpl { visitor.endVisit(this); } + + public SQLCharacterDataType clone() { + SQLCharacterDataType x = new SQLCharacterDataType(name); + + super.cloneTo(x); + + x.charSetName = charSetName; + x.collate = collate; + x.charType = charType; + x.hasBinary = hasBinary; + + return x; + } + @Override public String toString() { return SQLUtils.toSQLString(this); diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnCheck.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnCheck.java index e09e8e6267..71ee386377 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnCheck.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnCheck.java @@ -50,4 +50,16 @@ public class SQLColumnCheck extends SQLConstraintImpl implements SQLColumnConstr visitor.endVisit(this); } + public SQLColumnCheck clone() { + SQLColumnCheck x = new SQLColumnCheck(); + + super.cloneTo(x); + + if (expr != null) { + x.setExpr(expr.clone()); + } + + return x; + } + } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnConstraint.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnConstraint.java index fd0e98842b..32f485900c 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnConstraint.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnConstraint.java @@ -16,5 +16,5 @@ package com.alibaba.druid.sql.ast.statement; public interface SQLColumnConstraint extends SQLConstraint { - + SQLColumnConstraint clone(); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java index 172bc35b1e..e0e806a68e 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java @@ -264,6 +264,13 @@ public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElemen visitor.endVisit(this); } + public Identity clone () { + Identity x = new Identity(); + x.seed = seed; + x.increment = increment; + x.notForReplication = notForReplication; + return x; + } } public String computeAlias() { @@ -277,4 +284,61 @@ public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElemen return SQLUtils.normalize(alias); } + + public SQLColumnDefinition clone() { + SQLColumnDefinition x = new SQLColumnDefinition(); + + if(name != null) { + x.setName(name.clone()); + } + + if (dataType != null) { + x.setDataType(dataType.clone()); + } + + if (defaultExpr != null) { + x.setDefaultExpr(defaultExpr.clone()); + } + + for (SQLColumnConstraint item : constraints) { + SQLColumnConstraint itemCloned = item.clone(); + itemCloned.setParent(x); + x.constraints.add(itemCloned); + } + + if (comment != null) { + x.setComment(comment.clone()); + } + + x.enable = enable; + x.validate = validate; + x.rely = rely; + + x.autoIncrement = autoIncrement; + + if (onUpdate != null) { + x.setOnUpdate(onUpdate.clone()); + } + + if (storage != null) { + x.setStorage(storage.clone()); + } + + if (charsetExpr != null) { + x.setCharsetExpr(charsetExpr.clone()); + } + + if (asExpr != null) { + x.setAsExpr(asExpr.clone()); + } + + x.sorted = sorted; + x.virtual = virtual; + + if (identity != null) { + x.setIdentity(identity.clone()); + } + + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnPrimaryKey.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnPrimaryKey.java index 3e0e74501b..1373598c4e 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnPrimaryKey.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnPrimaryKey.java @@ -27,4 +27,11 @@ public class SQLColumnPrimaryKey extends SQLConstraintImpl implements SQLColumnC visitor.endVisit(this); } + public SQLColumnPrimaryKey clone() { + SQLColumnPrimaryKey x = new SQLColumnPrimaryKey(); + + super.cloneTo(x); + + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnReference.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnReference.java index 7822b4de37..345741b265 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnReference.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnReference.java @@ -50,4 +50,22 @@ public class SQLColumnReference extends SQLConstraintImpl implements SQLColumnCo this.columns = columns; } + public SQLColumnReference clone() { + SQLColumnReference x = new SQLColumnReference(); + + super.cloneTo(x); + + if (table != null) { + x.setTable(table.clone()); + } + + for (SQLName column : columns) { + SQLName columnCloned = column.clone(); + columnCloned.setParent(x); + x.columns.add(columnCloned); + } + + return x; + } + } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnUniqueKey.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnUniqueKey.java index 193866f2e1..14dd2b2bd7 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnUniqueKey.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnUniqueKey.java @@ -27,4 +27,9 @@ public class SQLColumnUniqueKey extends SQLConstraintImpl implements SQLColumnCo visitor.endVisit(this); } + public SQLColumnUniqueKey clone() { + SQLColumnUniqueKey x = new SQLColumnUniqueKey(); + super.cloneTo(x); + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLConstraintImpl.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLConstraintImpl.java index 2db6703d5c..ec33505829 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLConstraintImpl.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLConstraintImpl.java @@ -34,6 +34,15 @@ public abstract class SQLConstraintImpl extends SQLObjectImpl implements SQLCons } + public void cloneTo(SQLConstraintImpl x) { + if (name != null) { + x.setName(name.clone()); + } + + x.enable = enable; + x.validate = validate; + x.rely = rely; + } public List getHints() { return hints; diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java index 7c1ea74d12..3eff1cf508 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java @@ -22,6 +22,7 @@ import com.alibaba.druid.sql.ast.*; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex; import com.alibaba.druid.sql.visitor.SQLASTVisitor; +import com.alibaba.druid.util.JdbcConstants; import com.alibaba.druid.util.ListDG; import com.alibaba.druid.util.lang.Consumer; @@ -283,8 +284,32 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS return false; } + public SQLAlterTableStatement foreignKeyToAlterTable() { + SQLAlterTableStatement stmt = new SQLAlterTableStatement(); + for (int i = this.tableElementList.size() - 1; i >= 0; --i) { + SQLTableElement element = this.tableElementList.get(i); + if (element instanceof SQLForeignKeyConstraint) { + SQLForeignKeyConstraint fk = (SQLForeignKeyConstraint) element; + this.tableElementList.remove(i); + stmt.addItem(new SQLAlterTableAddConstraint(fk)); + } + } + + if (stmt.getItems().size() == 0) { + return null; + } + + stmt.setDbType(getDbType()); + stmt.setTableSource(this.tableSource.clone()); + + Collections.reverse(stmt.getItems()); + + return stmt; + } + public static void sort(List stmtList) { Map tables = new HashMap(); + Map> referencedTables = new HashMap>(); for (SQLStatement stmt : stmtList) { if (stmt instanceof SQLCreateTableStatement) { @@ -295,7 +320,7 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS } } - List edges = new ArrayList(); + List edges = new ArrayList(); for (SQLCreateTableStatement stmt : tables.values()) { for (SQLTableElement element : stmt.getTableElementList()) { @@ -306,9 +331,15 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS SQLCreateTableStatement refTable = tables.get(refTableName); if (refTable != null) { - Object[] edge = new Object[] {stmt, refTable}; - edges.add(edge); + edges.add(new ListDG.Edge(stmt, refTable)); } + + List referencedList = referencedTables.get(refTableName); + if (referencedList == null) { + referencedList = new ArrayList(); + referencedTables.put(refTableName, referencedList); + } + referencedList.add(stmt); } } } @@ -316,9 +347,71 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS ListDG dg = new ListDG(stmtList, edges); SQLStatement[] tops = new SQLStatement[stmtList.size()]; - dg.topologicalSort(tops); - for (int i = 0, size = stmtList.size(); i < size; ++i) { - stmtList.set(i, tops[size - i - 1]); + if (dg.topologicalSort(tops)) { + for (int i = 0, size = stmtList.size(); i < size; ++i) { + stmtList.set(i, tops[size - i - 1]); + } + return; } + + List alterList = new ArrayList(); + + for (int i = edges.size() - 1; i >= 0; --i) { + ListDG.Edge edge = edges.get(i); + SQLCreateTableStatement from = (SQLCreateTableStatement) edge.from; + String fromTableName = from.getName().getSimpleName(); + fromTableName = SQLUtils.normalize(fromTableName).toLowerCase(); + if (referencedTables.containsKey(fromTableName)) { + edges.remove(i); + + Arrays.fill(tops, null); + tops = new SQLStatement[stmtList.size()]; + + dg = new ListDG(stmtList, edges); + if (dg.topologicalSort(tops)) { + for (int j = 0, size = stmtList.size(); j < size; ++j) { + SQLStatement stmt = tops[size - j - 1]; + stmtList.set(j, stmt); + } + + SQLAlterTableStatement alter = from.foreignKeyToAlterTable(); + alterList.add(alter); + + stmtList.add(alter); + return; + } + edges.add(i, edge); + } + } + + for (int i = edges.size() - 1; i >= 0; --i) { + ListDG.Edge edge = edges.get(i); + SQLCreateTableStatement from = (SQLCreateTableStatement) edge.from; + String fromTableName = from.getName().getSimpleName(); + fromTableName = SQLUtils.normalize(fromTableName).toLowerCase(); + if (referencedTables.containsKey(fromTableName)) { + SQLAlterTableStatement alter = from.foreignKeyToAlterTable(); + + edges.remove(i); + if (alter != null) { + alterList.add(alter); + } + + Arrays.fill(tops, null); + tops = new SQLStatement[stmtList.size()]; + + dg = new ListDG(stmtList, edges); + if (dg.topologicalSort(tops)) { + for (int j = 0, size = stmtList.size(); j < size; ++j) { + SQLStatement stmt = tops[size - j - 1]; + stmtList.set(j, stmt); + } + + stmtList.addAll(alterList); + return; + } + } + } + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLForeignKeyImpl.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLForeignKeyImpl.java index 50876750d9..3099e53bd1 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLForeignKeyImpl.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLForeignKeyImpl.java @@ -80,7 +80,7 @@ public class SQLForeignKeyImpl extends SQLConstraintImpl implements SQLForeignKe visitor.endVisit(this); } - public void cloneTo(SQLForeignKeyConstraint x) { + public void cloneTo(SQLForeignKeyImpl x) { super.cloneTo(x); if (referencedTableName != null) { @@ -99,4 +99,10 @@ public class SQLForeignKeyImpl extends SQLConstraintImpl implements SQLForeignKe x.getReferencedColumns().add(columnClone); } } + + public SQLForeignKeyImpl clone() { + SQLForeignKeyImpl x = new SQLForeignKeyImpl(); + cloneTo(x); + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLNotNullConstraint.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLNotNullConstraint.java index cb1a0d52ef..0286a30dae 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLNotNullConstraint.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLNotNullConstraint.java @@ -22,8 +22,6 @@ import java.util.List; public class SQLNotNullConstraint extends SQLConstraintImpl implements SQLColumnConstraint { - - public SQLNotNullConstraint(){ } @@ -34,4 +32,9 @@ public class SQLNotNullConstraint extends SQLConstraintImpl implements SQLColumn visitor.endVisit(this); } + public SQLNotNullConstraint clone() { + SQLNotNullConstraint x = new SQLNotNullConstraint(); + super.cloneTo(x); + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLNullConstraint.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLNullConstraint.java index ff51d8fbd9..e2f6516d1b 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLNullConstraint.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLNullConstraint.java @@ -27,4 +27,10 @@ public class SQLNullConstraint extends SQLConstraintImpl implements SQLColumnCon visitor.visit(this); visitor.endVisit(this); } + + public SQLNullConstraint clone() { + SQLNullConstraint x = new SQLNullConstraint(); + super.cloneTo(x); + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalDay.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalDay.java index f86b2d0eb2..26db9f1221 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalDay.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalDay.java @@ -58,4 +58,17 @@ public class OracleDataTypeIntervalDay extends SQLDataTypeImpl implements Oracle return fractionalSeconds; } + public OracleDataTypeIntervalDay clone() { + OracleDataTypeIntervalDay x = new OracleDataTypeIntervalDay(); + + super.cloneTo(x); + + for (SQLExpr arg : fractionalSeconds) { + arg.setParent(x); + x.fractionalSeconds.add(arg); + } + + return x; + } + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalYear.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalYear.java index 4a6cfae001..afbfb85cba 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalYear.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalYear.java @@ -16,6 +16,7 @@ package com.alibaba.druid.sql.dialect.oracle.ast; import com.alibaba.druid.sql.ast.SQLDataTypeImpl; +import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -38,4 +39,11 @@ public class OracleDataTypeIntervalYear extends SQLDataTypeImpl implements Oracl visitor.endVisit(this); } + public OracleDataTypeIntervalYear clone() { + OracleDataTypeIntervalYear x = new OracleDataTypeIntervalYear(); + + super.cloneTo(x); + + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java index 5914cc710d..db115e82c7 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java @@ -91,6 +91,10 @@ public class OracleCreateTableParser extends SQLCreateTableParser { lexer.nextToken(); stmt.setParallel(false); continue; + } else if (identifierEquals("PARALLEL")) { + lexer.nextToken(); + stmt.setParallel(true); + continue; } else if (lexer.token() == Token.CACHE) { lexer.nextToken(); stmt.setCache(Boolean.TRUE); 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 39bec5c7be..004fb70f21 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 @@ -2053,7 +2053,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS if (enable.booleanValue()) { print0(ucase ? " ENABLE" : " enable"); } else { - print0(ucase ? " DIABLE" : " diable"); + print0(ucase ? " DISABLE" : " disable"); } } diff --git a/src/main/java/com/alibaba/druid/util/ListDG.java b/src/main/java/com/alibaba/druid/util/ListDG.java index c01c3ee897..bac07df8b6 100644 --- a/src/main/java/com/alibaba/druid/util/ListDG.java +++ b/src/main/java/com/alibaba/druid/util/ListDG.java @@ -26,6 +26,16 @@ package com.alibaba.druid.util; import java.util.*; public class ListDG { + public static class Edge { + public Object from; + public Object to; + + public Edge(Object from, Object to) { + this.from = from; + this.to = to; + } + } + // 邻接表中表对应的链表的顶点 private class ENode { int ivex; // 该边所指向的顶点的位置 @@ -47,7 +57,7 @@ public class ListDG { * vexs -- 顶点数组 * edges -- 边数组 */ - public ListDG(List vexs, List edges) { + public ListDG(List vexs, List edges) { // 初始化"顶点数"和"边数" int vlen = vexs.size(); @@ -67,11 +77,11 @@ public class ListDG { // 初始化"边" for (int i = 0; i < elen; i++) { // 读取边的起始顶点和结束顶点 - Object c1 = edges.get(i)[0]; - Object c2 = edges.get(i)[1]; + Object c1 = edges.get(i).from; + Object c2 = edges.get(i).to; // 读取边的起始顶点和结束顶点 - int p1 = getPosition(edges.get(i)[0]); - int p2 = getPosition(edges.get(i)[1]); + int p1 = getPosition(edges.get(i).from); + int p2 = getPosition(edges.get(i).to); // 初始化node1 ENode node1 = new ENode(); @@ -112,7 +122,6 @@ public class ListDG { ENode node; visited[i] = true; - System.out.printf("%c ", mVexs.get(i).data); node = mVexs.get(i).firstEdge; while (node != null) { if (!visited[node.ivex]) @@ -131,12 +140,10 @@ public class ListDG { for (int i = 0; i < mVexs.size(); i++) visited[i] = false; - System.out.printf("== DFS: "); for (int i = 0; i < mVexs.size(); i++) { if (!visited[i]) DFS(i, visited); } - System.out.printf("\n"); } /* @@ -151,7 +158,6 @@ public class ListDG { for (int i = 0; i < mVexs.size(); i++) visited[i] = false; - System.out.printf("== BFS: "); for (int i = 0; i < mVexs.size(); i++) { if (!visited[i]) { visited[i] = true; @@ -174,7 +180,6 @@ public class ListDG { } } } - System.out.printf("\n"); } /* @@ -189,11 +194,10 @@ public class ListDG { System.out.printf("%d(%c) ", node.ivex, mVexs.get(node.ivex).data); node = node.nextEdge; } - System.out.printf("\n"); } } - public int topologicalSort() { + public boolean topologicalSort() { return topologicalSort(new Object[mVexs.size()]); } @@ -201,11 +205,10 @@ public class ListDG { * 拓扑排序 * * 返回值: - * -1 -- 失败(由于内存不足等原因导致) - * 0 -- 成功排序,并输入结果 - * 1 -- 失败(该有向图是有环的) + * true 成功排序,并输入结果 + * false 失败(该有向图是有环的) */ - public int topologicalSort(Object[] tops) { + public boolean topologicalSort(Object[] tops) { int index = 0; int num = mVexs.size(); int[] ins; // 入度数组 @@ -250,30 +253,22 @@ public class ListDG { } if(index != num) { - // System.out.printf("Graph has a cycle\n"); - return 1; + return false; } - // 打印拓扑排序结果 -// System.out.printf("== TopSort: "); -// for(int i = 0; i < num; i ++) { -// System.out.printf("%c ", tops[i]); -// } -// System.out.printf("\n"); - - return 0; + return true; } public static void main(String[] args) { Object[] vexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}; - Object[][] edges = new Object[][]{ - {vexs[0], vexs[6]}, - {vexs[1], vexs[0]}, - {vexs[1], vexs[3]}, - {vexs[2], vexs[5]}, - {vexs[2], vexs[6]}, - {vexs[3], vexs[4]}, - {vexs[3], vexs[5]}}; + Edge[] edges = new Edge[]{ + new Edge(vexs[0], vexs[6]), + new Edge(vexs[1], vexs[0]), + new Edge(vexs[1], vexs[3]), + new Edge(vexs[2], vexs[5]), + new Edge(vexs[2], vexs[6]), + new Edge(vexs[3], vexs[4]), + new Edge(vexs[3], vexs[5])}; ListDG pG; // 自定义"图"(输入矩阵队列) diff --git a/src/main/resources/META-INF/druid/parser/mysql/keywords b/src/main/resources/META-INF/druid/parser/mysql/keywords index 47da8234b5..6c4d5d0fa6 100644 --- a/src/main/resources/META-INF/druid/parser/mysql/keywords +++ b/src/main/resources/META-INF/druid/parser/mysql/keywords @@ -239,6 +239,7 @@ longtext loop low_priority match +maxvalue max_connections_per_hour max_queries_per_hour max_rows @@ -257,6 +258,7 @@ migrate minute minute_microsecond minute_second +minvalue mod modifies modify @@ -326,6 +328,7 @@ processlist purge quarter query +range read reads read_only diff --git a/src/test/java/com/alibaba/druid/bvt/sql/CreateCompareTest_cycle.java b/src/test/java/com/alibaba/druid/bvt/sql/CreateCompareTest_cycle.java new file mode 100644 index 0000000000..6ddf2f4bb0 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/CreateCompareTest_cycle.java @@ -0,0 +1,100 @@ +package com.alibaba.druid.bvt.sql; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement; +import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; + +import java.util.List; + +/** + * Created by wenshao on 18/07/2017. + */ +public class CreateCompareTest_cycle extends TestCase { + public void test_0() throws Exception { + String sql = "CREATE TABLE t0 (\n" + + "\tint bigint\n" + + ");\n" + + "\n" + + "CREATE TABLE t1 (\n" + + "\tint bigint\n" + + ");\n" + + "CREATE TABLE t2 (\n" + + "\tint bigint,\n" + + "\tFOREIGN KEY (id)\n" + + "\t\tREFERENCES t1 (id)\n" + + ");\n" + + "\n" + + "CREATE TABLE t3 (\n" + + "\tint bigint,\n" + + "\tFOREIGN KEY (id)\n" + + "\t\tREFERENCES t2 (id)\n" + + ");\n" + + "\n" + + "CREATE TABLE t4 (\n" + + "\tint bigint,\n" + + "\tFOREIGN KEY (id)\n" + + "\t\tREFERENCES t3 (id),\n" + + "\tFOREIGN KEY (id)\n" + + "\t\tREFERENCES t4 (id)\n" + + ");\n" + + "\n" + + "CREATE TABLE t5 (\n" + + "\tint bigint,\n" + + "\tFOREIGN KEY (id)\n" + + "\t\tREFERENCES t4 (id)\n" + + ");\n" + + "\n" + + "CREATE TABLE t6 (\n" + + "\tint bigint,\n" + + "\tFOREIGN KEY (id)\n" + + "\t\tREFERENCES t5 (id)\n" + + ");\n" + + "\n" + + "CREATE TABLE t7 (\n" + + "\tint bigint,\n" + + "\tFOREIGN KEY (id)\n" + + "\t\tREFERENCES t6 (id)\n" + + ");\n" + + "\n" + + "\n" + + "CREATE TABLE t8 (\n" + + "\tint bigint,\n" + + "\tFOREIGN KEY (id)\n" + + "\t\tREFERENCES t7 (id)\n" + + ");\n" + + "\n" + + "CREATE TABLE t9 (\n" + + "\tint bigint,\n" + + "\tFOREIGN KEY (id)\n" + + "\t\tREFERENCES t8 (id)\n" + + ");"; + + List stmtList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + + + SQLCreateTableStatement.sort(stmtList); + + String sortedSql = SQLUtils.toSQLString(stmtList, JdbcConstants.ORACLE); + System.out.println(sortedSql); + + assertEquals("t0", ((SQLCreateTableStatement)stmtList.get(9)).getName().getSimpleName()); + assertEquals("t9", ((SQLCreateTableStatement)stmtList.get(8)).getName().getSimpleName()); + assertEquals("t8", ((SQLCreateTableStatement)stmtList.get(7)).getName().getSimpleName()); + assertEquals("t7", ((SQLCreateTableStatement)stmtList.get(6)).getName().getSimpleName()); + assertEquals("t6", ((SQLCreateTableStatement)stmtList.get(5)).getName().getSimpleName()); + assertEquals("t5", ((SQLCreateTableStatement)stmtList.get(4)).getName().getSimpleName()); + assertEquals("t4", ((SQLCreateTableStatement)stmtList.get(3)).getName().getSimpleName()); + assertEquals("t3", ((SQLCreateTableStatement)stmtList.get(2)).getName().getSimpleName()); + assertEquals("t2", ((SQLCreateTableStatement)stmtList.get(1)).getName().getSimpleName()); + assertEquals("t1", ((SQLCreateTableStatement)stmtList.get(0)).getName().getSimpleName()); + + assertEquals("t4", ((SQLAlterTableStatement)stmtList.get(10)).getName().getSimpleName()); + + assertEquals(11, stmtList.size()); + + + + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest74.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest74.java new file mode 100644 index 0000000000..93a5aa6d17 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest74.java @@ -0,0 +1,139 @@ +/* + * Copyright 1999-2017 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.create; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class OracleCreateTableTest74 extends OracleTest { + + public void test_types() throws Exception { + String sql = // + "CREATE TABLE \"WEB_FPXX\".\"XX_MX_0901\" \n" + + " (\t\"NSRSBH\" VARCHAR2(20) NOT NULL ENABLE, \n" + + "\t\"SBRQ\" DATE NOT NULL ENABLE, \n" + + "\t\"TBRQ\" DATE, \n" + + "\t\"SSSQQ\" DATE NOT NULL ENABLE, \n" + + "\t\"FPDM\" CHAR(10) NOT NULL ENABLE, \n" + + "\t\"FPHM\" CHAR(8) NOT NULL ENABLE, \n" + + "\t\"KPRQ\" DATE, \n" + + "\t\"JE\" NUMBER(14,2) NOT NULL ENABLE, \n" + + "\t\"SE\" NUMBER(14,2) NOT NULL ENABLE, \n" + + "\t\"GHF_NSRSBH\" VARCHAR2(20) NOT NULL ENABLE, \n" + + "\t\"ZF_BZ\" CHAR(1) NOT NULL ENABLE, \n" + + "\t\"SWJG_DM\" CHAR(11) NOT NULL ENABLE, \n" + + "\t\"BZ\" CHAR(1), \n" + + "\t\"FP_LB\" VARCHAR2(4), \n" + + "\t CONSTRAINT \"PK_XX_MX_0901\" PRIMARY KEY (\"FPDM\", \"FPHM\")\n" + + " USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS \n" + + " STORAGE(INITIAL 1048576 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645\n" + + " PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1\n" + + " BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)\n" + + " TABLESPACE \"FPXX_IDX\" ENABLE\n" + + " ) SEGMENT CREATION IMMEDIATE \n" + + " PCTFREE 10 PCTUSED 40 INITRANS 2 MAXTRANS 255 \n" + + " NOCOMPRESS NOLOGGING\n" + + " STORAGE(INITIAL 24576 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645\n" + + " PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1\n" + + " BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)\n" + + " TABLESPACE \"FPXX_DAT\" \n" + + " CACHE PARALLEL "; + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + SQLStatement stmt = statementList.get(0); + print(statementList); + + assertEquals(1, statementList.size()); +// + assertEquals("CREATE TABLE \"WEB_FPXX\".\"XX_MX_0901\" (\n" + + "\t\"NSRSBH\" VARCHAR2(20) NOT NULL ENABLE,\n" + + "\t\"SBRQ\" DATE NOT NULL ENABLE,\n" + + "\t\"TBRQ\" DATE,\n" + + "\t\"SSSQQ\" DATE NOT NULL ENABLE,\n" + + "\t\"FPDM\" CHAR(10) NOT NULL ENABLE,\n" + + "\t\"FPHM\" CHAR(8) NOT NULL ENABLE,\n" + + "\t\"KPRQ\" DATE,\n" + + "\t\"JE\" NUMBER(14, 2) NOT NULL ENABLE,\n" + + "\t\"SE\" NUMBER(14, 2) NOT NULL ENABLE,\n" + + "\t\"GHF_NSRSBH\" VARCHAR2(20) NOT NULL ENABLE,\n" + + "\t\"ZF_BZ\" CHAR(1) NOT NULL ENABLE,\n" + + "\t\"SWJG_DM\" CHAR(11) NOT NULL ENABLE,\n" + + "\t\"BZ\" CHAR(1),\n" + + "\t\"FP_LB\" VARCHAR2(4),\n" + + "\tCONSTRAINT \"PK_XX_MX_0901\" PRIMARY KEY (\"FPDM\", \"FPHM\")\n" + + "\t\tUSING INDEX\n" + + "\t\tPCTFREE 10\n" + + "\t\tINITRANS 2\n" + + "\t\tMAXTRANS 255\n" + + "\t\tTABLESPACE \"FPXX_IDX\"\n" + + "\t\tSTORAGE (\n" + + "\t\t\tINITIAL 1048576\n" + + "\t\t\tNEXT 1048576\n" + + "\t\t\tMINEXTENTS 1\n" + + "\t\t\tMAXEXTENTS 2147483645\n" + + "\t\t\tPCTINCREASE 0\n" + + "\t\t\tFREELISTS 1\n" + + "\t\t\tFREELIST GROUPS 1\n" + + "\t\t\tBUFFER_POOL DEFAULT\n" + + "\t\t\tFLASH_CACHE DEFAULT\n" + + "\t\t\tCELL_FLASH_CACHE DEFAULT\n" + + "\t\t)\n" + + "\t\tCOMPUTE STATISTICS\n" + + "\t\tENABLE\n" + + ")\n" + + "PCTFREE 10\n" + + "PCTUSED 40\n" + + "INITRANS 2\n" + + "MAXTRANS 255\n" + + "NOCOMPRESS\n" + + "NOLOGGING\n" + + "TABLESPACE \"FPXX_DAT\"\n" + + "STORAGE (\n" + + "\tINITIAL 24576\n" + + "\tNEXT 1048576\n" + + "\tMINEXTENTS 1\n" + + "\tMAXEXTENTS 2147483645\n" + + "\tPCTINCREASE 0\n" + + "\tFREELISTS 1\n" + + "\tFREELIST GROUPS 1\n" + + "\tBUFFER_POOL DEFAULT\n" + + "\tFLASH_CACHE DEFAULT\n" + + "\tCELL_FLASH_CACHE DEFAULT\n" + + ")\n" + + "PARALLEL\n" + + "CACHE",// + SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE)); +// +// SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ORACLE); +// stmt.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()); +// +// assertEquals(1, visitor.getTables().size()); +// +// assertEquals(3, visitor.getColumns().size()); +// +// assertTrue(visitor.getColumns().contains(new TableStat.Column("JWGZPT.A", "XM"))); + } +}