diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAssignItem.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAssignItem.java new file mode 100644 index 0000000000..3b6227b34c --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAssignItem.java @@ -0,0 +1,53 @@ +package com.alibaba.druid.sql.ast.statement; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLObjectImpl; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class SQLAssignItem extends SQLObjectImpl { + + private static final long serialVersionUID = 1L; + + private SQLExpr target; + private SQLExpr value; + + public SQLAssignItem(){ + } + + public SQLAssignItem(SQLExpr target, SQLExpr value){ + this.target = target; + this.value = value; + } + + public SQLExpr getTarget() { + return target; + } + + public void setTarget(SQLExpr target) { + this.target = target; + } + + public SQLExpr getValue() { + return value; + } + + public void setValue(SQLExpr value) { + this.value = value; + } + + public void output(StringBuffer buf) { + target.output(buf); + buf.append(" = "); + value.output(buf); + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, this.target); + acceptChild(visitor, this.value); + } + visitor.endVisit(this); + } + +} \ No newline at end of file diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java index 3b11c60b4b..d285ccccff 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; -import com.alibaba.druid.sql.ast.SQLObjectImpl; import com.alibaba.druid.sql.ast.SQLStatementImpl; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -27,20 +26,20 @@ public class SQLSetStatement extends SQLStatementImpl { private static final long serialVersionUID = 1L; - private List items = new ArrayList(); + private List items = new ArrayList(); public SQLSetStatement(){ } public SQLSetStatement(SQLExpr target, SQLExpr value) { - this.items.add(new Item(target, value)); + this.items.add(new SQLAssignItem(target, value)); } - public List getItems() { + public List getItems() { return items; } - public void setItems(List items) { + public void setItems(List items) { this.items = items; } @@ -60,56 +59,8 @@ public class SQLSetStatement extends SQLStatementImpl { buf.append(", "); } - Item item = items.get(i); + SQLAssignItem item = items.get(i); item.output(buf); } } - - public static class Item extends SQLObjectImpl { - - private static final long serialVersionUID = 1L; - - private SQLExpr target; - private SQLExpr value; - - public Item(){ - } - - public Item(SQLExpr target, SQLExpr value){ - this.target = target; - this.value = value; - } - - public SQLExpr getTarget() { - return target; - } - - public void setTarget(SQLExpr target) { - this.target = target; - } - - public SQLExpr getValue() { - return value; - } - - public void setValue(SQLExpr value) { - this.value = value; - } - - public void output(StringBuffer buf) { - target.output(buf); - buf.append(" = "); - value.output(buf); - } - - @Override - protected void accept0(SQLASTVisitor visitor) { - if (visitor.visit(this)) { - acceptChild(visitor, this.target); - acceptChild(visitor, this.value); - } - visitor.endVisit(this); - } - - } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterSessionStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterSessionStatement.java new file mode 100644 index 0000000000..608f979fbb --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterSessionStatement.java @@ -0,0 +1,31 @@ +package com.alibaba.druid.sql.dialect.oracle.ast.stmt; + +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.druid.sql.ast.statement.SQLAssignItem; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; + +public class OracleAlterSessionStatement extends OracleStatementImpl { + + private static final long serialVersionUID = 1L; + + private List items = new ArrayList(); + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, items); + } + visitor.endVisit(this); + } + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMethodInvokeStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMethodInvokeStatement.java new file mode 100644 index 0000000000..2f6a549afe --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMethodInvokeStatement.java @@ -0,0 +1,37 @@ +package com.alibaba.druid.sql.dialect.oracle.ast.stmt; + +import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; + +public class OracleMethodInvokeStatement extends OracleStatementImpl { + + private static final long serialVersionUID = 1L; + + private SQLMethodInvokeExpr expr; + + public OracleMethodInvokeStatement(){ + + } + + public OracleMethodInvokeStatement(SQLMethodInvokeExpr expr){ + this.expr = expr; + } + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, expr); + } + visitor.endVisit(this); + + } + + public SQLMethodInvokeExpr getExpr() { + return expr; + } + + public void setExpr(SQLMethodInvokeExpr expr) { + this.expr = expr; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleTruncateStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleTruncateStatement.java new file mode 100644 index 0000000000..7a319ee4f8 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleTruncateStatement.java @@ -0,0 +1,18 @@ +package com.alibaba.druid.sql.dialect.oracle.ast.stmt; + +import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class OracleTruncateStatement extends SQLTruncateStatement implements OracleStatement { + + private static final long serialVersionUID = 1L; + + @Override + protected void accept0(SQLASTVisitor visitor) { + this.accept0((OracleASTVisitor) visitor); + } + + public void accept0(OracleASTVisitor visitor) { + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java index 5561030682..f368222dc9 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java @@ -120,6 +120,7 @@ public class OracleLexer extends Lexer { map.put("MODE", Token.MODE); map.put("WAIT", Token.WAIT); map.put("NOWAIT", Token.NOWAIT); + map.put("SESSION", Token.SESSION); DEFAULT_ORACLE_KEYWORDS = new Keywords(map); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java index 128a4bfca0..23e67bee81 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java @@ -572,6 +572,38 @@ public class OracleSelectParser extends SQLSelectParser { groupBy.setHaving(this.createExprParser().expr()); } + queryBlock.setGroupBy(groupBy); + } else if (lexer.token() == (Token.HAVING)) { + lexer.nextToken(); + + SQLSelectGroupByClause groupBy = new SQLSelectGroupByClause(); + groupBy.setHaving(this.createExprParser().expr()); + + if (lexer.token() == (Token.GROUP)) { + lexer.nextToken(); + accept(Token.BY); + + for (;;) { + if (identifierEquals("GROUPING")) { + GroupingSetExpr groupingSet = new GroupingSetExpr(); + lexer.nextToken(); + acceptIdentifier("SETS"); + accept(Token.LPAREN); + createExprParser().exprList(groupingSet.getParameters()); + accept(Token.RPAREN); + groupBy.getItems().add(groupingSet); + } else { + groupBy.getItems().add(this.createExprParser().expr()); + } + + if (!(lexer.token() == (Token.COMMA))) { + break; + } + + lexer.nextToken(); + } + } + queryBlock.setGroupBy(groupBy); } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java index cca3126751..4f8b6a2522 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java @@ -22,6 +22,7 @@ import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; +import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; import com.alibaba.druid.sql.ast.statement.SQLInsertInto; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; @@ -31,14 +32,16 @@ import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; import com.alibaba.druid.sql.dialect.oracle.ast.OracleHint; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterSessionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleBlockStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement.LockMode; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMethodInvokeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OraclePLSQLCommitStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement.LockMode; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLStatementParser; @@ -60,7 +63,7 @@ public class OracleStatementParser extends SQLStatementParser { protected OracleExprParser createExprParser() { return new OracleExprParser(lexer); } - + protected void parseInsert0_hinits(SQLInsertInto insertStatement) { if (insertStatement instanceof OracleInsertStatement) { OracleInsertStatement stmt = (OracleInsertStatement) insertStatement; @@ -119,7 +122,8 @@ public class OracleStatementParser extends SQLStatementParser { } if (lexer.token() == Token.ALTER) { - throw new ParserException("TODO"); + statementList.add(parserAlter()); + continue; } if (lexer.token() == Token.WITH) { @@ -146,6 +150,11 @@ public class OracleStatementParser extends SQLStatementParser { statementList.add(this.parseLock()); continue; } + + if (lexer.token() == Token.TRUNCATE) { + statementList.add(this.parseTruncate()); + continue; + } if (lexer.token() == Token.VARIANT) { SQLExpr variant = this.exprParser.primary(); @@ -164,10 +173,42 @@ public class OracleStatementParser extends SQLStatementParser { statementList.add(stmt); continue; } + + if (lexer.token() == Token.IDENTIFIER) { + SQLExpr expr = exprParser.expr(); + if (expr instanceof SQLMethodInvokeExpr) { + OracleMethodInvokeStatement stmt = new OracleMethodInvokeStatement((SQLMethodInvokeExpr) expr); + statementList.add(stmt); + continue; + } else { + throw new ParserException("expr : " + expr); + } + } throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } } + + public SQLStatement parseTruncate() { + return super.parseTruncate(); + } + + public OracleStatement parserAlter() { + accept(Token.ALTER); + if (lexer.token() == Token.SESSION) { + lexer.nextToken(); + + OracleAlterSessionStatement stmt = new OracleAlterSessionStatement(); + if (lexer.token() == Token.SET) { + lexer.nextToken(); + parseAssignItems(stmt.getItems()); + } else { + throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); + } + return stmt; + } + throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); + } public OracleLockTableStatement parseLock() { accept(Token.LOCK); @@ -185,7 +226,7 @@ public class OracleStatementParser extends SQLStatementParser { lexer.nextToken(); } accept(Token.MODE); - + if (lexer.token() == Token.NOWAIT) { lexer.nextToken(); } else if (lexer.token() == Token.WAIT) { @@ -313,9 +354,14 @@ public class OracleStatementParser extends SQLStatementParser { public OracleStatement parseInsert() { accept(Token.INSERT); + List hints = new ArrayList(); + + this.createExprParser().parseHints(hints); + if (lexer.token() == Token.INTO) { OracleInsertStatement stmt = new OracleInsertStatement(); - + stmt.setHints(hints); + parseInsert0(stmt); stmt.setReturning(parseReturningClause()); @@ -324,10 +370,12 @@ public class OracleStatementParser extends SQLStatementParser { return stmt; } - return parseMultiInsert(); + OracleMultiInsertStatement stmt = parseMultiInsert(); + stmt.setHints(hints); + return stmt; } - public OracleStatement parseMultiInsert() { + public OracleMultiInsertStatement parseMultiInsert() { OracleMultiInsertStatement stmt = new OracleMultiInsertStatement(); if (lexer.token() == Token.ALL) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVIsitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVIsitorAdapter.java index e303105fde..4e0effd04e 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVIsitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVIsitorAdapter.java @@ -36,6 +36,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIsSetExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleOuterExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleTimestampExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterSessionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleBlockStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleConstraintState; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; @@ -44,6 +45,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeUpdateClause; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMethodInvokeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem; @@ -700,85 +702,85 @@ public class OracleASTVIsitorAdapter extends SQLASTVisitorAdapter implements Ora public void endVisit(OracleErrorLoggingClause x) { } - + @Override public boolean visit(OracleReturningClause x) { return true; } - + @Override public void endVisit(OracleReturningClause x) { - + } - + @Override public boolean visit(OracleInsertStatement x) { return true; } - + @Override public void endVisit(OracleInsertStatement x) { - + } - + @Override public boolean visit(InsertIntoClause x) { return true; } - + @Override public void endVisit(InsertIntoClause x) { - + } - + @Override public boolean visit(OracleMultiInsertStatement x) { return true; } - + @Override public void endVisit(OracleMultiInsertStatement x) { - + } - + @Override public boolean visit(ConditionalInsertClause x) { return true; } - + @Override public void endVisit(ConditionalInsertClause x) { - + } - + @Override public boolean visit(ConditionalInsertClauseItem x) { return true; } - + @Override public void endVisit(ConditionalInsertClauseItem x) { - + } - + @Override public boolean visit(OracleSelectQueryBlock x) { return true; } - + @Override public void endVisit(OracleSelectQueryBlock x) { - + } - + @Override public boolean visit(OracleBlockStatement x) { return true; } - + @Override public void endVisit(OracleBlockStatement x) { - + } @Override @@ -788,7 +790,27 @@ public class OracleASTVIsitorAdapter extends SQLASTVisitorAdapter implements Ora @Override public void endVisit(OracleLockTableStatement x) { - + + } + + @Override + public boolean visit(OracleAlterSessionStatement x) { + return true; + } + + @Override + public void endVisit(OracleAlterSessionStatement x) { + + } + + @Override + public boolean visit(OracleMethodInvokeStatement x) { + return true; + } + + @Override + public void endVisit(OracleMethodInvokeStatement x) { + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java index b587dc5bcb..ee59ef25e6 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java @@ -42,12 +42,14 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIsSetExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleOuterExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleTimestampExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterSessionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleBlockStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleConstraintState; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMethodInvokeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem; @@ -345,4 +347,12 @@ public interface OracleASTVisitor extends SQLASTVisitor { boolean visit(OracleLockTableStatement x); void endVisit(OracleLockTableStatement x); + + boolean visit(OracleAlterSessionStatement x); + + void endVisit(OracleAlterSessionStatement x); + + boolean visit(OracleMethodInvokeStatement x); + + void endVisit(OracleMethodInvokeStatement x); } 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 1e84973ee3..363fdcc16a 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 @@ -68,6 +68,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIsSetExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleOuterExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleTimestampExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterSessionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleBlockStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleConstraintState; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; @@ -76,6 +77,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeUpdateClause; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMethodInvokeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem; @@ -1669,4 +1671,27 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public void endVisit(OracleLockTableStatement x) { } + + @Override + public boolean visit(OracleAlterSessionStatement x) { + print("ALTER SESSION SET "); + printAndAccept(x.getItems(), ", "); + return false; + } + + @Override + public void endVisit(OracleAlterSessionStatement x) { + + } + + @Override + public boolean visit(OracleMethodInvokeStatement x) { + x.getExpr().accept(this); + return false; + } + + @Override + public void endVisit(OracleMethodInvokeStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java index 9610f5f830..2b6a6eeea7 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java @@ -51,6 +51,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIsSetExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleOuterExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleTimestampExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterSessionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleBlockStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleConstraintState; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; @@ -59,6 +60,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeUpdateClause; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMethodInvokeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem; @@ -95,28 +97,28 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle if (expr instanceof OracleOuterExpr) { expr = ((OracleOuterExpr) expr).getExpr(); } - + return super.getColumn(expr); } - + public boolean visit(OracleSelectTableReference x) { SQLExpr expr = x.getExpr(); - + if (expr instanceof SQLMethodInvokeExpr) { SQLMethodInvokeExpr methodInvoke = (SQLMethodInvokeExpr) expr; if ("TABLE".equalsIgnoreCase(methodInvoke.getMethodName()) && methodInvoke.getParameters().size() == 1) { expr = methodInvoke.getParameters().get(0); } } - + Map aliasMap = aliasLocal.get(); - + if (expr instanceof SQLName) { String ident; if (expr instanceof SQLPropertyExpr) { String owner = ((SQLPropertyExpr) expr).getOwner().toString(); String name = ((SQLPropertyExpr) expr).getName(); - + if (aliasMap.containsKey(owner)) { owner = aliasMap.get(owner); } @@ -124,11 +126,11 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle } else { ident = expr.toString(); } - + if (subQueryMap.containsKey(ident)) { return false; } - + if ("DUAL".equalsIgnoreCase(ident)) { return false; } @@ -254,7 +256,7 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle if (x.getWhere() != null) { x.getWhere().setParent(x); } - + return visit((SQLSelectQueryBlock) x); } @@ -269,7 +271,7 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle return super.visit(x); } - + public boolean visit(SQLMethodInvokeExpr x) { accept(x.getParameters()); return false; @@ -287,7 +289,7 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle if ("+".equalsIgnoreCase(x.getName())) { return false; } - + if ("LEVEL".equals(x.getName())) { return false; } @@ -530,7 +532,7 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle if (x.getCondition() != null) { x.getCondition().accept(this); } - + for (SQLExpr item : x.getUsing()) { if (item instanceof SQLIdentifierExpr) { String columnName = ((SQLIdentifierExpr) item).getName(); @@ -543,17 +545,17 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle relationship.setOperator("USING"); relationships.add(relationship); } - + if (leftTable != null) { columns.add(new Column(leftTable, columnName)); } - + if (rightTable != null) { columns.add(new Column(rightTable, columnName)); } } } - + return false; } @@ -1090,7 +1092,6 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle @Override public void endVisit(ConditionalInsertClauseItem x) { - } @Override @@ -1100,8 +1101,29 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle @Override public void endVisit(OracleBlockStatement x) { + + } + + @Override + public boolean visit(OracleAlterSessionStatement x) { + return false; + } + + @Override + public void endVisit(OracleAlterSessionStatement x) { + + } + + @Override + public boolean visit(OracleMethodInvokeStatement x) { + return false; + } + + @Override + public void endVisit(OracleMethodInvokeStatement x) { } + @Override public boolean visit(OracleLockTableStatement x) { String tableName = x.getTable().toString(); @@ -1109,9 +1131,9 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle this.tableStats.put(new TableStat.Name(tableName), stat); return false; } - + @Override public void endVisit(OracleLockTableStatement x) { - + } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java index 3b4f098b46..e5affa0b58 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -19,7 +19,6 @@ import static com.alibaba.druid.sql.parser.CharTypes.isFirstIdentifierChar; import static com.alibaba.druid.sql.parser.CharTypes.isIdentifierChar; import static com.alibaba.druid.sql.parser.CharTypes.isWhitespace; import static com.alibaba.druid.sql.parser.LayoutCharacters.EOI; -import static com.alibaba.druid.sql.parser.Token.COLON; import static com.alibaba.druid.sql.parser.Token.COLONEQ; import static com.alibaba.druid.sql.parser.Token.COMMA; import static com.alibaba.druid.sql.parser.Token.EOF; 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 99d2e2ff80..a0a6ceaa1e 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -569,6 +569,12 @@ public class SQLExprParser extends SQLParser { if (lexer.token() == Token.DOT) { lexer.nextToken(); + + if (lexer.token() == Token.KEY) { + name = new SQLPropertyExpr(name, "KEY"); + lexer.nextToken(); + return name; + } if (lexer.token() != Token.LITERAL_ALIAS && lexer.token() != Token.IDENTIFIER) { throw new ParserException("error, " + lexer.token()); diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java index 234df9d221..3dfdbaedcb 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java @@ -65,7 +65,7 @@ public class SQLParser { return alias; } - if (lexer.token() == Token.YEAR || lexer.token() == Token.DAY) { + if (lexer.token() == Token.YEAR || lexer.token() == Token.DAY || lexer.token() == Token.KEY) { alias = lexer.token.name(); lexer.nextToken(); return alias; diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java index 014a178d02..e48d34a8ee 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java @@ -167,6 +167,12 @@ public class SQLSelectParser extends SQLParser { groupBy.setHaving(expr()); } + queryBlock.setGroupBy(groupBy); + } else if (lexer.token() == (Token.HAVING)) { + lexer.nextToken(); + + SQLSelectGroupByClause groupBy = new SQLSelectGroupByClause(); + groupBy.setHaving(this.createExprParser().expr()); queryBlock.setGroupBy(groupBy); } } 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 0fd7ad4ca6..ea6b7d98ef 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -22,6 +22,7 @@ import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; +import com.alibaba.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement; @@ -32,6 +33,7 @@ import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLSetStatement; import com.alibaba.druid.sql.ast.statement.SQLTableSource; +import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; @@ -157,7 +159,23 @@ public class SQLStatementParser extends SQLParser { } public SQLStatement parseTruncate() { - throw new ParserException("TODO " + lexer.token()); + accept(Token.TRUNCATE); + accept(Token.TABLE); + SQLTruncateStatement stmt = new SQLTruncateStatement(); + + for (;;) { + SQLName name = this.exprParser.name(); + stmt.getTableNames().add(name); + + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } + + break; + } + + return stmt; } public SQLStatement parseInsert() { @@ -236,13 +254,19 @@ public class SQLStatementParser extends SQLParser { accept(Token.SET); SQLSetStatement stmt = new SQLSetStatement(); + parseAssignItems(stmt.getItems()); + + return stmt; + } + + public void parseAssignItems(List items) { for (;;) { - SQLSetStatement.Item item = new SQLSetStatement.Item(); + SQLAssignItem item = new SQLAssignItem(); item.setTarget(exprParser.primary()); accept(Token.EQ); item.setValue(exprParser.expr()); - stmt.getItems().add(item); + items.add(item); if (lexer.token() == Token.COMMA) { lexer.nextToken(); @@ -251,8 +275,6 @@ public class SQLStatementParser extends SQLParser { break; } } - - return stmt; } public SQLStatement parseCreate() throws ParserException { diff --git a/src/main/java/com/alibaba/druid/sql/parser/Token.java b/src/main/java/com/alibaba/druid/sql/parser/Token.java index 7e224d24b3..128768ba15 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -155,6 +155,8 @@ public enum Token { EXCLUSIVE("EXCLUSIVE"), MODE("MODE"), WAIT("WAIT"), + ADVISE("ADVISE"), + SESSION("SESSION"), // transact-sql TOP("TOP"), 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 a1f4596448..9552454a25 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -53,6 +53,7 @@ import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.druid.sql.ast.expr.SQLSomeExpr; import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.druid.sql.ast.statement.NotNullConstraint; import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLColumnConstraint; @@ -746,7 +747,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { } @Override - public boolean visit(SQLSetStatement.Item x) { + public boolean visit(SQLAssignItem x) { x.getTarget().accept(this); print(" = "); x.getValue().accept(this); 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 31fcd89a19..69a17a2792 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java @@ -50,6 +50,7 @@ import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.druid.sql.ast.expr.SQLSomeExpr; import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.druid.sql.ast.statement.NotNullConstraint; import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; @@ -281,9 +282,9 @@ public interface SQLASTVisitor { boolean visit(SQLSetStatement x); - void endVisit(SQLSetStatement.Item x); + void endVisit(SQLAssignItem x); - boolean visit(SQLSetStatement.Item x); + boolean visit(SQLAssignItem x); void endVisit(SQLCallStatement 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 865c35a0d9..86dfc3005b 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -50,6 +50,7 @@ import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.druid.sql.ast.expr.SQLSomeExpr; import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.druid.sql.ast.statement.NotNullConstraint; import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; @@ -443,12 +444,12 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { } @Override - public void endVisit(SQLSetStatement.Item x) { + public void endVisit(SQLAssignItem x) { } @Override - public boolean visit(SQLSetStatement.Item x) { + public boolean visit(SQLAssignItem x) { return true; } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleAlterSessionTest.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleAlterSessionTest.java new file mode 100644 index 0000000000..851d403e5b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleAlterSessionTest.java @@ -0,0 +1,41 @@ +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 OracleAlterSessionTest extends OracleTest { + + public void test_0() throws Exception { + String sql = "alter session set current_schema=retl"; + + 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("employees@remote"))); + + Assert.assertEquals(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + +// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("bonuses", "employee_id"))); + } + +}