diff --git a/src/main/java/com/alibaba/druid/sql/SQLUtils.java b/src/main/java/com/alibaba/druid/sql/SQLUtils.java index 66a583f6d0..6bfc090ce1 100644 --- a/src/main/java/com/alibaba/druid/sql/SQLUtils.java +++ b/src/main/java/com/alibaba/druid/sql/SQLUtils.java @@ -425,7 +425,7 @@ public class SQLUtils { SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); List stmtList = parser.parseStatementList(); if (parser.getLexer().token() != Token.EOF) { - throw new DruidRuntimeException("syntax error : " + sql); + throw new ParserException("syntax error : " + sql); } return stmtList; } @@ -434,7 +434,7 @@ public class SQLUtils { SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, keepComments); List stmtList = parser.parseStatementList(); if (parser.getLexer().token() != Token.EOF) { - throw new DruidRuntimeException("syntax error : " + sql); + throw new ParserException("syntax error : " + sql); } return stmtList; } diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLDeclareItem.java b/src/main/java/com/alibaba/druid/sql/ast/SQLDeclareItem.java index 7a3a3ab1f2..323da37701 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLDeclareItem.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLDeclareItem.java @@ -33,6 +33,21 @@ public class SQLDeclareItem extends SQLObjectImpl { protected List tableElementList = new ArrayList(); + public SQLDeclareItem() { + + } + + public SQLDeclareItem(SQLExpr name, SQLDataType dataType) { + this.setName(name); + this.setDataType(dataType); + } + + public SQLDeclareItem(SQLExpr name, SQLDataType dataType, SQLExpr value) { + this.setName(name); + this.setDataType(dataType); + this.setValue(value); + } + @Override protected void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { @@ -49,6 +64,9 @@ public class SQLDeclareItem extends SQLObjectImpl { } public void setName(SQLExpr name) { + if (name != null) { + name.setParent(this); + } this.name = name; } @@ -57,6 +75,9 @@ public class SQLDeclareItem extends SQLObjectImpl { } public void setDataType(SQLDataType dataType) { + if (dataType != null) { + dataType.setParent(this); + } this.dataType = dataType; } @@ -65,6 +86,9 @@ public class SQLDeclareItem extends SQLObjectImpl { } public void setValue(SQLExpr value) { + if (value != null) { + value.setParent(this); + } this.value = value; } diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLParameter.java b/src/main/java/com/alibaba/druid/sql/ast/SQLParameter.java index f3582eabd8..6bd1d0c9ae 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLParameter.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLParameter.java @@ -37,6 +37,9 @@ public class SQLParameter extends SQLObjectImpl { } public void setDefaultValue(SQLExpr deaultValue) { + if (deaultValue != null) { + deaultValue.setParent(this); + } this.defaultValue = deaultValue; } @@ -45,6 +48,9 @@ public class SQLParameter extends SQLObjectImpl { } public void setName(SQLExpr name) { + if (name != null) { + name.setParent(this); + } this.name = name; } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateFunctionStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateFunctionStatement.java index 16029a6fd4..cbac85f3e2 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateFunctionStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateFunctionStatement.java @@ -40,6 +40,12 @@ public class SQLCreateFunctionStatement extends SQLStatementImpl { SQLDataType returnDataType; + // for mysql + + private String comment; + + private boolean deterministic = false; + @Override public void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { @@ -131,4 +137,20 @@ public class SQLCreateFunctionStatement extends SQLStatementImpl { } this.returnDataType = returnDataType; } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public boolean isDeterministic() { + return deterministic; + } + + public void setDeterministic(boolean deterministic) { + this.deterministic = deterministic; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDeclareStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDeclareStatement.java index 734e78e87c..b276ddd2c2 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDeclareStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDeclareStatement.java @@ -18,9 +18,7 @@ package com.alibaba.druid.sql.ast.statement; import java.util.ArrayList; import java.util.List; -import com.alibaba.druid.sql.ast.SQLDeclareItem; -import com.alibaba.druid.sql.ast.SQLStatement; -import com.alibaba.druid.sql.ast.SQLStatementImpl; +import com.alibaba.druid.sql.ast.*; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerObjectImpl; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatement; import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor; @@ -30,7 +28,17 @@ public class SQLDeclareStatement extends SQLStatementImpl { protected List items = new ArrayList(); - private String dbType; + public SQLDeclareStatement() { + + } + + public SQLDeclareStatement(SQLExpr name, SQLDataType dataType) { + this.addItem(new SQLDeclareItem(name, dataType)); + } + + public SQLDeclareStatement(SQLExpr name, SQLDataType dataType, SQLExpr value) { + this.addItem(new SQLDeclareItem(name, dataType, value)); + } @Override public void accept0(SQLASTVisitor visitor) { @@ -50,12 +58,4 @@ public class SQLDeclareStatement extends SQLStatementImpl { } this.items.add(item); } - - public String getDbType() { - return dbType; - } - - public void setDbType(String dbType) { - this.dbType = dbType; - } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLIfStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLIfStatement.java index de29dce6ad..b05bebd739 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLIfStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLIfStatement.java @@ -57,17 +57,15 @@ public class SQLIfStatement extends SQLStatementImpl { return statements; } - public void setStatements(List statements) { - this.statements = statements; - } - - public List getElseIfList() { - return elseIfList; + public void addStatement(SQLStatement statement) { + if (statement != null) { + statement.setParent(this); + } + this.statements.add(statement); } - - public void setElseIfList(List elseIfList) { - this.elseIfList = elseIfList; + public List getElseIfList() { + return elseIfList; } public Else getElseItem() { diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertInto.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertInto.java index 2129a3c87e..2911e8132c 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertInto.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertInto.java @@ -30,7 +30,7 @@ public abstract class SQLInsertInto extends SQLObjectImpl { protected final List columns = new ArrayList(); protected SQLSelect query; - protected List valuesList = new ArrayList(); + protected final List valuesList = new ArrayList(); public SQLInsertInto(){ @@ -105,7 +105,10 @@ public abstract class SQLInsertInto extends SQLObjectImpl { return valuesList; } - public void setValuesList(List valuesList) { - this.valuesList = valuesList; + public void addValueCause(ValuesClause valueClause) { + if (valueClause != null) { + valueClause.setParent(this); + } + valuesList.add(valueClause); } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLLoopStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLLoopStatement.java index 14e84958df..909b00d043 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLLoopStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLLoopStatement.java @@ -48,4 +48,10 @@ public class SQLLoopStatement extends SQLStatementImpl { this.labelName = labelName; } + public void addStatement(SQLStatement stmt) { + if (stmt != null) { + stmt.setParent(this); + } + statements.add(stmt); + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelect.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelect.java index 579222e7dc..da49f5a4d7 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelect.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelect.java @@ -80,6 +80,14 @@ public class SQLSelect extends SQLObjectImpl { this.query = query; } + public SQLSelectQueryBlock getQueryBlock() { + if (query instanceof SQLSelectQueryBlock) { + return (SQLSelectQueryBlock) query; + } + + return null; + } + public SQLOrderBy getOrderBy() { return this.orderBy; } 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 eac4dac556..831bda7028 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 @@ -20,7 +20,11 @@ import java.util.List; import com.alibaba.druid.sql.ast.SQLCommentHint; import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLStatementImpl; +import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; +import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; +import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLSetStatement extends SQLStatementImpl { @@ -45,6 +49,11 @@ public class SQLSetStatement extends SQLStatementImpl { this.items.add(new SQLAssignItem(target, value)); } + public static SQLSetStatement plus(SQLName target) { + SQLExpr value = new SQLBinaryOpExpr(target.clone(), SQLBinaryOperator.Add, new SQLIntegerExpr(1)); + return new SQLSetStatement(target, value); + } + public List getItems() { return items; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlLeaveStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlLeaveStatement.java index 4adabf666f..8e4f00379b 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlLeaveStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlLeaveStatement.java @@ -25,7 +25,15 @@ import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; public class MySqlLeaveStatement extends MySqlStatementImpl { private String labelName; - + + public MySqlLeaveStatement() { + + } + + public MySqlLeaveStatement(String labelName) { + this.labelName = labelName; + } + @Override public void accept0(MySqlASTVisitor visitor) { visitor.visit(this); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index b72b56495f..e90409b478 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -15,16 +15,8 @@ */ package com.alibaba.druid.sql.dialect.mysql.parser; -import com.alibaba.druid.sql.ast.SQLCommentHint; -import com.alibaba.druid.sql.ast.SQLDataTypeImpl; -import com.alibaba.druid.sql.ast.SQLDeclareItem; -import com.alibaba.druid.sql.ast.SQLExpr; -import com.alibaba.druid.sql.ast.SQLName; -import com.alibaba.druid.sql.ast.SQLOrderBy; -import com.alibaba.druid.sql.ast.SQLParameter; +import com.alibaba.druid.sql.ast.*; import com.alibaba.druid.sql.ast.SQLParameter.ParameterType; -import com.alibaba.druid.sql.ast.SQLPartition; -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.SQLCharExpr; @@ -355,6 +347,13 @@ public class MySqlStatementParser extends SQLStatementParser { return parseCreateProcedure(); } + if (lexer.token() == Token.FUNCTION) { + if (replace) { + lexer.reset(markBp, markChar, Token.CREATE); + } + return parseCreateFunction(); + } + throw new ParserException("TODO " + lexer.info()); } @@ -1750,6 +1749,7 @@ public class MySqlStatementParser extends SQLStatementParser { lexer.nextToken(); SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(); + values.setParent(stmt); stmt.getValuesList().add(values); for (; ; ) { stmt.addColumn(this.exprParser.name()); @@ -2100,7 +2100,7 @@ public class MySqlStatementParser extends SQLStatementParser { lexer.nextToken(); SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(); - insertStatement.getValuesList().add(values); + insertStatement.addValueCause(values); for (; ; ) { SQLName name = this.exprParser.name(); @@ -3141,6 +3141,61 @@ public class MySqlStatementParser extends SQLStatementParser { } + public SQLCreateFunctionStatement parseCreateFunction() { + SQLCreateFunctionStatement stmt = new SQLCreateFunctionStatement(); + stmt.setDbType(dbType); + + if (lexer.token() != Token.FUNCTION) { + if (identifierEquals("DEFINER")) { + lexer.nextToken(); + accept(Token.EQ); + SQLName definer = this.exprParser.name(); + stmt.setDefiner(definer); + } else { + accept(Token.CREATE); + if (lexer.token() == Token.OR) { + lexer.nextToken(); + accept(Token.REPLACE); + stmt.setOrReplace(true); + } + } + } + + accept(Token.FUNCTION); + + stmt.setName(this.exprParser.name()); + + if (lexer.token() == Token.LPAREN) {// match "(" + lexer.nextToken(); + parserParameters(stmt.getParameters(), stmt); + accept(Token.RPAREN);// match ")" + } + + acceptIdentifier("RETURNS"); + SQLDataType dataType = this.exprParser.parseDataType(); + stmt.setReturnDataType(dataType); + + for (;;) { + if (identifierEquals("DETERMINISTIC")) { + lexer.nextToken(); + stmt.setDeterministic(true); + continue; + } + + break; + } + + SQLStatement block; + if (lexer.token() == Token.BEGIN) { + block = this.parseBlock(); + } else { + block = this.parseStatement(); + } + + stmt.setBlock(block); + + return stmt; + } /** * parse create procedure statement */ @@ -3173,7 +3228,7 @@ public class MySqlStatementParser extends SQLStatementParser { if (lexer.token() == Token.LPAREN) {// match "(" lexer.nextToken(); - parserParameters(stmt.getParameters()); + parserParameters(stmt.getParameters(), stmt); accept(Token.RPAREN);// match ")" } SQLStatement block; @@ -3194,7 +3249,7 @@ public class MySqlStatementParser extends SQLStatementParser { * * @param parameters */ - private void parserParameters(List parameters) { + private void parserParameters(List parameters, SQLObject parent) { if (lexer.token() == Token.RPAREN) { return; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index ae670dbf7f..3466648fa4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -3587,4 +3587,46 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV } return false; } + + @Override + public boolean visit(SQLCreateFunctionStatement x) { + print0(ucase ? "CREATE FUNCTION " : "create function "); + x.getName().accept(this); + + int paramSize = x.getParameters().size(); + + if (paramSize > 0) { + print0(" ("); + incrementIndent(); + println(); + + for (int i = 0; i < paramSize; ++i) { + if (i != 0) { + print0(", "); + println(); + } + SQLParameter param = x.getParameters().get(i); + param.accept(this); + } + + decrementIndent(); + println(); + print(')'); + } + + println(); + print(ucase ? "RETURNS " : "returns "); + x.getReturnDataType().accept(this); + + if (x.isDeterministic()) { + print(ucase ? " DETERMINISTIC" : " deterministic"); + } + + SQLStatement block = x.getBlock(); + + println(); + + block.accept(this); + return false; + } } // diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateIndexStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateIndexStatement.java index 9abe48279a..33e7480c81 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateIndexStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateIndexStatement.java @@ -17,12 +17,14 @@ package com.alibaba.druid.sql.dialect.oracle.ast.stmt; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.SQLObject; import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributes; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; import com.alibaba.druid.util.JdbcConstants; -public class OracleCreateIndexStatement extends SQLCreateIndexStatement implements OracleDDLStatement { +public class OracleCreateIndexStatement extends SQLCreateIndexStatement implements OracleDDLStatement, OracleSegmentAttributes { private boolean online = false; @@ -32,12 +34,22 @@ public class OracleCreateIndexStatement extends SQLCreateIndexStatement implemen private SQLExpr parallel; - private SQLName tablespace; + private Integer pctfree; + private Integer pctused; + private Integer initrans; - private SQLExpr ptcfree; - private SQLExpr pctused; - private SQLExpr initrans; - private SQLExpr maxtrans; + private Integer maxtrans; + private Integer pctincrease; + private Integer freeLists; + private Boolean compress; + private Integer compressLevel; + private boolean compressForOltp; + private Integer pctthreshold; + + private Boolean logging; + + protected SQLName tablespace; + protected SQLObject storage; private Boolean enable = null; @@ -47,14 +59,6 @@ public class OracleCreateIndexStatement extends SQLCreateIndexStatement implemen super (JdbcConstants.ORACLE); } - public SQLName getTablespace() { - return tablespace; - } - - public void setTablespace(SQLName tablespace) { - this.tablespace = tablespace; - } - public SQLExpr getParallel() { return parallel; } @@ -95,37 +99,6 @@ public class OracleCreateIndexStatement extends SQLCreateIndexStatement implemen visitor.endVisit(this); } - public SQLExpr getPtcfree() { - return ptcfree; - } - - public void setPtcfree(SQLExpr ptcfree) { - this.ptcfree = ptcfree; - } - - public SQLExpr getPctused() { - return pctused; - } - - public void setPctused(SQLExpr pctused) { - this.pctused = pctused; - } - - public SQLExpr getInitrans() { - return initrans; - } - - public void setInitrans(SQLExpr initrans) { - this.initrans = initrans; - } - - public SQLExpr getMaxtrans() { - return maxtrans; - } - - public void setMaxtrans(SQLExpr maxtrans) { - this.maxtrans = maxtrans; - } public Boolean getEnable() { return enable; @@ -151,4 +124,113 @@ public class OracleCreateIndexStatement extends SQLCreateIndexStatement implemen this.online = online; } + ////////////// + + public SQLName getTablespace() { + return tablespace; + } + + public void setTablespace(SQLName tablespace) { + if (tablespace != null) { + tablespace.setParent(this); + } + this.tablespace = tablespace; + } + + public Boolean getCompress() { + return compress; + } + + public void setCompress(Boolean compress) { + this.compress = compress; + } + + public Integer getCompressLevel() { + return compressLevel; + } + + public void setCompressLevel(Integer compressLevel) { + this.compressLevel = compressLevel; + } + + public Integer getPctthreshold() { + return pctthreshold; + } + + public void setPctthreshold(Integer pctthreshold) { + this.pctthreshold = pctthreshold; + } + + public Integer getPctfree() { + return pctfree; + } + + public void setPctfree(Integer ptcfree) { + this.pctfree = ptcfree; + } + + public Integer getPctused() { + return pctused; + } + + public void setPctused(Integer ptcused) { + this.pctused = ptcused; + } + + public Integer getInitrans() { + return initrans; + } + + public void setInitrans(Integer initrans) { + this.initrans = initrans; + } + + public Integer getMaxtrans() { + return maxtrans; + } + + public void setMaxtrans(Integer maxtrans) { + this.maxtrans = maxtrans; + } + + public Integer getPctincrease() { + return pctincrease; + } + + public void setPctincrease(Integer pctincrease) { + this.pctincrease = pctincrease; + } + + public Integer getFreeLists() { + return freeLists; + } + + public void setFreeLists(Integer freeLists) { + this.freeLists = freeLists; + } + + public Boolean getLogging() { + return logging; + } + + public void setLogging(Boolean logging) { + this.logging = logging; + } + + public SQLObject getStorage() { + return storage; + } + + public void setStorage(SQLObject storage) { + this.storage = storage; + } + + public boolean isCompressForOltp() { + return compressForOltp; + } + + public void setCompressForOltp(boolean compressForOltp) { + this.compressForOltp = compressForOltp; + } + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleLockTableStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleLockTableStatement.java index 0ea6a24094..34977a2d1b 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleLockTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleLockTableStatement.java @@ -77,6 +77,27 @@ public class OracleLockTableStatement extends OracleStatementImpl { } public static enum LockMode { - EXCLUSIVE, SHARE + ROW_SHARE, + ROW_EXCLUSIVE, + SHARE_UPDATE, + SHARE, + SHARE_ROW_EXCLUSIVE, + EXCLUSIVE, + ; + + public String toString() { + switch (this) { + case ROW_SHARE: + return "ROW SHARE"; + case ROW_EXCLUSIVE: + return "ROW EXCLUSIVE"; + case SHARE_UPDATE: + return "SHARE UPDATE"; + case SHARE_ROW_EXCLUSIVE: + return "SHARE ROW EXCLUSIVE"; + default: + return this.name(); + } + } } } 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 5e81dbf773..18d6a18384 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 @@ -1442,12 +1442,38 @@ public class OracleStatementParser extends SQLStatementParser { stmt.setTable(this.exprParser.name()); accept(Token.IN); - if (lexer.token() == Token.SHARE) { - stmt.setLockMode(LockMode.SHARE); + + Token token = lexer.token(); + if (token == Token.SHARE) { lexer.nextToken(); - } else if (lexer.token() == Token.EXCLUSIVE) { + + if (lexer.token() == Token.ROW) { + lexer.nextToken(); + accept(Token.EXCLUSIVE); + stmt.setLockMode(LockMode.SHARE_ROW_EXCLUSIVE); + } else if (lexer.token() == Token.UPDATE) { + lexer.nextToken(); + stmt.setLockMode(LockMode.SHARE_UPDATE); + } else { + stmt.setLockMode(LockMode.SHARE); + } + } else if (token == Token.EXCLUSIVE) { stmt.setLockMode(LockMode.EXCLUSIVE); lexer.nextToken(); + } else if(token == Token.ROW) { + lexer.nextToken(); + token = lexer.token(); + if (token == Token.SHARE) { + stmt.setLockMode(LockMode.ROW_SHARE); + lexer.nextToken(); + } else if (token == Token.EXCLUSIVE) { + stmt.setLockMode(LockMode.ROW_EXCLUSIVE); + lexer.nextToken(); + } else { + throw new ParserException(lexer.info()); + } + } else { + throw new ParserException(lexer.info()); } accept(Token.MODE); @@ -1944,23 +1970,9 @@ public class OracleStatementParser extends SQLStatementParser { accept(Token.RPAREN); for (;;) { - if (lexer.token() == Token.TABLESPACE) { - lexer.nextToken(); - stmt.setTablespace(this.exprParser.name()); - continue; - } else if (lexer.token() == Token.PCTFREE) { - lexer.nextToken(); - stmt.setPtcfree(this.exprParser.expr()); - continue; - } else if (lexer.token() == Token.INITRANS) { - lexer.nextToken(); - stmt.setInitrans(this.exprParser.expr()); - continue; - } else if (lexer.token() == Token.MAXTRANS) { - lexer.nextToken(); - stmt.setMaxtrans(this.exprParser.expr()); - continue; - } else if (lexer.token() == Token.COMPUTE) { + this.getExprParser().parseSegmentAttributes(stmt); + + if (lexer.token() == Token.COMPUTE) { lexer.nextToken(); acceptIdentifier("STATISTICS"); stmt.setComputeStatistics(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 5c05c15503..b485aacff1 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 @@ -1363,7 +1363,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print0(ucase ? "LOCK TABLE " : "lock table "); x.getTable().accept(this); print0(ucase ? " IN " : " in "); - print0(x.getLockMode().name()); + print0(x.getLockMode().toString()); print0(ucase ? " MODE " : " mode "); if (x.isNoWait()) { print0(ucase ? "NOWAIT" : "nowait"); @@ -1752,24 +1752,6 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print0(ucase ? "INDEX ONLY TOPLEVEL" : "index only toplevel"); } - if (x.getPtcfree() != null) { - println(); - print0(ucase ? "PCTFREE " : "pctfree "); - x.getPtcfree().accept(this); - } - - if (x.getInitrans() != null) { - println(); - print0(ucase ? "INITRANS " : "initrans "); - x.getInitrans().accept(this); - } - - if (x.getMaxtrans() != null) { - println(); - print0(ucase ? "MAXTRANS " : "maxtrans "); - x.getMaxtrans().accept(this); - } - if (x.isComputeStatistics()) { println(); print0(ucase ? "COMPUTE STATISTICS" : "compute statistics"); @@ -1791,6 +1773,9 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS print0(ucase ? " PARALLEL " : " parallel "); x.getParallel().accept(this); } + + this.printOracleSegmentAttributes(x); + return false; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerInsertStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerInsertStatement.java index 705b5e640d..dedf3addd0 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerInsertStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerInsertStatement.java @@ -27,33 +27,12 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLServerInsertStatement extends SQLInsertStatement implements SQLServerObject { - private List valuesList = new ArrayList(); - private boolean defaultValues; private SQLServerTop top; private SQLServerOutput output; - public ValuesClause getValues() { - if (valuesList.size() == 0) { - return null; - } - return valuesList.get(0); - } - - public void setValues(ValuesClause values) { - if (valuesList.size() == 0) { - valuesList.add(values); - } else { - valuesList.set(0, values); - } - } - - public List getValuesList() { - return valuesList; - } - @Override protected void accept0(SQLASTVisitor visitor) { this.accept0((SQLServerASTVisitor) visitor); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java index a7cc38e92b..8d4f649371 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java @@ -283,7 +283,7 @@ public class SQLServerStatementParser extends SQLStatementParser { accept(Token.LPAREN); SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(); this.exprParser.exprList(values.getValues(), values); - insertStatement.getValuesList().add(values); + insertStatement.addValueCause(values); accept(Token.RPAREN); if (!parseCompleteValues && insertStatement.getValuesList().size() >= parseValuesSize) { 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 dc58530f8c..1a2351825c 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -361,6 +361,12 @@ public class SQLStatementParser extends SQLParser { continue; } + if (identifierEquals("RETURN")) { + SQLStatement stmt = parseReturn(); + statementList.add(stmt); + continue; + } + // throw new ParserException("syntax error, " + lexer.token() + " " // + lexer.stringVal() + ", pos " // + lexer.pos()); @@ -368,6 +374,24 @@ public class SQLStatementParser extends SQLParser { } } + public SQLStatement parseReturn() { + if (lexer.token() == Token.RETURN + || identifierEquals("RETURN")) { + lexer.nextToken(); + } + + SQLReturnStatement stmt = new SQLReturnStatement(); + if (lexer.token() != Token.SEMI) { + SQLExpr expr = this.exprParser.expr(); + stmt.setExpr(expr); + } + + accept(Token.SEMI); + stmt.setAfterSemi(true); + + return stmt; + } + public SQLStatement parseUpsert() { SQLInsertStatement insertStatement = new SQLInsertStatement(); @@ -1539,7 +1563,7 @@ public class SQLStatementParser extends SQLParser { accept(Token.LPAREN); SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(); this.exprParser.exprList(values.getValues(), values); - insertStatement.getValuesList().add(values); + insertStatement.addValueCause(values); accept(Token.RPAREN); if (lexer.token() == Token.COMMA) { diff --git a/src/main/java/com/alibaba/druid/sql/repository/SchemaObject.java b/src/main/java/com/alibaba/druid/sql/repository/SchemaObject.java index 0ac0cff183..4649d79864 100644 --- a/src/main/java/com/alibaba/druid/sql/repository/SchemaObject.java +++ b/src/main/java/com/alibaba/druid/sql/repository/SchemaObject.java @@ -42,7 +42,7 @@ public class SchemaObject { } public static enum Type { - Sequence, Table, Index + Sequence, Table, Index, Function } public SQLStatement getStatement() { diff --git a/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java b/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java index 1df1b468fa..316ce443d6 100644 --- a/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java +++ b/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java @@ -17,13 +17,17 @@ package com.alibaba.druid.sql.repository; import com.alibaba.druid.sql.SQLUtils; 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.SQLAggregateExpr; +import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter; -import com.alibaba.druid.util.JdbcUtils; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -33,9 +37,11 @@ import java.util.concurrent.ConcurrentSkipListMap; * Created by wenshao on 03/06/2017. */ public class SchemaRepository { - public Map objects = new ConcurrentSkipListMap(); + private final Map objects = new ConcurrentSkipListMap(); - public final SchemaVisitor visitor = new SchemaVisitor(); + private final Map functions = new ConcurrentSkipListMap(); + + private final SchemaVisitor visitor = new SchemaVisitor(); public SchemaObject findTable(String tableName) { String lowerName = tableName.toLowerCase(); @@ -48,6 +54,11 @@ public class SchemaRepository { return null; } + public SchemaObject findFunction(String functionName) { + String lowerName = functionName.toLowerCase(); + return functions.get(lowerName); + } + public void acceptDDL(String ddl, String dbType) { List stmtList = SQLUtils.parseStatements(ddl, dbType); for (SQLStatement stmt : stmtList) { @@ -103,6 +114,15 @@ public class SchemaRepository { return false; } + + public boolean visit(SQLCreateFunctionStatement x) { + String name = x.getName().getSimpleName(); + SchemaObject object = new SchemaObject(name, SchemaObject.Type.Function, x); + + functions.put(name.toLowerCase(), object); + + return false; + } } public SchemaObject findTable(SQLTableSource tableSource, String alias) { @@ -134,4 +154,103 @@ public class SchemaRepository { return null; } + + public SQLColumnDefinition findColumn(SQLTableSource tableSource, SQLSelectItem selectItem) { + if (selectItem == null) { + return null; + } + + return findColumn(tableSource, selectItem.getExpr()); + } + + public SQLColumnDefinition findColumn(SQLTableSource tableSource, SQLExpr expr) { + SchemaObject object = findTable(tableSource, expr); + if (object != null) { + if (expr instanceof SQLAggregateExpr) { + SQLAggregateExpr aggregateExpr = (SQLAggregateExpr) expr; + String function = aggregateExpr.getMethodName(); + if ("min".equalsIgnoreCase(function) + || "max".equalsIgnoreCase(function)) { + SQLExpr arg = aggregateExpr.getArguments().get(0); + expr = arg; + } + } + + if (expr instanceof SQLName) { + return object.findColumn(((SQLName) expr).getSimpleName()); + } + } + + return null; + } + + public SchemaObject findTable(SQLTableSource tableSource, SQLSelectItem selectItem) { + if (selectItem == null) { + return null; + } + + return findTable(tableSource, selectItem.getExpr()); + } + + public SchemaObject findTable(SQLTableSource tableSource, SQLExpr expr) { + if (expr instanceof SQLAggregateExpr) { + SQLAggregateExpr aggregateExpr = (SQLAggregateExpr) expr; + String function = aggregateExpr.getMethodName(); + if ("min".equalsIgnoreCase(function) + || "max".equalsIgnoreCase(function)) { + SQLExpr arg = aggregateExpr.getArguments().get(0); + return findTable(tableSource, arg); + } + } + + if (expr instanceof SQLPropertyExpr) { + String ownerName = ((SQLPropertyExpr) expr).getOwnernName(); + return findTable(tableSource, ownerName); + } + + if (expr instanceof SQLAllColumnExpr || expr instanceof SQLIdentifierExpr) { + if (tableSource instanceof SQLExprTableSource) { + return findTable(tableSource, tableSource.computeAlias()); + } + return null; + } + + return null; + } + + public Map getTables(SQLTableSource x) { + Map tables = new LinkedHashMap(); + computeTable(x, tables); + return tables; + } + + private void computeTable(SQLTableSource x, Map tables) { + if (x == null) { + return; + } + + if (x instanceof SQLExprTableSource) { + SQLExpr expr = ((SQLExprTableSource) x).getExpr(); + if (expr instanceof SQLIdentifierExpr) { + String tableName = ((SQLIdentifierExpr) expr).getName(); + SchemaObject table = findTable(tableName); + if (table != null) { + tables.put(tableName, table); + + String alias = x.getAlias(); + if (alias != null && !alias.equalsIgnoreCase(tableName)) { + tables.put(alias, table); + } + } + } + + return; + } + + if (x instanceof SQLJoinTableSource) { + SQLJoinTableSource join = (SQLJoinTableSource) x; + computeTable(join.getLeft(), tables); + computeTable(join.getRight(), tables); + } + } } 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 a6f7e7b3a2..a4dc28e4b1 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -3606,7 +3606,12 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } } else { if (x.getParamType() == SQLParameter.ParameterType.IN) { - print0(ucase ? "IN " : "in "); + boolean skip = JdbcConstants.MYSQL.equals(dbType) + && x.getParent() instanceof SQLCreateFunctionStatement; + + if (!skip) { + print0(ucase ? "IN " : "in "); + } } else if (x.getParamType() == SQLParameter.ParameterType.OUT) { print0(ucase ? "OUT " : "out "); } else if (x.getParamType() == SQLParameter.ParameterType.INOUT) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/create_function/MySql_Create_Function_0.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/create_function/MySql_Create_Function_0.java new file mode 100644 index 0000000000..1a319e99eb --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/create_function/MySql_Create_Function_0.java @@ -0,0 +1,69 @@ +/* + * 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.mysql.create_function; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class MySql_Create_Function_0 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "CREATE FUNCTION hello (s CHAR(20))\n" + + " RETURNS CHAR(50) DETERMINISTIC\n" + + " RETURN CONCAT('Hello, ',s,'!');"; + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); + SQLStatement stmt = statementList.get(0); + + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL); + stmt.accept(visitor); + + assertEquals("CREATE FUNCTION hello (\n" + + "\ts CHAR(20)\n" + + ")\n" + + "RETURNS CHAR(50) DETERMINISTIC\n" + + "RETURN CONCAT('Hello, ', s, '!');", // + SQLUtils.toMySqlString(stmt)); + + assertEquals("create function hello (\n" + + "\ts CHAR(20)\n" + + ")\n" + + "returns CHAR(50) deterministic\n" + + "return CONCAT('Hello, ', s, '!');", // + SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); +// System.out.println("orderBy : " + visitor.getOrderByColumns()); + + assertEquals(0, visitor.getTables().size()); + assertEquals(1, visitor.getColumns().size()); + assertEquals(0, visitor.getConditions().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("City"))); +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("t2"))); + +// Assert.assertTrue(visitor.getColumns().contains(new Column("t2", "id"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleLockTableTest3.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleLockTableTest3.java new file mode 100644 index 0000000000..c2f9cce6cd --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleLockTableTest3.java @@ -0,0 +1,58 @@ +/* + * 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; + +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; +import org.junit.Assert; + +import java.util.List; + +public class OracleLockTableTest3 extends OracleTest { + + public void test_0() throws Exception { + String sql = "LOCK TABLE \"FIN_SETTLEMENT_DETAIL\" IN ROW SHARE MODE "; + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + SQLStatement stmt = statementList.get(0); + print(statementList); + + assertEquals(1, statementList.size()); + + assertEquals("LOCK TABLE \"FIN_SETTLEMENT_DETAIL\" IN ROW SHARE MODE ", SQLUtils.toOracleString(stmt)); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + 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()); + + assertTrue(visitor.getTables().containsKey(new TableStat.Name("FIN_SETTLEMENT_DETAIL"))); + + assertEquals(1, visitor.getTables().size()); + assertEquals(0, visitor.getColumns().size()); + +// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("bonuses", "employee_id"))); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateIndexTest5.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateIndexTest5.java new file mode 100644 index 0000000000..00bb5c827a --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateIndexTest5.java @@ -0,0 +1,59 @@ +/* + * 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.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 org.junit.Assert; + +import java.util.List; + +public class OracleCreateIndexTest5 extends OracleTest { + + public void test_0() throws Exception { + String sql = // + " CREATE UNIQUE INDEX \"FINANCE\".\"SYS_IOT_TOP_179872\" on \"FINANCE\".\"SYS_JOURNAL_179871\"(\"C0\",\"RID\") INDEX ONLY TOPLEVEL TABLESPACE \"FINANCE\" STORAGE( BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) NOPARALLEL ;"; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + print(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()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(1, visitor.getTables().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("FINANCE.SYS_JOURNAL_179871"))); + + Assert.assertEquals(2, visitor.getColumns().size()); + + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("FINANCE.SYS_JOURNAL_179871", "RID"))); + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "YEAR"))); + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "order_mode"))); + } +}