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 8cbd310b5e..f025427a54 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 @@ -1,458 +1,803 @@ package com.alibaba.druid.sql.dialect.oracle.visitor; import java.util.HashMap; -import java.util.HashSet; -import java.util.List; import java.util.Map; -import java.util.Set; 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.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.SQLMethodInvokeExpr; +import com.alibaba.druid.sql.ast.expr.SQLObjectCreateExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; -import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; -import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; -import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; -import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; -import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource; -import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleHint; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.VersionsFlashbackQueryClause; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.GroupingSetExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.CellAssignment; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.CellAssignmentItem; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.MainModelClause; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ModelColumn; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ModelColumnClause; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ModelRulesClause; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.QueryPartitionClause; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ReturnRowsClause; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.PartitionExtensionClause; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.SampleClause; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.SearchClause; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.SubqueryFactoringClause; +import com.alibaba.druid.sql.dialect.oracle.ast.clause.SubqueryFactoringClause.Entry; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAggregateExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAnalytic; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAnalyticWindowing; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryDoubleExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryFloatExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDateExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDbLinkExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExtractExpr; +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.OracleConstraintState; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleOrderByItem; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OraclePLSQLCommitStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelect; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectForUpdate; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectHierachicalQueryClause; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectJoin; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectPivot; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectPivot.Item; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectRestriction.CheckOption; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectRestriction.ReadOnly; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectSubqueryTableSource; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectUnPivot; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleTableExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateSetListClause; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateSetListMultiColumnItem; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateSetListSingleColumnItem; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateSetValueClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.stat.TableStat; import com.alibaba.druid.stat.TableStat.Column; import com.alibaba.druid.stat.TableStat.Mode; -import com.alibaba.druid.stat.TableStat.Name; - -public class OracleSchemaStatVisitor extends OracleASTVIsitorAdapter { - - private HashMap tableStats = new HashMap(); - private Set fields = new HashSet(); - - private final static ThreadLocal> aliasLocal = new ThreadLocal>(); - private final static ThreadLocal currentTableLocal = new ThreadLocal(); - private final static ThreadLocal modeLocal = new ThreadLocal(); - - public boolean visit(SQLSubqueryTableSource x) { - Map aliasMap = aliasLocal.get(); - if (aliasMap != null) { - if (x.getAlias() != null) { - aliasMap.put(x.getAlias(), null); - } - } - return true; - } - - public boolean visit(SQLExprTableSource x) { - if (x.getExpr() instanceof SQLIdentifierExpr || x.getExpr() instanceof SQLPropertyExpr) { - String ident = x.getExpr().toString(); - TableStat stat = tableStats.get(ident); - if (stat == null) { - stat = new TableStat(); - tableStats.put(new TableStat.Name(ident), stat); - } - - Mode mode = modeLocal.get(); - switch (mode) { - case Delete: - stat.incrementDeleteCount(); - break; - case Insert: - stat.incrementInsertCount(); - break; - case Update: - stat.incrementUpdateCount(); - break; - case Select: - stat.incrementSelectCount(); - break; - default: - break; - } - - Map aliasMap = aliasLocal.get(); - if (aliasMap != null) { - if (x.getAlias() != null) { - aliasMap.put(x.getAlias(), ident); - } - aliasMap.put(ident, ident); - } - } else { - accept(x.getExpr()); - } - - return false; - } - - public boolean visit(OracleSelectTableReference x) { - SQLExpr expr = x.getExpr(); - if (expr instanceof SQLName) { - String ident = ((SQLName) expr).toString(); - TableStat stat = tableStats.get(ident); - if (stat == null) { - stat = new TableStat(); - tableStats.put(new TableStat.Name(ident), stat); - } - - Mode mode = modeLocal.get(); - switch (mode) { - case Delete: - stat.incrementDeleteCount(); - break; - case Insert: - stat.incrementInsertCount(); - break; - case Update: - stat.incrementUpdateCount(); - break; - case Select: - stat.incrementSelectCount(); - break; - default: - break; - } - - Map aliasMap = aliasLocal.get(); - if (aliasMap != null) { - if (x.getAlias() != null) { - aliasMap.put(x.getAlias(), ident); - } - aliasMap.put(ident, ident); - } - return false; - } - - accept(x.getExpr()); - - return false; - } - - public boolean visit(SQLAggregateExpr x) { - accept(x.getArguments()); - return false; - } - - public boolean visit(OracleAggregateExpr x) { - accept(x.getArguments()); - accept(x.getOver()); - return false; - } - - public boolean visit(SQLMethodInvokeExpr x) { - accept(x.getParameters()); - return false; - } - - public boolean visit(SQLSelect x) { - accept(x.getQuery()); - - String originalTable = currentTableLocal.get(); - - currentTableLocal.set((String) x.getQuery().getAttribute("table")); - x.putAttribute("_old_local_", originalTable); - - accept(x.getOrderBy()); - - currentTableLocal.set(originalTable); - - return false; - } - - public void endVisit(OracleSelect x) { - } - - public boolean visit(OracleSelect x) { - accept(x.getFactoring()); - accept(x.getQuery()); - - String originalTable = currentTableLocal.get(); - - currentTableLocal.set((String) x.getQuery().getAttribute("table")); - x.putAttribute("_old_local_", originalTable); - - accept(x.getOrderBy()); - - currentTableLocal.set(originalTable); - - return false; - } - - public void endVisit(SQLSelect x) { - } - public boolean visit(SQLUpdateStatement x) { - aliasLocal.set(new HashMap()); - - String ident = x.getTableName().toString(); - currentTableLocal.set(ident); - - TableStat stat = tableStats.get(ident); - if (stat == null) { - stat = new TableStat(); - tableStats.put(new TableStat.Name(ident), stat); - } - stat.incrementUpdateCount(); +public class OracleSchemaStatVisitor extends SchemaStatVisitor implements + OracleASTVisitor { + + public boolean visit(OracleSelectTableReference x) { + SQLExpr expr = x.getExpr(); + if (expr instanceof SQLName) { + String ident = ((SQLName) expr).toString(); + TableStat stat = tableStats.get(ident); + if (stat == null) { + stat = new TableStat(); + tableStats.put(new TableStat.Name(ident), stat); + } + + Mode mode = modeLocal.get(); + switch (mode) { + case Delete: + stat.incrementDeleteCount(); + break; + case Insert: + stat.incrementInsertCount(); + break; + case Update: + stat.incrementUpdateCount(); + break; + case Select: + stat.incrementSelectCount(); + break; + default: + break; + } + + Map aliasMap = aliasLocal.get(); + if (aliasMap != null) { + if (x.getAlias() != null) { + aliasMap.put(x.getAlias(), ident); + } + aliasMap.put(ident, ident); + } + return false; + } + + accept(x.getExpr()); + + return false; + } + + public boolean visit(SQLAggregateExpr x) { + accept(x.getArguments()); + return false; + } + + public boolean visit(OracleAggregateExpr x) { + accept(x.getArguments()); + accept(x.getOver()); + return false; + } + + public void endVisit(OracleSelect x) { + } + + public boolean visit(OracleSelect x) { + accept(x.getFactoring()); + accept(x.getQuery()); + + String originalTable = currentTableLocal.get(); + + currentTableLocal.set((String) x.getQuery().getAttribute("table")); + x.putAttribute("_old_local_", originalTable); + + accept(x.getOrderBy()); + + currentTableLocal.set(originalTable); + + return false; + } + + public void endVisit(SQLSelect x) { + } + + public boolean visit(OracleUpdateStatement x) { + aliasLocal.set(new HashMap()); + + if (x.getTable() instanceof SQLIdentifierExpr) { + String ident = x.getTable().toString(); + currentTableLocal.set(ident); + + TableStat stat = tableStats.get(ident); + if (stat == null) { + stat = new TableStat(); + tableStats.put(new TableStat.Name(ident), stat); + } + stat.incrementUpdateCount(); + + Map aliasMap = aliasLocal.get(); + aliasMap.put(ident, ident); + } else { + accept(x.getTable()); + } + + accept(x.getSetClause()); + accept(x.getWhere()); + + return false; + } + + public void endVisit(OracleUpdateStatement x) { + aliasLocal.set(null); + } - Map aliasMap = aliasLocal.get(); - aliasMap.put(ident, ident); + public boolean visit(OracleDeleteStatement x) { + return visit((SQLDeleteStatement) x); + } - accept(x.getItems()); - accept(x.getWhere()); + public void endVisit(OracleDeleteStatement x) { + aliasLocal.set(null); + } - return false; - } + public boolean visit(OracleSelectQueryBlock x) { + return visit((SQLSelectQueryBlock) x); + } - public void endVisit(SQLUpdateStatement x) { - aliasLocal.set(null); - } + public void endVisit(OracleSelectQueryBlock x) { + endVisit((SQLSelectQueryBlock) x); + } - public boolean visit(OracleUpdateStatement x) { - aliasLocal.set(new HashMap()); + public boolean visit(SQLPropertyExpr x) { + if ("ROWNUM".equalsIgnoreCase(x.getName())) { + return false; + } - if (x.getTable() instanceof SQLIdentifierExpr) { - String ident = x.getTable().toString(); - currentTableLocal.set(ident); + if (x.getOwner() instanceof SQLIdentifierExpr) { + String owner = ((SQLIdentifierExpr) x.getOwner()).getName(); - TableStat stat = tableStats.get(ident); - if (stat == null) { - stat = new TableStat(); - tableStats.put(new TableStat.Name(ident), stat); - } - stat.incrementUpdateCount(); + if (owner != null) { + Map aliasMap = aliasLocal.get(); + if (aliasMap != null) { + String table = aliasMap.get(owner); - Map aliasMap = aliasLocal.get(); - aliasMap.put(ident, ident); - } else { - accept(x.getTable()); - } + // table == null时是SubQuery + if (table != null) { + fields.add(new Column(table, x.getName())); + } + } + } + } + return false; + } - accept(x.getSetClause()); - accept(x.getWhere()); + public boolean visit(SQLIdentifierExpr x) { + if ("ROWNUM".equalsIgnoreCase(x.getName())) { + return false; + } - return false; - } + if ("SYSDATE".equalsIgnoreCase(x.getName())) { + return false; + } - public void endVisit(OracleUpdateStatement x) { - aliasLocal.set(null); - } + if ("+".equalsIgnoreCase(x.getName())) { + return false; + } - public boolean visit(OracleDeleteStatement x) { - return visit((SQLDeleteStatement) x); - } + String currentTable = currentTableLocal.get(); - public void endVisit(OracleDeleteStatement x) { - aliasLocal.set(null); - } + if (currentTable != null) { + fields.add(new Column(currentTable, x.getName())); + } + return false; + } - public boolean visit(SQLDeleteStatement x) { - aliasLocal.set(new HashMap()); + @Override + public void endVisit(OracleAggregateExpr astNode) { - x.putAttribute("_original_use_mode", modeLocal.get()); - modeLocal.set(Mode.Delete); + } - aliasLocal.set(new HashMap()); + @Override + public void endVisit(OracleConstraintState astNode) { - String ident = ((SQLIdentifierExpr) x.getTableName()).getName(); - currentTableLocal.set(ident); + } - TableStat stat = tableStats.get(ident); - if (stat == null) { - stat = new TableStat(); - tableStats.put(new TableStat.Name(ident), stat); - } - stat.incrementDeleteCount(); + @Override + public void endVisit(OraclePLSQLCommitStatement astNode) { - accept(x.getWhere()); + } - return false; - } + @Override + public void endVisit(OracleAnalytic x) { - public void endVisit(SQLDeleteStatement x) { - aliasLocal.set(null); - } + } - public boolean visit(SQLSelectStatement x) { - aliasLocal.set(new HashMap()); - return true; - } + @Override + public void endVisit(OracleAnalyticWindowing x) { - public void endVisit(SQLSelectStatement x) { - aliasLocal.set(null); - } + } - public void endVisit(SQLInsertStatement x) { - Mode originalMode = (Mode) x.getAttribute("_original_use_mode"); - modeLocal.set(originalMode); - } - - public boolean visit(SQLInsertStatement x) { - x.putAttribute("_original_use_mode", modeLocal.get()); - modeLocal.set(Mode.Insert); - - aliasLocal.set(new HashMap()); - - String originalTable = currentTableLocal.get(); + @Override + public void endVisit(OracleDateExpr x) { - if (x.getTableName() instanceof SQLIdentifierExpr) { - String ident = ((SQLIdentifierExpr) x.getTableName()).getName(); - currentTableLocal.set(ident); - x.putAttribute("_old_local_", originalTable); - - TableStat stat = tableStats.get(ident); - if (stat == null) { - stat = new TableStat(); - tableStats.put(new TableStat.Name(ident), stat); - } - stat.incrementInsertCount(); - - Map aliasMap = aliasLocal.get(); - if (aliasMap != null) { - if (x.getAlias() != null) { - aliasMap.put(x.getAlias(), ident); - } - aliasMap.put(ident, ident); - } - } - - accept(x.getColumns()); - accept(x.getValues()); - accept(x.getQuery()); - - return false; - } - - protected void accept(SQLObject x) { - if (x != null) { - x.accept(this); - } - } - - protected void accept(List nodes) { - for (int i = 0, size = nodes.size(); i < size; ++i) { - accept(nodes.get(i)); - } - } - - public boolean visit(SQLSelectQueryBlock x) { - - if (x.getFrom() instanceof SQLSubqueryTableSource) { - x.getFrom().accept(this); - return false; - } - - x.putAttribute("_original_use_mode", modeLocal.get()); - modeLocal.set(Mode.Select); - - String originalTable = currentTableLocal.get(); - - if (x.getFrom() instanceof SQLExprTableSource) { - SQLExprTableSource tableSource = (SQLExprTableSource) x.getFrom(); - if (tableSource.getExpr() instanceof SQLName) { - String ident = ((SQLName) tableSource.getExpr()).toString(); - currentTableLocal.set(ident); - x.putAttribute("_old_local_", originalTable); - } - } - - x.getFrom().accept(this); // 提前执行,获得aliasMap - - return true; - } - - public void endVisit(SQLSelectQueryBlock x) { - String originalTable = (String) x.getAttribute("_old_local_"); - x.putAttribute("table", currentTableLocal.get()); - currentTableLocal.set(originalTable); - - Mode originalMode = (Mode) x.getAttribute("_original_use_mode"); - modeLocal.set(originalMode); - } - - public boolean visit(OracleSelectQueryBlock x) { - return visit((SQLSelectQueryBlock) x); - } - - public void endVisit(OracleSelectQueryBlock x) { - endVisit((SQLSelectQueryBlock) x); - } - - public boolean visit(SQLJoinTableSource x) { - return true; - } - - public boolean visit(SQLPropertyExpr x) { - if ("ROWNUM".equalsIgnoreCase(x.getName())) { - return false; - } - - if (x.getOwner() instanceof SQLIdentifierExpr) { - String owner = ((SQLIdentifierExpr) x.getOwner()).getName(); - - if (owner != null) { - Map aliasMap = aliasLocal.get(); - if (aliasMap != null) { - String table = aliasMap.get(owner); - - // table == null时是SubQuery - if (table != null) { - fields.add(new Column(table, x.getName())); - } - } - } - } - return false; - } - - public boolean visit(SQLIdentifierExpr x) { - if ("ROWNUM".equalsIgnoreCase(x.getName())) { - return false; - } - - if ("SYSDATE".equalsIgnoreCase(x.getName())) { - return false; - } - - if ("+".equalsIgnoreCase(x.getName())) { - return false; - } - - String currentTable = currentTableLocal.get(); - - if (currentTable != null) { - fields.add(new Column(currentTable, x.getName())); - } - return false; - } - - public boolean visit(SQLAllColumnExpr x) { - String currentTable = currentTableLocal.get(); - - if (currentTable != null) { - fields.add(new Column(currentTable, "*")); - } - return false; - } - - public Map getTables() { - return tableStats; - } - - public boolean containsTable(String tableName) { - return tableStats.containsKey(new TableStat.Name(tableName)); - } - - public Set getFields() { - return fields; - } + } + + @Override + public void endVisit(OracleDbLinkExpr x) { + + } + + @Override + public void endVisit(OracleExtractExpr x) { + + } + + @Override + public void endVisit(OracleHint x) { + + } + + @Override + public void endVisit(OracleIntervalExpr x) { + + } + + @Override + public void endVisit(SQLObjectCreateExpr x) { + + } + + @Override + public void endVisit(OracleOrderBy x) { + + } + + @Override + public void endVisit(OracleOuterExpr x) { + + } + + @Override + public void endVisit(OracleSelectForUpdate x) { + + } + + @Override + public void endVisit(OracleSelectHierachicalQueryClause x) { + + } + + @Override + public void endVisit(OracleSelectJoin x) { + + } + + @Override + public void endVisit(OracleOrderByItem x) { + + } + + @Override + public void endVisit(OracleSelectPivot x) { + + } + + @Override + public void endVisit(Item x) { + + } + + @Override + public void endVisit(CheckOption x) { + + } + + @Override + public void endVisit(ReadOnly x) { + + } + + @Override + public void endVisit(OracleSelectSubqueryTableSource x) { + + } + + @Override + public void endVisit(OracleSelectUnPivot x) { + + } + + @Override + public void endVisit(OracleTableExpr x) { + + } + + @Override + public void endVisit(OracleTimestampExpr x) { + + } + + @Override + public void endVisit(OracleUpdateSetListClause x) { + + } + + @Override + public void endVisit(OracleUpdateSetListMultiColumnItem x) { + + } + + @Override + public void endVisit(OracleUpdateSetListSingleColumnItem x) { + + } + + @Override + public void endVisit(OracleUpdateSetValueClause x) { + + } + + @Override + public boolean visit(OracleConstraintState astNode) { + + return true; + } + + @Override + public boolean visit(OraclePLSQLCommitStatement astNode) { + + return true; + } + + @Override + public boolean visit(OracleAnalytic x) { + + return true; + } + + @Override + public boolean visit(OracleAnalyticWindowing x) { + + return true; + } + + @Override + public boolean visit(OracleDateExpr x) { + + return true; + } + + @Override + public boolean visit(OracleDbLinkExpr x) { + + return true; + } + + @Override + public boolean visit(OracleExtractExpr x) { + + return true; + } + + @Override + public boolean visit(OracleHint x) { + + return true; + } + + @Override + public boolean visit(OracleIntervalExpr x) { + + return true; + } + + @Override + public boolean visit(SQLObjectCreateExpr x) { + + return true; + } + + @Override + public boolean visit(OracleOrderBy x) { + + return true; + } + + @Override + public boolean visit(OracleOuterExpr x) { + + return true; + } + + @Override + public boolean visit(OracleSelectForUpdate x) { + + return true; + } + + @Override + public boolean visit(OracleSelectHierachicalQueryClause x) { + + return true; + } + + @Override + public boolean visit(OracleSelectJoin x) { + + return true; + } + + @Override + public boolean visit(OracleOrderByItem x) { + + return true; + } + + @Override + public boolean visit(OracleSelectPivot x) { + + return true; + } + + @Override + public boolean visit(Item x) { + + return true; + } + + @Override + public boolean visit(CheckOption x) { + + return true; + } + + @Override + public boolean visit(ReadOnly x) { + + return true; + } + + @Override + public boolean visit(OracleSelectSubqueryTableSource x) { + + return true; + } + + @Override + public boolean visit(OracleSelectUnPivot x) { + + return true; + } + + @Override + public boolean visit(OracleTableExpr x) { + + return true; + } + + @Override + public boolean visit(OracleTimestampExpr x) { + + return true; + } + + @Override + public boolean visit(OracleUpdateSetListClause x) { + + return true; + } + + @Override + public boolean visit(OracleUpdateSetListMultiColumnItem x) { + + return true; + } + + @Override + public boolean visit(OracleUpdateSetListSingleColumnItem x) { + + return true; + } + + @Override + public boolean visit(OracleUpdateSetValueClause x) { + + return true; + } + + @Override + public boolean visit(SampleClause x) { + + return true; + } + + @Override + public void endVisit(SampleClause x) { + + } + + @Override + public void endVisit(OracleSelectTableReference x) { + + } + + @Override + public boolean visit(PartitionExtensionClause x) { + + return true; + } + + @Override + public void endVisit(PartitionExtensionClause x) { + + } + + @Override + public boolean visit(VersionsFlashbackQueryClause x) { + + return true; + } + + @Override + public void endVisit(VersionsFlashbackQueryClause x) { + + } + + @Override + public boolean visit(AsOfFlashbackQueryClause x) { + + return true; + } + + @Override + public void endVisit(AsOfFlashbackQueryClause x) { + + } + + @Override + public boolean visit(GroupingSetExpr x) { + + return true; + } + + @Override + public void endVisit(GroupingSetExpr x) { + + } + + @Override + public boolean visit(SubqueryFactoringClause x) { + + return true; + } + + @Override + public void endVisit(SubqueryFactoringClause x) { + + } + + @Override + public boolean visit(Entry x) { + + return true; + } + + @Override + public void endVisit(Entry x) { + + } + + @Override + public boolean visit(SearchClause x) { + + return true; + } + + @Override + public void endVisit(SearchClause x) { + + } + + @Override + public boolean visit(CycleClause x) { + + return true; + } + + @Override + public void endVisit(CycleClause x) { + + } + + @Override + public boolean visit(OracleBinaryFloatExpr x) { + + return true; + } + + @Override + public void endVisit(OracleBinaryFloatExpr x) { + + } + + @Override + public boolean visit(OracleBinaryDoubleExpr x) { + + return true; + } + + @Override + public void endVisit(OracleBinaryDoubleExpr x) { + + } + + @Override + public boolean visit(OracleCursorExpr x) { + + return true; + } + + @Override + public void endVisit(OracleCursorExpr x) { + + } + + @Override + public boolean visit(OracleIsSetExpr x) { + + return true; + } + + @Override + public void endVisit(OracleIsSetExpr x) { + + } + + @Override + public boolean visit(ReturnRowsClause x) { + + return true; + } + + @Override + public void endVisit(ReturnRowsClause x) { + + } + + @Override + public boolean visit(MainModelClause x) { + + return true; + } + + @Override + public void endVisit(MainModelClause x) { + + } + + @Override + public boolean visit(ModelColumnClause x) { + + return true; + } + + @Override + public void endVisit(ModelColumnClause x) { + + } + + @Override + public boolean visit(QueryPartitionClause x) { + + return true; + } + + @Override + public void endVisit(QueryPartitionClause x) { + + } + + @Override + public boolean visit(ModelColumn x) { + + return true; + } + + @Override + public void endVisit(ModelColumn x) { + + } + + @Override + public boolean visit(ModelRulesClause x) { + + return true; + } + + @Override + public void endVisit(ModelRulesClause x) { + + } + + @Override + public boolean visit(CellAssignmentItem x) { + + return true; + } + + @Override + public void endVisit(CellAssignmentItem x) { + + } + + @Override + public boolean visit(CellAssignment x) { + + return true; + } + + @Override + public void endVisit(CellAssignment x) { + + } + + @Override + public boolean visit(ModelClause x) { + return true; + } + + @Override + public void endVisit(ModelClause x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSelectQueryBlock.java index 68617c7eed..9197cb47a0 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSelectQueryBlock.java @@ -8,7 +8,6 @@ import com.alibaba.druid.sql.ast.SQLOrderBy; import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; - import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class PGSelectQueryBlock extends SQLSelectQueryBlock { @@ -24,6 +23,15 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { private SQLOrderBy orderBy; private FetchClause fetch; private ForClause forClause; + private IntoClause into; + + public IntoClause getInto() { + return into; + } + + public void setInto(IntoClause into) { + this.into = into; + } @Override protected void accept0(SQLASTVisitor visitor) { @@ -35,6 +43,7 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { acceptChild(visitor, this.with); acceptChild(visitor, this.distinctOn); acceptChild(visitor, this.selectList); + acceptChild(visitor, this.into); acceptChild(visitor, this.from); acceptChild(visitor, this.where); acceptChild(visitor, this.groupBy); @@ -284,4 +293,39 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { } } } + + public static class IntoClause extends PGSQLObjectImpl { + public static enum Option { + TEMPORARY, TEMP, UNLOGGED + } + + private static final long serialVersionUID = 1L; + + private SQLExpr table; + private Option option; + + public Option getOption() { + return option; + } + + public void setOption(Option option) { + this.option = option; + } + + public SQLExpr getTable() { + return table; + } + + public void setTable(SQLExpr table) { + this.table = table; + } + + @Override + public void accept0(PGASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, table); + } + } + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java index b6a32afa69..72a236a765 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java @@ -5,6 +5,7 @@ import com.alibaba.druid.sql.ast.SQLSetQuantifier; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.IntoClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WithQuery; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; @@ -76,6 +77,31 @@ public class PGSelectParser extends SQLSelectParser { } parseSelectList(queryBlock); + + if (lexer.token() == Token.INTO) { + IntoClause into = new IntoClause(); + lexer.nextToken(); + + if (lexer.token() == Token.TEMPORARY) { + lexer.nextToken(); + into.setOption(IntoClause.Option.TEMPORARY); + } else if (lexer.token() == Token.TEMP) { + lexer.nextToken(); + into.setOption(IntoClause.Option.TEMP); + } else if (lexer.token() == Token.UNLOGGED) { + lexer.nextToken(); + into.setOption(IntoClause.Option.UNLOGGED); + } + + if (lexer.token() == Token.TABLE) { + lexer.nextToken(); + } + + SQLExpr name = this.createExprParser().name(); + into.setTable(name); + + queryBlock.setInto(into); + } parseFrom(queryBlock); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java index 85c3836945..8e03e23342 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java @@ -23,4 +23,8 @@ public interface PGASTVisitor extends SQLASTVisitor { void endVisit(PGSelectQueryBlock.WithClause x); boolean visit(PGSelectQueryBlock.WithClause x); + + void endVisit(PGSelectQueryBlock.IntoClause x); + + boolean visit(PGSelectQueryBlock.IntoClause x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java index a28567f054..a73c754c80 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java @@ -2,6 +2,7 @@ package com.alibaba.druid.sql.dialect.postgresql.visitor; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.FetchClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.ForClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.IntoClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WindowClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WithClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WithQuery; @@ -64,5 +65,16 @@ public class PGASTVisitorAdapter extends SQLASTVisitorAdapter implements return true; } + + @Override + public void endVisit(IntoClause x) { + + } + + @Override + public boolean visit(IntoClause x) { + + return true; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java index f000609ecb..9ed68008ca 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java @@ -5,6 +5,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.FetchClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.ForClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.IntoClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WindowClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WithClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WithQuery; @@ -157,6 +158,11 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements } printSelectList(x.getSelectList()); + + if (x.getInto() != null) { + println(); + x.getInto().accept(this); + } if (x.getFrom() != null) { println(); @@ -210,4 +216,20 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements return false; } + + @Override + public void endVisit(IntoClause x) { + + } + + @Override + public boolean visit(IntoClause x) { + print("INTO "); + if (x.getOption() != null) { + print(x.getOption().name()); + print(" "); + } + x.getTable().accept(this); + return false; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java index 83c6cac432..00ecd4d419 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java @@ -2,10 +2,12 @@ package com.alibaba.druid.sql.dialect.postgresql.visitor; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.FetchClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.ForClause; +import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.IntoClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WindowClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WithClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGSelectQueryBlock.WithQuery; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; public class PGSchemaStatVisitor extends SchemaStatVisitor implements PGASTVisitor { @@ -63,4 +65,22 @@ public class PGSchemaStatVisitor extends SchemaStatVisitor implements return true; } + @Override + public void endVisit(IntoClause x) { + + } + + @Override + public boolean visit(IntoClause x) { + String ident = x.getTable().toString(); + + TableStat stat = tableStats.get(ident); + if (stat == null) { + stat = new TableStat(); + tableStats.put(new TableStat.Name(ident), stat); + } + stat.incrementInsertCount(); + return false; + } + } 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 527313c51e..4c4292544f 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -112,6 +112,9 @@ public enum Token { SHARE("SHARE"), NOWAIT("NOWAIT"), RECURSIVE("RECURSIVE"), + TEMPORARY("TEMPORARY"), + TEMP("TEMP"), + UNLOGGED("UNLOGGED"), // oracle START("START"), 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 aa489c9668..00c214e62d 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -6,12 +6,14 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLObject; 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.SQLMethodInvokeExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; +import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; @@ -41,8 +43,8 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { String originalTable = currentTableLocal.get(); - if (x.getTableName() instanceof SQLIdentifierExpr) { - String ident = ((SQLIdentifierExpr) x.getTableName()).getName(); + if (x.getTableName() instanceof SQLName) { + String ident = ((SQLName) x.getTableName()).toString(); currentTableLocal.set(ident); x.putAttribute("_old_local_", originalTable); @@ -94,9 +96,8 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { if (x.getFrom() instanceof SQLExprTableSource) { SQLExprTableSource tableSource = (SQLExprTableSource) x.getFrom(); - if (tableSource.getExpr() instanceof SQLIdentifierExpr) { - String ident = ((SQLIdentifierExpr) tableSource.getExpr()) - .getName(); + if (tableSource.getExpr() instanceof SQLName) { + String ident = tableSource.getExpr().toString(); currentTableLocal.set(ident); x.putAttribute("_old_local_", originalTable); } @@ -188,9 +189,12 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { return true; } + protected boolean isSimpleExprTableSource(SQLExprTableSource x) { + return x.getExpr() instanceof SQLName; + } + public boolean visit(SQLExprTableSource x) { - if (x.getExpr() instanceof SQLIdentifierExpr - || x.getExpr() instanceof SQLPropertyExpr) { + if (isSimpleExprTableSource(x)) { String ident = x.getExpr().toString(); TableStat stat = tableStats.get(ident); if (stat == null) { @@ -276,6 +280,33 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { return false; } + + public boolean visit(SQLDeleteStatement x) { + aliasLocal.set(new HashMap()); + + x.putAttribute("_original_use_mode", modeLocal.get()); + modeLocal.set(Mode.Delete); + + aliasLocal.set(new HashMap()); + + String ident = ((SQLIdentifierExpr) x.getTableName()).getName(); + currentTableLocal.set(ident); + + TableStat stat = tableStats.get(ident); + if (stat == null) { + stat = new TableStat(); + tableStats.put(new TableStat.Name(ident), stat); + } + stat.incrementDeleteCount(); + + accept(x.getWhere()); + + return false; + } + + public void endVisit(SQLDeleteStatement x) { + aliasLocal.set(null); + } public void endVisit(SQLUpdateStatement x) { aliasLocal.set(null); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlSchemaStatVisitorTest5.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlSchemaStatVisitorTest5.java index 00711a7b4f..36c9a5a94c 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlSchemaStatVisitorTest5.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlSchemaStatVisitorTest5.java @@ -18,7 +18,7 @@ public class MySqlSchemaStatVisitorTest5 extends TestCase { + " LEFT JOIN (select * from view_portal_panel) c ON a.panel_id = c.panel_id " + " WHERE b.user_id = ? and ((b.is_grid='y' and c.param_name='is_hidden' and c.param_value='false') or b.is_grid != 'y') and b.user_id in (select user_id from table1 where id = 1) ORDER BY a.col ASC, a.position ASC"; - sql = "select columnName from table1 where id in (select id from table3 where name = ?)"; +// sql = "select columnName from table1 where id in (select id from table3 where name = ?)"; MySqlStatementParser parser = new MySqlStatementParser(sql); List statementList = parser.parseStatementList(); SQLStatement statemen = statementList.get(0); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PostgresqlResourceTest.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PostgresqlResourceTest.java index 44da320ae5..6c540323f8 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PostgresqlResourceTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PostgresqlResourceTest.java @@ -6,15 +6,15 @@ import java.io.Reader; import java.util.List; import junit.framework.Assert; -import junit.framework.TestCase; +import com.alibaba.druid.sql.PGTest; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGSchemaStatVisitor; import com.alibaba.druid.util.JdbcUtils; -public class PostgresqlResourceTest extends TestCase { +public class PostgresqlResourceTest extends PGTest { public void test_0() throws Exception { // 13 @@ -70,14 +70,5 @@ public class PostgresqlResourceTest extends TestCase { Assert.assertEquals(expect, out.toString()); } - private String output(List stmtList) { - StringBuilder out = new StringBuilder(); - PGOutputVisitor visitor = new PGOutputVisitor(out); - for (SQLStatement stmt : stmtList) { - stmt.accept(visitor); - } - - return out.toString(); - } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PostgresqlTest.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PostgresqlTest.java new file mode 100644 index 0000000000..1705478b7a --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PostgresqlTest.java @@ -0,0 +1,37 @@ +package com.alibaba.druid.bvt.sql.postgresql; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.PGTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.stat.TableStat.Column; + +public class PostgresqlTest extends PGTest { + public void test_0() throws Exception { + String sql = "SELECT * INTO films_recent FROM films WHERE date_prod >= '2002-01-01';"; + + PGSQLStatementParser parser = new PGSQLStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + System.out.println(output(statementList)); + + Assert.assertEquals(1, statementList.size()); + + PGSchemaStatVisitor visitor = new PGSchemaStatVisitor(); + statemen.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getFields()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("films_recent"))); + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("films"))); + + Assert.assertTrue(visitor.getFields().contains(new Column("films", "*"))); + Assert.assertTrue(visitor.getFields().contains(new Column("films", "date_prod"))); + } +} diff --git a/src/test/java/com/alibaba/druid/sql/PGTest.java b/src/test/java/com/alibaba/druid/sql/PGTest.java new file mode 100644 index 0000000000..eae850f05b --- /dev/null +++ b/src/test/java/com/alibaba/druid/sql/PGTest.java @@ -0,0 +1,21 @@ +package com.alibaba.druid.sql; + +import java.util.List; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor; + +import junit.framework.TestCase; + +public class PGTest extends TestCase { + protected String output(List stmtList) { + StringBuilder out = new StringBuilder(); + PGOutputVisitor visitor = new PGOutputVisitor(out); + + for (SQLStatement stmt : stmtList) { + stmt.accept(visitor); + } + + return out.toString(); + } +}