diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java index 52140be9a2..0302c48446 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -179,14 +179,14 @@ public class SQLStatementParser extends SQLParser { accept(Token.RPAREN); } - if (lexer.token() == (Token.VALUES)) { + if (lexer.token() == Token.VALUES) { lexer.nextToken(); accept(Token.LPAREN); SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(); this.exprParser.exprList(values.getValues()); insertStatement.setValues(values); accept(Token.RPAREN); - } else if (lexer.token() == (Token.SELECT)) { + } else if (lexer.token() == Token.SELECT || lexer.token() == Token.LPAREN) { SQLQueryExpr queryExpr = (SQLQueryExpr) this.createExprParser().expr(); insertStatement.setQuery(queryExpr.getSubQuery()); } @@ -196,7 +196,7 @@ public class SQLStatementParser extends SQLParser { public boolean parseStatementListDialect(List statementList) { return false; } - + public SQLStatement parseDropUser() throws ParserException { throw new ParserException("TODO " + lexer.token()); } @@ -344,6 +344,5 @@ public class SQLStatementParser extends SQLParser { createView.setSubQuery(new SQLSelectParser(this.lexer).select()); return createView; } - } 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 0d164f1c72..1f7af07501 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -397,6 +397,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { x.getSubQuery().accept(this); decrementIndent(); + } else if (x.getParent() instanceof ValuesClause) { + println(); + x.getSubQuery().accept(this); + println(); } else { print("("); incrementIndent(); @@ -784,7 +788,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { print(", "); } - x.getValues().get(i).accept(this); + SQLExpr expr = x.getValues().get(i); + expr.setParent(x); + expr.accept(this); } decrementIndent(); print(")"); diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java index 38b1cf3b7e..f32d91e206 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -38,12 +38,14 @@ import com.alibaba.druid.stat.TableStat; import com.alibaba.druid.stat.TableStat.Column; import com.alibaba.druid.stat.TableStat.Condition; import com.alibaba.druid.stat.TableStat.Mode; +import com.alibaba.druid.stat.TableStat.Relationship; public class SchemaStatVisitor extends SQLASTVisitorAdapter { protected final HashMap tableStats = new LinkedHashMap(); protected final Set columns = new LinkedHashSet(); protected final Set conditions = new LinkedHashSet(); + protected final Set relationships = new LinkedHashSet(); protected final Set orderByColumns = new LinkedHashSet(); protected final Set groupByColumns = new LinkedHashSet(); @@ -116,6 +118,10 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { return true; } + public Set getRelationships() { + return relationships; + } + public Set getOrderByColumns() { return orderByColumns; } @@ -143,6 +149,8 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { case IsNot: handleCondition(x.getLeft(), x.getOperator().name); handleCondition(x.getRight(), x.getOperator().name); + + handleRelationship(x.getLeft(), x.getOperator().name, x.getRight()); break; default: break; @@ -150,10 +158,41 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { return true; } + protected void handleRelationship(SQLExpr left, String operator, SQLExpr right) { + Column leftColumn = getColumn(left); + if (leftColumn == null) { + return; + } + + Column rightColumn = getColumn(right); + if (rightColumn == null) { + return; + } + + Relationship relationship = new Relationship(); + relationship.setLeft(leftColumn); + relationship.setRight(rightColumn); + relationship.setOperator(operator); + + this.relationships.add(relationship); + } + protected void handleCondition(SQLExpr expr, String operator) { + Column column = getColumn(expr); + if (column == null) { + return; + } + + Condition condition = new Condition(); + condition.setColumn(column); + condition.setOperator(operator); + this.conditions.add(condition); + } + + protected Column getColumn(SQLExpr expr) { Map aliasMap = aliasLocal.get(); if (aliasMap == null) { - return; + return null; } if (expr instanceof SQLPropertyExpr) { @@ -168,22 +207,13 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { } if (table != null) { - Condition condition = new Condition(); - condition.setColumn(new Column(table, column)); - condition.setOperator(operator); - this.conditions.add(condition); - } else { - Column sqlColumn = handleSubQueryColumn(tableName, column); - if (sqlColumn != null) { - Condition condition = new Condition(); - condition.setColumn(sqlColumn); - condition.setOperator(operator); - this.conditions.add(condition); - } + return new Column(table, column); } + + return handleSubQueryColumn(tableName, column); } - return; + return null; } if (expr instanceof SQLIdentifierExpr) { @@ -196,12 +226,11 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { } if (table != null) { - Condition condition = new Condition(); - condition.setColumn(new Column(table, column)); - condition.setOperator(operator); - this.conditions.add(condition); + return new Column(table, column); } } + + return null; } @Override diff --git a/src/main/java/com/alibaba/druid/stat/TableStat.java b/src/main/java/com/alibaba/druid/stat/TableStat.java index 2dd3b2ef5b..25c7ade638 100644 --- a/src/main/java/com/alibaba/druid/stat/TableStat.java +++ b/src/main/java/com/alibaba/druid/stat/TableStat.java @@ -112,7 +112,6 @@ public class TableStat { if (dropCount > 0) { buf.append("Drop"); } - return buf.toString(); } @@ -148,6 +147,89 @@ public class TableStat { } } + public static class Relationship { + + private Column left; + private Column right; + private String operator; + + public Column getLeft() { + return left; + } + + public void setLeft(Column left) { + this.left = left; + } + + public Column getRight() { + return right; + } + + public void setRight(Column right) { + this.right = right; + } + + public String getOperator() { + return operator; + } + + public void setOperator(String operator) { + this.operator = operator; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((left == null) ? 0 : left.hashCode()); + result = prime * result + ((operator == null) ? 0 : operator.hashCode()); + result = prime * result + ((right == null) ? 0 : right.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Relationship other = (Relationship) obj; + if (left == null) { + if (other.left != null) { + return false; + } + } else if (!left.equals(other.left)) { + return false; + } + if (operator == null) { + if (other.operator != null) { + return false; + } + } else if (!operator.equals(other.operator)) { + return false; + } + if (right == null) { + if (other.right != null) { + return false; + } + } else if (!right.equals(other.right)) { + return false; + } + return true; + } + + @Override + public String toString() { + return left + " " + operator + " " + right; + } + + } + public static class Condition { private Column column; diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleInsertTest.java similarity index 91% rename from src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest.java rename to src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleInsertTest.java index 616de6c0d2..c87968b225 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleInsertTest.java @@ -10,7 +10,7 @@ import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; import com.alibaba.druid.stat.TableStat; -public class OracleSelectTest extends OracleTest { +public class OracleInsertTest extends OracleTest { public void test_0() throws Exception { String sql = "INSERT INTO films VALUES ('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes');"; @@ -28,6 +28,7 @@ public class OracleSelectTest extends OracleTest { System.out.println("Tables : " + visitor.getTables()); System.out.println("fields : " + visitor.getColumns()); System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("films"))); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleInsertTest1.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleInsertTest1.java new file mode 100644 index 0000000000..bc6d315d57 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleInsertTest1.java @@ -0,0 +1,49 @@ +package com.alibaba.druid.bvt.sql.oracle; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.OracleTest; +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; + +public class OracleInsertTest1 extends OracleTest { + + public void test_0() throws Exception { + String sql = "INSERT INTO bonuses(employee_id)" + + " (SELECT e.employee_id FROM employees e, orders o" + + " WHERE e.employee_id = o.sales_rep_id" + + " GROUP BY e.employee_id); "; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + System.out.println(output(statementList)); + + Assert.assertEquals(1, statementList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + statemen.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()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("bonuses"))); + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees"))); + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("orders"))); + + Assert.assertEquals(3, visitor.getTables().size()); + Assert.assertEquals(3, visitor.getColumns().size()); + + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("bonuses", "employee_id"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "employee_id"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("orders", "sales_rep_id"))); + } + + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleMergeTest.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleMergeTest.java index b5d511d74e..ff6eb8ba30 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleMergeTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleMergeTest.java @@ -36,6 +36,7 @@ public class OracleMergeTest extends OracleTest { System.out.println("Tables : " + visitor.getTables()); System.out.println("fields : " + visitor.getColumns()); System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); Assert.assertEquals(2, visitor.getTables().size()); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest2.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest2.java index 9abafa7593..22a763cb3f 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest2.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleSelectTest2.java @@ -40,6 +40,7 @@ public class OracleSelectTest2 extends OracleTest { System.out.println("Tables : " + visitor.getTables()); System.out.println("fields : " + visitor.getColumns()); System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); Assert.assertEquals(2, visitor.getTables().size());