diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalDay.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalDay.java new file mode 100644 index 0000000000..26c014b934 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalDay.java @@ -0,0 +1,48 @@ +package com.alibaba.druid.sql.dialect.oracle.ast; + +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.druid.sql.ast.SQLDataTypeImpl; +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class OracleDataTypeIntervalDay extends SQLDataTypeImpl implements OracleSQLObject { + + private static final long serialVersionUID = 1L; + + private boolean toSecond = false; + + protected final List fractionalSeconds = new ArrayList(); + + public OracleDataTypeIntervalDay(){ + this.setName("INTERVAL DAY"); + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + this.accept0((OracleASTVisitor) visitor); + } + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, getArguments()); + } + visitor.endVisit(this); + } + + public boolean isToSecond() { + return toSecond; + } + + public void setToSecond(boolean toSecond) { + this.toSecond = toSecond; + } + + public List getFractionalSeconds() { + return fractionalSeconds; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalYear.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalYear.java new file mode 100644 index 0000000000..f0484ee139 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalYear.java @@ -0,0 +1,28 @@ +package com.alibaba.druid.sql.dialect.oracle.ast; + +import com.alibaba.druid.sql.ast.SQLDataTypeImpl; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class OracleDataTypeIntervalYear extends SQLDataTypeImpl implements OracleSQLObject { + + private static final long serialVersionUID = 1L; + + public OracleDataTypeIntervalYear(){ + this.setName("INTERVAL YEAR"); + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + this.accept0((OracleASTVisitor) visitor); + } + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, getArguments()); + } + visitor.endVisit(this); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeTimestamp.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeTimestamp.java new file mode 100644 index 0000000000..a8de670fb1 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeTimestamp.java @@ -0,0 +1,47 @@ +package com.alibaba.druid.sql.dialect.oracle.ast; + +import com.alibaba.druid.sql.ast.SQLDataTypeImpl; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class OracleDataTypeTimestamp extends SQLDataTypeImpl implements OracleSQLObject { + + private static final long serialVersionUID = 1L; + + private boolean withTimeZone = false; + private boolean withLocalTimeZone = false; + + public OracleDataTypeTimestamp() { + this.setName("TIMESTAMP"); + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + this.accept0((OracleASTVisitor) visitor); + } + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, getArguments()); + } + visitor.endVisit(this); + } + + public boolean isWithTimeZone() { + return withTimeZone; + } + + public void setWithTimeZone(boolean withTimeZone) { + this.withTimeZone = withTimeZone; + } + + public boolean isWithLocalTimeZone() { + return withLocalTimeZone; + } + + public void setWithLocalTimeZone(boolean withLocalTimeZone) { + this.withLocalTimeZone = withLocalTimeZone; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java index 635c91c47c..68ac72fbc4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java @@ -37,6 +37,9 @@ import com.alibaba.druid.sql.ast.expr.SQLUnaryOperator; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.ast.statement.SQLCharactorDataType; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeTimestamp; import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAggregateExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAnalytic; @@ -75,6 +78,7 @@ public class OracleExprParser extends SQLExprParser { + public boolean allowStringAdditive = false; /** @@ -117,9 +121,73 @@ public class OracleExprParser extends SQLExprParser { return null; } + if (lexer.token() == Token.INTERVAL) { + lexer.nextToken(); + if (identifierEquals("YEAR")) { + lexer.nextToken(); + OracleDataTypeIntervalYear interval = new OracleDataTypeIntervalYear(); + + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + interval.getArguments().add(this.expr()); + accept(Token.RPAREN); + } + + accept(Token.TO); + acceptIdentifier("MONTH"); + + return interval; + } else { + acceptIdentifier("DAY"); + OracleDataTypeIntervalDay interval = new OracleDataTypeIntervalDay(); + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + interval.getArguments().add(this.expr()); + accept(Token.RPAREN); + } + + accept(Token.TO); + acceptIdentifier("SECOND"); + + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + interval.getFractionalSeconds().add(this.expr()); + accept(Token.RPAREN); + } + + return interval; + } + } + SQLName typeExpr = name(); String typeName = typeExpr.toString(); + if ("TIMESTAMP".equalsIgnoreCase(typeName)) { + OracleDataTypeTimestamp timestamp = new OracleDataTypeTimestamp(); + + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + timestamp.getArguments().add(this.expr()); + accept(Token.RPAREN); + } + + if (lexer.token() == Token.WITH) { + lexer.nextToken(); + + if (identifierEquals("LOCAL")) { + lexer.nextToken(); + timestamp.setWithLocalTimeZone(true); + } else { + timestamp.setWithTimeZone(true); + } + + acceptIdentifier("TIME"); + acceptIdentifier("ZONE"); + } + + return timestamp; + } + if (isCharType(typeName)) { SQLCharactorDataType charType = new SQLCharactorDataType(typeName); 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 baa78a0f71..7246799850 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 @@ -16,6 +16,9 @@ package com.alibaba.druid.sql.dialect.oracle.visitor; import com.alibaba.druid.sql.ast.expr.SQLObjectCreateExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeTimestamp; 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; @@ -611,4 +614,17 @@ public interface OracleASTVisitor extends SQLASTVisitor { boolean visit(OracleDropDatabaseLinkStatement x); void endVisit(OracleDropDatabaseLinkStatement x); + + boolean visit(OracleDataTypeTimestamp x); + + void endVisit(OracleDataTypeTimestamp x); + + boolean visit(OracleDataTypeIntervalYear x); + + void endVisit(OracleDataTypeIntervalYear x); + + boolean visit(OracleDataTypeIntervalDay x); + + void endVisit(OracleDataTypeIntervalDay x); + } 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 7122c89aa6..afe2ae8df9 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 @@ -16,6 +16,9 @@ package com.alibaba.druid.sql.dialect.oracle.visitor; import com.alibaba.druid.sql.ast.expr.SQLObjectCreateExpr; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeTimestamp; 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; @@ -1393,4 +1396,34 @@ public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements Ora } + @Override + public boolean visit(OracleDataTypeTimestamp x) { + return true; + } + + @Override + public void endVisit(OracleDataTypeTimestamp x) { + + } + + @Override + public boolean visit(OracleDataTypeIntervalYear x) { + return true; + } + + @Override + public void endVisit(OracleDataTypeIntervalYear x) { + + } + + @Override + public boolean visit(OracleDataTypeIntervalDay x) { + return true; + } + + @Override + public void endVisit(OracleDataTypeIntervalDay 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 07a611c768..89c151d483 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 @@ -38,6 +38,9 @@ import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType; import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeTimestamp; 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; @@ -3107,4 +3110,72 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } return false; } + + @Override + public boolean visit(OracleDataTypeTimestamp x) { + print(x.getName()); + if (x.getArguments().size() > 0) { + print("("); + x.getArguments().get(0).accept(this); + print(")"); + } + + if (x.isWithTimeZone()) { + print(" WITH TIME ZONE"); + } else if (x.isWithLocalTimeZone()) { + print(" WITH LOCAL TIME ZONE"); + } + + return false; + } + + @Override + public void endVisit(OracleDataTypeTimestamp x) { + + } + + @Override + public boolean visit(OracleDataTypeIntervalYear x) { + print(x.getName()); + if (x.getArguments().size() > 0) { + print("("); + x.getArguments().get(0).accept(this); + print(")"); + } + + print(" TO MONTH"); + + return false; + } + + @Override + public void endVisit(OracleDataTypeIntervalYear x) { + + } + + @Override + public boolean visit(OracleDataTypeIntervalDay x) { + print(x.getName()); + if (x.getArguments().size() > 0) { + print("("); + x.getArguments().get(0).accept(this); + print(")"); + } + + print(" TO SECOND"); + + if (x.getFractionalSeconds().size() > 0) { + print("("); + x.getFractionalSeconds().get(0).accept(this); + print(")"); + } + + return false; + } + + @Override + public void endVisit(OracleDataTypeIntervalDay x) { + // TODO Auto-generated method stub + + } } 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 cd06b63dc3..9daabe6a55 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 @@ -37,6 +37,9 @@ import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeTimestamp; 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; @@ -1822,4 +1825,34 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle public void endVisit(OracleDropDatabaseLinkStatement x) { } + + @Override + public boolean visit(OracleDataTypeTimestamp x) { + return false; + } + + @Override + public void endVisit(OracleDataTypeTimestamp x) { + + } + + @Override + public boolean visit(OracleDataTypeIntervalYear x) { + return false; + } + + @Override + public void endVisit(OracleDataTypeIntervalYear x) { + + } + + @Override + public boolean visit(OracleDataTypeIntervalDay x) { + return false; + } + + @Override + public void endVisit(OracleDataTypeIntervalDay x) { + + } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest15.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest15.java new file mode 100644 index 0000000000..65b21b964d --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest15.java @@ -0,0 +1,79 @@ +/* + * Copyright 1999-2011 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 java.util.List; + +import junit.framework.Assert; + +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; + +public class OracleCreateTableTest15 extends OracleTest { + + public void test_types() throws Exception { + String sql = // + "create table T (" + // + "F1 TIMESTAMP," + // + "F2 TIMESTAMP(9), " + // + "F3 TIMESTAMP WITH TIME ZONE," + // + "F4 TIMESTAMP(9) WITH TIME ZONE, " + // + "F5 TIMESTAMP WITH TIME ZONE," + // + "F6 TIMESTAMP(9) WITH TIME ZONE" + // + ") "; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statement = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + Assert.assertEquals("CREATE TABLE T (" + // + "\n\tF1 TIMESTAMP," + // + "\n\tF2 TIMESTAMP(9)," + // + "\n\tF3 TIMESTAMP WITH TIME ZONE," + // + "\n\tF4 TIMESTAMP(9) WITH TIME ZONE," + // + "\n\tF5 TIMESTAMP WITH TIME ZONE," + // + "\n\tF6 TIMESTAMP(9) WITH TIME ZONE" + // + "\n)", SQLUtils.toSQLString(statement, JdbcConstants.ORACLE)); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + statement.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.assertEquals(6, visitor.getColumns().size()); + + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F1"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F2"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F3"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F4"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F5"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F6"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest16.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest16.java new file mode 100644 index 0000000000..2ffd095467 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest16.java @@ -0,0 +1,79 @@ +/* + * Copyright 1999-2011 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 java.util.List; + +import junit.framework.Assert; + +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; + +public class OracleCreateTableTest16 extends OracleTest { + + public void test_types() throws Exception { + String sql = // + "create table T (" + // + "F1 INTERVAL YEAR TO MONTH," + // + "F2 INTERVAL YEAR (3) TO MONTH," + // + "F3 INTERVAL DAY TO SECOND," + // + "F4 INTERVAL DAY (3) TO SECOND," + // + "F5 INTERVAL DAY TO SECOND (9)," + // + "F6 INTERVAL DAY (3) TO SECOND (9)" + // + ") "; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statement = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + Assert.assertEquals("CREATE TABLE T (" + // + "\n\tF1 INTERVAL YEAR TO MONTH," + // + "\n\tF2 INTERVAL YEAR(3) TO MONTH," + // + "\n\tF3 INTERVAL DAY TO SECOND," + // + "\n\tF4 INTERVAL DAY(3) TO SECOND," + // + "\n\tF5 INTERVAL DAY TO SECOND(9)," + // + "\n\tF6 INTERVAL DAY(3) TO SECOND(9)" + // + "\n)", SQLUtils.toSQLString(statement, JdbcConstants.ORACLE)); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + statement.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.assertEquals(6, visitor.getColumns().size()); + + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F1"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F2"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F3"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F4"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F5"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F6"))); + } +}