diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateMaterializedViewStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateMaterializedViewStatement.java index 2307c721cd..e21106341d 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateMaterializedViewStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateMaterializedViewStatement.java @@ -17,6 +17,7 @@ package com.alibaba.druid.sql.ast.statement; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLObject; +import com.alibaba.druid.sql.ast.SQLPartitionBy; import com.alibaba.druid.sql.ast.SQLStatementImpl; import com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributes; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -56,6 +57,7 @@ public class SQLCreateMaterializedViewStatement extends SQLStatementImpl impleme private Integer pctthreshold; private Boolean logging; + private Boolean cache; protected SQLName tablespace; protected SQLObject storage; @@ -65,6 +67,10 @@ public class SQLCreateMaterializedViewStatement extends SQLStatementImpl impleme private Boolean enableQueryRewrite; + private SQLPartitionBy partitionBy; + + private boolean withRowId; + public SQLName getName() { return name; } @@ -285,11 +291,39 @@ public class SQLCreateMaterializedViewStatement extends SQLStatementImpl impleme this.enableQueryRewrite = enableQueryRewrite; } + public Boolean getCache() { + return cache; + } + + public void setCache(Boolean cache) { + this.cache = cache; + } + + public SQLPartitionBy getPartitionBy() { + return partitionBy; + } + + public void setPartitionBy(SQLPartitionBy x) { + if (x != null) { + x.setParent(this); + } + this.partitionBy = x; + } + + public boolean isWithRowId() { + return withRowId; + } + + public void setWithRowId(boolean withRowId) { + this.withRowId = withRowId; + } + @Override protected void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { acceptChild(visitor, name); acceptChild(visitor, columns); + acceptChild(visitor, partitionBy); acceptChild(visitor, query); } visitor.endVisit(this); diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropMaterializedViewStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropMaterializedViewStatement.java new file mode 100644 index 0000000000..d52d3246ec --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropMaterializedViewStatement.java @@ -0,0 +1,75 @@ +/* + * 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.sql.ast.statement; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLObject; +import com.alibaba.druid.sql.ast.SQLStatementImpl; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +import java.util.ArrayList; +import java.util.List; + +public class SQLDropMaterializedViewStatement extends SQLStatementImpl implements SQLDropStatement { + + private SQLExpr name; + private boolean ifExists; + + public SQLDropMaterializedViewStatement() { + + } + + public SQLDropMaterializedViewStatement(String dbType) { + super (dbType); + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, name); + } + visitor.endVisit(this); + } + + public SQLExpr getName() { + return name; + } + + public void setName(SQLExpr x) { + if (x != null) { + x.setParent(this); + } + this.name = x; + } + + public boolean isIfExists() { + return ifExists; + } + + public void setIfExists(boolean ifExists) { + this.ifExists = ifExists; + } + + @Override + public List getChildren() { + List children = new ArrayList(); + if (name != null) { + children.add(name); + } + return children; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java index e32bd3447a..e754d92683 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java @@ -203,7 +203,7 @@ public class OracleCreateTableParser extends SQLCreateTableParser { stmt.setPartitioning(partitionByHash); continue; } else if (lexer.identifierEquals("LIST")) { - SQLPartitionByList partitionByList = partitionByList(); + SQLPartitionByList partitionByList = this.getExprParser().partitionByList(); this.getExprParser().partitionClauseRest(partitionByList); stmt.setPartitioning(partitionByList); continue; @@ -329,19 +329,6 @@ public class OracleCreateTableParser extends SQLCreateTableParser { stmt.setOrganization(organization); } - protected SQLPartitionByList partitionByList() { - acceptIdentifier("LIST"); - SQLPartitionByList partitionByList = new SQLPartitionByList(); - - accept(Token.LPAREN); - partitionByList.addColumn(this.exprParser.expr()); - accept(Token.RPAREN); - - this.getExprParser().parsePartitionByRest(partitionByList); - - return partitionByList; - } - protected void parseCreateTableSupplementalLogingProps(SQLCreateTableStatement stmt) { acceptIdentifier("SUPPLEMENTAL"); acceptIdentifier("LOG"); 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 aba991ec1f..c462cc3b67 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 @@ -1632,6 +1632,57 @@ public class OracleExprParser extends SQLExprParser { } } + protected SQLPartitionBy parsePartitionBy() { + lexer.nextToken(); + + accept(Token.BY); + + SQLPartitionBy partitionBy; + + if (lexer.identifierEquals("RANGE")) { + return this.partitionByRange(); + } else if (lexer.identifierEquals("HASH")) { + SQLPartitionByHash partitionByHash = this.partitionByHash(); + this.partitionClauseRest(partitionByHash); + + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + for (;;) { + SQLPartition partition = this.parsePartition(); + partitionByHash.addPartition(partition); + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } else if (lexer.token() == Token.RPAREN) { + lexer.nextToken(); + break; + } + throw new ParserException("TODO : " + lexer.info()); + } + } + return partitionByHash; + } else if (lexer.identifierEquals("LIST")) { + SQLPartitionByList partitionByList = partitionByList(); + this.partitionClauseRest(partitionByList); + return partitionByList; + } else { + throw new ParserException("TODO : " + lexer.info()); + } + } + + protected SQLPartitionByList partitionByList() { + acceptIdentifier("LIST"); + SQLPartitionByList partitionByList = new SQLPartitionByList(); + + accept(Token.LPAREN); + partitionByList.addColumn(this.expr()); + accept(Token.RPAREN); + + this.parsePartitionByRest(partitionByList); + + return partitionByList; + } + protected SQLPartitionByRange partitionByRange() { acceptIdentifier("RANGE"); accept(Token.LPAREN); 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 80d5f1a578..293ef479f8 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 @@ -606,6 +606,15 @@ public class OracleStatementParser extends SQLStatementParser { continue; } + if (lexer.identifierEquals(FnvHash.Constants.MATERIALIZED)) { + lexer.reset(savePoint); + + SQLStatement stmt = parseDropMaterializedView(); + stmt.setParent(parent); + statementList.add(stmt); + continue; + } + throw new ParserException("TODO : " + lexer.info()); } @@ -711,6 +720,21 @@ public class OracleStatementParser extends SQLStatementParser { return stmt; } + public SQLStatement parseDropMaterializedView() { + if (lexer.token() == Token.DROP) { + lexer.nextToken(); + } + SQLDropMaterializedViewStatement stmt = new SQLDropMaterializedViewStatement(); + stmt.setDbType(dbType); + + acceptIdentifier("MATERIALIZED"); + + accept(Token.VIEW); + + stmt.setName(this.exprParser.name()); + return stmt; + } + public SQLStatement parseDropSynonym() { if (lexer.token() == Token.DROP) { lexer.nextToken(); diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index a6e76f4d3e..9935bd1159 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -3085,6 +3085,14 @@ public class SQLExprParser extends SQLParser { return expr; } + + protected SQLPartition parsePartition() { + throw new ParserException("TODO"); + } + + protected SQLPartitionBy parsePartitionBy() { + throw new ParserException("TODO"); + } public SQLPartitionValue parsePartitionValues() { if (lexer.token != Token.VALUES) { 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 65968f8c26..f579aff509 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -2141,6 +2141,11 @@ public class SQLStatementParser extends SQLParser { SQLCreateMaterializedViewStatement stmt = new SQLCreateMaterializedViewStatement(); stmt.setName(this.exprParser.name()); + if (lexer.token == Token.PARTITION) { + SQLPartitionBy partitionBy = this.exprParser.parsePartitionBy(); + stmt.setPartitionBy(partitionBy); + } + for (;;) { if (exprParser instanceof OracleExprParser) { ((OracleExprParser) exprParser).parseSegmentAttributes(stmt); @@ -2172,23 +2177,33 @@ public class SQLStatementParser extends SQLParser { break; } } - } else if (lexer.identifierEquals("BUILD")) { + } else if (lexer.identifierEquals(FnvHash.Constants.BUILD)) { lexer.nextToken(); if (lexer.identifierEquals("IMMEDIATE") || lexer.token == Token.IMMEDIATE) { lexer.nextToken(); stmt.setBuildImmediate(true); } else { - acceptIdentifier("DEFERRED"); + accept(Token.DEFERRED); stmt.setBuildDeferred(true); } - } else if (lexer.identifierEquals("PARALLEL")) { + } else if (lexer.identifierEquals(FnvHash.Constants.PARALLEL)) { lexer.nextToken(); stmt.setParallel(true); if (lexer.token == Token.LITERAL_INT) { stmt.setParallelValue(lexer.integerValue().intValue()); lexer.nextToken(); } + } else if (lexer.identifierEquals(FnvHash.Constants.NOCACHE) || lexer.token == Token.NOCACHE) { + lexer.nextToken(); + stmt.setCache(false); + } else if (lexer.identifierEquals(FnvHash.Constants.NOPARALLEL)) { + lexer.nextToken(); + stmt.setParallel(false); + } else if (lexer.token == Token.WITH) { + lexer.nextToken(); + acceptIdentifier("ROWID"); + stmt.setWithRowId(true); } else { break; } @@ -2208,6 +2223,7 @@ public class SQLStatementParser extends SQLParser { return stmt; } + public SQLStatement parseCreateDbLink() { throw new ParserException("TODO " + lexer.token); } 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 4350ced860..1e24a65556 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -2300,6 +2300,18 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet return false; } + public boolean visit(SQLDropMaterializedViewStatement x) { + print0(ucase ? "DROP VIEW " : "drop view "); + + if (x.isIfExists()) { + print0(ucase ? "IF EXISTS " : "if exists "); + } + + x.getName().accept(this); + + return false; + } + public boolean visit(SQLDropEventStatement x) { print0(ucase ? "DROP EVENT " : "drop event "); @@ -5684,9 +5696,22 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet public boolean visit(SQLCreateMaterializedViewStatement x) { print0(ucase ? "CREATE MATERIALIZED VIEW " : "create materialized view "); x.getName().accept(this); + + SQLPartitionBy partitionBy = x.getPartitionBy(); + if (partitionBy != null) { + println(); + partitionBy.accept(this); + } + this.printOracleSegmentAttributes(x); println(); + Boolean cache = x.getCache(); + if (cache != null) { + print(cache ? "CACHE" : "NOCACHE"); + println(); + } + Boolean parallel = x.getParallel(); if (parallel != null) { if (parallel) { diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java index 36753d245c..a4d53f3fb6 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java @@ -811,6 +811,10 @@ public interface SQLASTVisitor { boolean visit(SQLStructDataType x); void endVisit(SQLStructDataType x); + boolean visit(SQLStructDataType.Field x); void endVisit(SQLStructDataType.Field x); + + boolean visit(SQLDropMaterializedViewStatement x); + void endVisit(SQLDropMaterializedViewStatement x); } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java index 226ecc5b04..5107e3bf24 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -1914,6 +1914,16 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { } + @Override + public boolean visit(SQLDropMaterializedViewStatement x) { + return true; + } + + @Override + public void endVisit(SQLDropMaterializedViewStatement x) { + + } + public final boolean isEnabled(VisitorFeature feature) { return VisitorFeature.isEnabled(this.features, feature); } diff --git a/src/main/java/com/alibaba/druid/support/metrics/MetricCollector.java b/src/main/java/com/alibaba/druid/support/metrics/MetricCollector.java new file mode 100644 index 0000000000..7c53c0b303 --- /dev/null +++ b/src/main/java/com/alibaba/druid/support/metrics/MetricCollector.java @@ -0,0 +1,27 @@ +/* + * 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.support.metrics; + +import com.alibaba.druid.stat.DruidDataSourceStatManager; + +import java.util.concurrent.Callable; + +public class MetricCollector { + + public void collect() throws Exception { + + } +} diff --git a/src/main/java/com/alibaba/druid/util/FnvHash.java b/src/main/java/com/alibaba/druid/util/FnvHash.java index cff1491485..f1f888871d 100644 --- a/src/main/java/com/alibaba/druid/util/FnvHash.java +++ b/src/main/java/com/alibaba/druid/util/FnvHash.java @@ -625,5 +625,9 @@ public final class FnvHash { long INHERITS = fnv1a_64_lower("INHERITS"); long DELIMITED = fnv1a_64_lower("DELIMITED"); long TABLES = fnv1a_64_lower("TABLES"); + long PARALLEL = fnv1a_64_lower("PARALLEL"); + long BUILD = fnv1a_64_lower("BUILD"); + long NOCACHE = fnv1a_64_lower("NOCACHE"); + long NOPARALLEL = fnv1a_64_lower("NOPARALLEL"); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateMaterializedViewTest3.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateMaterializedViewTest3.java new file mode 100644 index 0000000000..c021f74530 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateMaterializedViewTest3.java @@ -0,0 +1,112 @@ +/* + * 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.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 java.util.List; + +public class OracleCreateMaterializedViewTest3 extends OracleTest { + + public void test_types() throws Exception { + String sql = // + "DROP MATERIALIZED VIEW ATOM_MVIEW.NONAUTO_CLAIM_FOLDER_T;\n" + + "--create materualized_view\n" + + "CREATE MATERIALIZED VIEW ATOM_MVIEW.NONAUTO_CLAIM_FOLDER_T\n" + + "PARTITION BY RANGE (BRANCH_COMPANY_CODE)\n" + + "( \n" + + " PARTITION P1010100 VALUES LESS THAN ('1020100')\n" + + " LOGGING\n" + + " NOCOMPRESS , \n" + + " PARTITION P1020100 VALUES LESS THAN ('1030100')\n" + + " LOGGING\n" + + " NOCOMPRESS , \n" + + " PARTITION P7040100 VALUES LESS THAN ('7050100')\n" + + " LOGGING\n" + + " NOCOMPRESS , \n" + + " PARTITION P7050100 VALUES LESS THAN ('7060100')\n" + + " LOGGING\n" + + " NOCOMPRESS , \n" + + " PARTITION P7060100 VALUES LESS THAN (MAXVALUE)\n" + + " LOGGING\n" + + " NOCOMPRESS\n" + + ")\n" + + "NOCACHE\n" + + "LOGGING\n" + + "NOCOMPRESS\n" + + "NOPARALLEL\n" + + "BUILD DEFERRED\n" + + "REFRESH FAST ON DEMAND\n" + + "WITH ROWID\n" + + "AS SELECT * FROM atom.NONAUTO_CLAIM_FOLDER_T@IDS_44;"; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(1); + print(statementList); + + assertEquals(2, statementList.size()); + + assertEquals("CREATE MATERIALIZED VIEW ATOM_MVIEW.NONAUTO_CLAIM_FOLDER_T\n" + + "PARTITION BY RANGE (BRANCH_COMPANY_CODE) (\n" + + "\tPARTITION P1010100 VALUES LESS THAN ('1020100')\n" + + "\t\tNOCOMPRESS\n" + + "\t\tLOGGING,\n" + + "\tPARTITION P1020100 VALUES LESS THAN ('1030100')\n" + + "\t\tNOCOMPRESS\n" + + "\t\tLOGGING,\n" + + "\tPARTITION P7040100 VALUES LESS THAN ('7050100')\n" + + "\t\tNOCOMPRESS\n" + + "\t\tLOGGING,\n" + + "\tPARTITION P7050100 VALUES LESS THAN ('7060100')\n" + + "\t\tNOCOMPRESS\n" + + "\t\tLOGGING,\n" + + "\tPARTITION P7060100 VALUES LESS THAN (MAXVALUE)\n" + + "\t\tNOCOMPRESS\n" + + "\t\tLOGGING\n" + + ")\n" + + "NOCOMPRESS\n" + + "LOGGING\n" + + "NOCACHE\n" + + "NOPARALLEL\n" + + "REFRESH FAST ON DEMAND\n" + + "AS\n" + + "SELECT *\n" + + "FROM atom.NONAUTO_CLAIM_FOLDER_T@IDS_44;",// + SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE)); + + 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()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + assertEquals(1, visitor.getTables().size()); + + assertEquals(2, visitor.getColumns().size()); + +// assertTrue(visitor.getColumns().contains(new TableStat.Column("times", "calendar_month_desc"))); + } +}