This is an automated email from the ASF dual-hosted git repository.
morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-doris.git
The following commit(s) were added to refs/heads/master by this push:
new c8705cc [MaterializedView] Support dropping materialized view (#3068)
c8705cc is described below
commit c8705ccf1296c50b5196b9521da143155589797b
Author: EmmyMiao87 <[email protected]>
AuthorDate: Wed Mar 11 18:16:24 2020 +0800
[MaterializedView] Support dropping materialized view (#3068)
`DROP MATERIALIZE VIEW [ IF EXISTS ] <mv_name> ON [db_name].<table_name>`
Parameters:
IF EXISTS: Do not throw an error if the materialized view does not exist.
A notice is issued in this case.
mv_name: The name of the materialized view to remove.
db_name: The name of db to which materialized view belongs.
table_name: The name of table to which materialized view belongs.
---
fe/src/main/cup/sql_parser.cup | 4 +
fe/src/main/java/org/apache/doris/alter/Alter.java | 55 ++++++---
.../doris/alter/MaterializedViewHandler.java | 134 ++++++++++++++-------
.../doris/analysis/CreateMaterializedViewStmt.java | 21 +---
.../doris/analysis/DropMaterializedViewStmt.java | 88 ++++++++++++++
.../java/org/apache/doris/catalog/Catalog.java | 6 +
.../java/org/apache/doris/catalog/OlapTable.java | 18 +++
.../main/java/org/apache/doris/qe/DdlExecutor.java | 3 +
.../doris/alter/MaterializedViewHandlerTest.java | 31 +++++
.../analysis/CreateMaterializedViewStmtTest.java | 87 +++++++++----
.../analysis/DropMaterializedViewStmtTest.java | 69 +++++++++++
.../planner/MaterializedViewFunctionTest.java | 4 +-
12 files changed, 419 insertions(+), 101 deletions(-)
diff --git a/fe/src/main/cup/sql_parser.cup b/fe/src/main/cup/sql_parser.cup
index e8ce8f4..0337f0a 100644
--- a/fe/src/main/cup/sql_parser.cup
+++ b/fe/src/main/cup/sql_parser.cup
@@ -1507,6 +1507,10 @@ drop_stmt ::=
{:
RESULT = new AlterTableStmt(tableName, Lists.newArrayList(new
DropIndexClause(indexName, tableName, false)));
:}
+ | KW_DROP KW_MATERIALIZED KW_VIEW opt_if_exists:ifExists ident:mvName
KW_ON table_name:tableName
+ {:
+ RESULT = new DropMaterializedViewStmt(ifExists, mvName, tableName);
+ :}
;
// Recover statement
diff --git a/fe/src/main/java/org/apache/doris/alter/Alter.java
b/fe/src/main/java/org/apache/doris/alter/Alter.java
index 766b42b..4edbbe1 100644
--- a/fe/src/main/java/org/apache/doris/alter/Alter.java
+++ b/fe/src/main/java/org/apache/doris/alter/Alter.java
@@ -31,6 +31,7 @@ import org.apache.doris.analysis.CreateIndexClause;
import org.apache.doris.analysis.CreateMaterializedViewStmt;
import org.apache.doris.analysis.DropColumnClause;
import org.apache.doris.analysis.DropIndexClause;
+import org.apache.doris.analysis.DropMaterializedViewStmt;
import org.apache.doris.analysis.DropPartitionClause;
import org.apache.doris.analysis.DropRollupClause;
import org.apache.doris.analysis.IndexDef;
@@ -56,6 +57,7 @@ import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.DdlException;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
+import org.apache.doris.common.MetaNotFoundException;
import org.apache.doris.common.UserException;
import org.apache.doris.common.util.DynamicPartitionUtil;
import org.apache.doris.common.util.PropertyAnalyzer;
@@ -94,7 +96,12 @@ public class Alter {
public void processCreateMaterializedView(CreateMaterializedViewStmt stmt)
throws DdlException, AnalysisException {
String tableName = stmt.getBaseIndexName();
- Database db = Catalog.getInstance().getDb(stmt.getDBName());
+ // check db
+ String dbName = stmt.getDBName();
+ Database db = Catalog.getInstance().getDb(dbName);
+ if (db == null) {
+ ErrorReport.reportDdlException(ErrorCode.ERR_BAD_DB_ERROR, dbName);
+ }
// check cluster capacity
Catalog.getCurrentSystemInfo().checkClusterCapacity(stmt.getClusterName());
// check db quota
@@ -107,24 +114,44 @@ public class Alter {
throw new DdlException("Do not support alter non-OLAP table["
+ tableName + "]");
}
OlapTable olapTable = (OlapTable) table;
+ olapTable.checkStableAndNormal(db.getClusterName());
+
+
((MaterializedViewHandler)materializedViewHandler).processCreateMaterializedView(stmt,
db, olapTable);
+ } finally {
+ db.writeUnlock();
+ }
+ }
+ public void processDropMaterializedView(DropMaterializedViewStmt stmt)
throws DdlException, MetaNotFoundException {
+ // check db
+ String dbName = stmt.getTableName().getDb();
+ Database db = Catalog.getInstance().getDb(dbName);
+ if (db == null) {
+ ErrorReport.reportDdlException(ErrorCode.ERR_BAD_DB_ERROR, dbName);
+ }
+
+ db.writeLock();
+ try {
+ String tableName = stmt.getTableName().getTbl();
+ Table table = db.getTable(tableName);
+ // if table exists
+ if (table == null) {
+ ErrorReport.reportDdlException(ErrorCode.ERR_BAD_TABLE_ERROR,
tableName);
+ }
+ // check table type
+ if (table.getType() != TableType.OLAP) {
+ throw new DdlException("Do not support non-OLAP table [" +
tableName + "] when drop materialized view");
+ }
+ // check table state
+ OlapTable olapTable = (OlapTable) table;
if (olapTable.getState() != OlapTableState.NORMAL) {
throw new DdlException("Table[" + table.getName() + "]'s state
is not NORMAL. "
- + "Do not allow doing
materialized view");
- }
- // check if all tablets are healthy, and no tablet is in tablet
scheduler
- boolean isStable =
olapTable.isStable(Catalog.getCurrentSystemInfo(),
-
Catalog.getCurrentCatalog().getTabletScheduler(),
- db.getClusterName());
- if (!isStable) {
- throw new DdlException("table [" + olapTable.getName() + "] is
not stable."
- + " Some tablets of this table
may not be healthy or are being "
- + "scheduled."
- + " You need to repair the
table first"
- + " or stop cluster balance.
See 'help admin;'.");
+ + "Do not allow doing DROP ops");
}
-
((MaterializedViewHandler)materializedViewHandler).processCreateMaterializedView(stmt,
db, olapTable);
+ // drop materialized view
+
((MaterializedViewHandler)materializedViewHandler).processDropMaterializedView(stmt,
db, olapTable);
+
} finally {
db.writeUnlock();
}
diff --git
a/fe/src/main/java/org/apache/doris/alter/MaterializedViewHandler.java
b/fe/src/main/java/org/apache/doris/alter/MaterializedViewHandler.java
index 23724f8..f333dbb 100644
--- a/fe/src/main/java/org/apache/doris/alter/MaterializedViewHandler.java
+++ b/fe/src/main/java/org/apache/doris/alter/MaterializedViewHandler.java
@@ -23,6 +23,7 @@ import org.apache.doris.analysis.AlterClause;
import org.apache.doris.analysis.CancelAlterTableStmt;
import org.apache.doris.analysis.CancelStmt;
import org.apache.doris.analysis.CreateMaterializedViewStmt;
+import org.apache.doris.analysis.DropMaterializedViewStmt;
import org.apache.doris.analysis.DropRollupClause;
import org.apache.doris.analysis.MVColumnItem;
import org.apache.doris.catalog.AggregateType;
@@ -46,6 +47,7 @@ import org.apache.doris.common.DdlException;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.FeConstants;
+import org.apache.doris.common.MetaNotFoundException;
import org.apache.doris.common.util.ListComparator;
import org.apache.doris.common.util.PropertyAnalyzer;
import org.apache.doris.common.util.Util;
@@ -638,68 +640,31 @@ public class MaterializedViewHandler extends AlterHandler
{
return baseIndexId;
}
- public void processBatchDropRollup(List<AlterClause> dropRollupClauses,
Database db, OlapTable olapTable) throws DdlException {
+ public void processBatchDropRollup(List<AlterClause> dropRollupClauses,
Database db, OlapTable olapTable)
+ throws DdlException, MetaNotFoundException {
db.writeLock();
try {
- // just for log
- Set<String> rollupNameSet = new HashSet<>();
- Preconditions.checkState(olapTable.getState() ==
OlapTableState.NORMAL, olapTable.getState().name());
- TabletInvertedIndex invertedIndex =
Catalog.getCurrentInvertedIndex();
- long dbId = db.getId();
- long tableId = olapTable.getId();
-
// check drop rollup index operation
for (AlterClause alterClause : dropRollupClauses) {
DropRollupClause dropRollupClause = (DropRollupClause)
alterClause;
-
- // make sure we got db write lock here.
- // up to here, table's state can only be NORMAL.
- String rollupIndexName = dropRollupClause.getRollupName();
- if (rollupIndexName.equals(olapTable.getName())) {
- throw new DdlException("Cannot drop base index by using
DROP ROLLUP.");
- }
-
- if (!olapTable.hasMaterializedIndex(rollupIndexName)) {
- throw new DdlException("Rollup index[" + rollupIndexName +
"] does not exist in table["
- + olapTable.getName() + "]");
- }
-
- long rollupIndexId =
olapTable.getIndexIdByName(rollupIndexName);
- int rollupSchemaHash =
olapTable.getSchemaHashByIndexId(rollupIndexId);
- Preconditions.checkState(rollupSchemaHash != -1);
-
- for (Partition partition : olapTable.getPartitions()) {
- MaterializedIndex rollupIndex =
partition.getIndex(rollupIndexId);
- Preconditions.checkNotNull(rollupIndex);
- }
-
+ checkDropMaterializedView(dropRollupClause.getRollupName(),
olapTable);
}
- Set<Long> indexIdSet = new HashSet<>();
// drop data in memory
+ Set<Long> indexIdSet = new HashSet<>();
+ Set<String> rollupNameSet = new HashSet<>();
for (AlterClause alterClause : dropRollupClauses) {
DropRollupClause dropRollupClause = (DropRollupClause)
alterClause;
String rollupIndexName = dropRollupClause.getRollupName();
-
- long rollupIndexId =
olapTable.getIndexIdByName(rollupIndexName);
- for (Partition partition : olapTable.getPartitions()) {
- MaterializedIndex rollupIndex =
partition.getIndex(rollupIndexId);
- // delete rollup index
- partition.deleteRollupIndex(rollupIndexId);
- // remove tablets from inverted index
- for (Tablet tablet : rollupIndex.getTablets()) {
- long tabletId = tablet.getId();
- invertedIndex.deleteTablet(tabletId);
- }
- }
- olapTable.deleteIndexInfo(rollupIndexName);
-
+ long rollupIndexId = dropMaterializedView(rollupIndexName,
olapTable);
indexIdSet.add(rollupIndexId);
rollupNameSet.add(rollupIndexName);
}
// batch log drop rollup operation
EditLog editLog = Catalog.getInstance().getEditLog();
+ long dbId = db.getId();
+ long tableId = olapTable.getId();
editLog.logBatchDropRollup(new BatchDropInfo(dbId, tableId,
indexIdSet));
LOG.info("finished drop rollup index[{}] in table[{}]",
String.join("", rollupNameSet), olapTable.getName());
} finally {
@@ -707,6 +672,83 @@ public class MaterializedViewHandler extends AlterHandler {
}
}
+ public void processDropMaterializedView(DropMaterializedViewStmt
dropMaterializedViewStmt, Database db,
+ OlapTable olapTable) throws DdlException, MetaNotFoundException {
+ db.writeLock();
+ try {
+ String mvName = dropMaterializedViewStmt.getMvName();
+ // Step1: check drop mv index operation
+ checkDropMaterializedView(mvName, olapTable);
+ // Step2; drop data in memory
+ long mvIndexId = dropMaterializedView(mvName, olapTable);
+ // Step3: log drop mv operation
+ EditLog editLog = Catalog.getInstance().getEditLog();
+ editLog.logDropRollup(new DropInfo(db.getId(), olapTable.getId(),
mvIndexId));
+ LOG.info("finished drop materialized view [{}] in table [{}]",
mvName, olapTable.getName());
+ } catch (MetaNotFoundException e) {
+ if (dropMaterializedViewStmt.isIfExists()) {
+ LOG.info(e.getMessage());
+ } else {
+ throw e;
+ }
+ } finally {
+ db.writeUnlock();
+ }
+ }
+
+ /**
+ * Make sure we got db write lock before using this method.
+ * Up to here, table's state can only be NORMAL.
+ *
+ * @param mvName
+ * @param olapTable
+ */
+ private void checkDropMaterializedView(String mvName, OlapTable olapTable)
+ throws DdlException, MetaNotFoundException {
+ Preconditions.checkState(olapTable.getState() ==
OlapTableState.NORMAL, olapTable.getState().name());
+ if (mvName.equals(olapTable.getName())) {
+ throw new DdlException("Cannot drop base index by using DROP
ROLLUP or DROP MATERIALIZED VIEW.");
+ }
+
+ if (!olapTable.hasMaterializedIndex(mvName)) {
+ throw new MetaNotFoundException(
+ "Materialized view [" + mvName + "] does not exist in
table [" + olapTable.getName() + "]");
+ }
+
+ long mvIndexId = olapTable.getIndexIdByName(mvName);
+ int mvSchemaHash = olapTable.getSchemaHashByIndexId(mvIndexId);
+ Preconditions.checkState(mvSchemaHash != -1);
+
+ for (Partition partition : olapTable.getPartitions()) {
+ MaterializedIndex materializedIndex =
partition.getIndex(mvIndexId);
+ Preconditions.checkNotNull(materializedIndex);
+ }
+ }
+
+ /**
+ * Return mv index id which has been dropped
+ *
+ * @param mvName
+ * @param olapTable
+ * @return
+ */
+ private long dropMaterializedView(String mvName, OlapTable olapTable) {
+ long mvIndexId = olapTable.getIndexIdByName(mvName);
+ TabletInvertedIndex invertedIndex = Catalog.getCurrentInvertedIndex();
+ for (Partition partition : olapTable.getPartitions()) {
+ MaterializedIndex rollupIndex = partition.getIndex(mvIndexId);
+ // delete rollup index
+ partition.deleteRollupIndex(mvIndexId);
+ // remove tablets from inverted index
+ for (Tablet tablet : rollupIndex.getTablets()) {
+ long tabletId = tablet.getId();
+ invertedIndex.deleteTablet(tabletId);
+ }
+ }
+ olapTable.deleteIndexInfo(mvName);
+ return mvIndexId;
+ }
+
public void replayDropRollup(DropInfo dropInfo, Catalog catalog) {
Database db = catalog.getDb(dropInfo.getDbId());
db.writeLock();
@@ -1045,7 +1087,7 @@ public class MaterializedViewHandler extends AlterHandler
{
@Override
public void process(List<AlterClause> alterClauses, String clusterName,
Database db, OlapTable olapTable)
- throws DdlException, AnalysisException {
+ throws DdlException, AnalysisException, MetaNotFoundException {
if (olapTable.existTempPartitions()) {
throw new DdlException("Can not alter table when there are temp
partitions in table");
diff --git
a/fe/src/main/java/org/apache/doris/analysis/CreateMaterializedViewStmt.java
b/fe/src/main/java/org/apache/doris/analysis/CreateMaterializedViewStmt.java
index 698b3b7..d73bbd1 100644
--- a/fe/src/main/java/org/apache/doris/analysis/CreateMaterializedViewStmt.java
+++ b/fe/src/main/java/org/apache/doris/analysis/CreateMaterializedViewStmt.java
@@ -29,7 +29,6 @@ import org.apache.doris.common.UserException;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.List;
@@ -135,8 +134,8 @@ public class CreateMaterializedViewStmt extends DdlStmt {
throw new AnalysisException("The materialized view must contain at
least one column");
}
boolean meetAggregate = false;
- Set<String> mvKeyColumnNameSet = Sets.newHashSet();
- Map<String, Set<String>> mvAggColumnNameToFunctionNames =
Maps.newHashMap();
+ // TODO(ml): support same column with different aggregation function
+ Set<String> mvColumnNameSet = Sets.newHashSet();
/**
* 1. The columns of mv must be a single column or a aggregate column
without any calculate.
* Also the children of aggregate column must be a single column
without any calculate.
@@ -158,9 +157,9 @@ public class CreateMaterializedViewStmt extends DdlStmt {
throw new AnalysisException("The aggregate column should
be after the single column");
}
SlotRef slotRef = (SlotRef) selectListItem.getExpr();
+ // check duplicate column
String columnName = slotRef.getColumnName().toLowerCase();
- // check duplicate key
- if (!mvKeyColumnNameSet.add(columnName)) {
+ if (!mvColumnNameSet.add(columnName)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_DUP_FIELDNAME, columnName);
}
MVColumnItem mvColumnItem = new MVColumnItem(columnName);
@@ -189,19 +188,11 @@ public class CreateMaterializedViewStmt extends DdlStmt {
+ "Error function: " +
functionCallExpr.toSqlImpl());
}
meetAggregate = true;
- // check duplicate value
+ // check duplicate column
String columnName = slotRef.getColumnName().toLowerCase();
- if (mvKeyColumnNameSet.contains(columnName)) {
+ if (!mvColumnNameSet.add(columnName)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_DUP_FIELDNAME, columnName);
}
- Set<String> functionNames =
mvAggColumnNameToFunctionNames.get(columnName);
- if (functionNames == null) {
- functionNames = Sets.newHashSet();
- }
- if (!functionNames.add(functionName.toLowerCase())) {
-
ErrorReport.reportAnalysisException(ErrorCode.ERR_DUP_FIELDNAME, columnName);
- }
- mvAggColumnNameToFunctionNames.put(columnName, functionNames);
if (beginIndexOfAggregation == -1) {
beginIndexOfAggregation = i;
diff --git
a/fe/src/main/java/org/apache/doris/analysis/DropMaterializedViewStmt.java
b/fe/src/main/java/org/apache/doris/analysis/DropMaterializedViewStmt.java
new file mode 100644
index 0000000..e416444
--- /dev/null
+++ b/fe/src/main/java/org/apache/doris/analysis/DropMaterializedViewStmt.java
@@ -0,0 +1,88 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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 org.apache.doris.analysis;
+
+import org.apache.doris.catalog.Catalog;
+import org.apache.doris.common.AnalysisException;
+import org.apache.doris.common.ErrorCode;
+import org.apache.doris.common.ErrorReport;
+import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.qe.ConnectContext;
+
+import com.google.common.base.Strings;
+
+/**
+ * DROP MATERIALIZE VIEW [ IF EXISTS ] <mv_name> ON [db_name].<table_name>
+ *
+ * Parameters
+ * IF EXISTS: Do not throw an error if the materialized view does not exist. A
notice is issued in this case.
+ * mv_name: The name of the materialized view to remove.
+ * db_name: The name of db to which materialized view belongs.
+ * table_name: The name of table to which materialized view belongs.
+ */
+public class DropMaterializedViewStmt extends DdlStmt {
+
+ private String mvName;
+ private TableName tableName;
+ private boolean ifExists;
+
+ public DropMaterializedViewStmt(boolean ifExists, String mvName, TableName
tableName) {
+ this.mvName = mvName;
+ this.tableName = tableName;
+ this.ifExists = ifExists;
+ }
+
+ public String getMvName() {
+ return mvName;
+ }
+
+ public TableName getTableName() {
+ return tableName;
+ }
+
+ public boolean isIfExists() {
+ return ifExists;
+ }
+
+ @Override
+ public void analyze(Analyzer analyzer) throws UserException {
+ if (Strings.isNullOrEmpty(mvName)) {
+ throw new AnalysisException("The materialized name could not be
empty or null.");
+ }
+ tableName.analyze(analyzer);
+
+ // check access
+ if
(!Catalog.getCurrentCatalog().getAuth().checkTblPriv(ConnectContext.get(),
tableName.getDb(),
+ tableName.getTbl(), PrivPredicate.DROP)) {
+
ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR,
"DROP");
+ }
+ }
+
+ @Override
+ public String toSql() {
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append("DROP MATERIALIZED VIEW ");
+ if (ifExists) {
+ stringBuilder.append("IF EXISTS ");
+ }
+ stringBuilder.append("`").append(mvName).append("` ");
+ stringBuilder.append("ON ").append(tableName.toSql());
+ return stringBuilder.toString();
+ }
+}
diff --git a/fe/src/main/java/org/apache/doris/catalog/Catalog.java
b/fe/src/main/java/org/apache/doris/catalog/Catalog.java
index 6e43668..222990f 100644
--- a/fe/src/main/java/org/apache/doris/catalog/Catalog.java
+++ b/fe/src/main/java/org/apache/doris/catalog/Catalog.java
@@ -54,6 +54,7 @@ import org.apache.doris.analysis.DistributionDesc;
import org.apache.doris.analysis.DropClusterStmt;
import org.apache.doris.analysis.DropDbStmt;
import org.apache.doris.analysis.DropFunctionStmt;
+import org.apache.doris.analysis.DropMaterializedViewStmt;
import org.apache.doris.analysis.DropPartitionClause;
import org.apache.doris.analysis.DropTableStmt;
import org.apache.doris.analysis.FunctionName;
@@ -105,6 +106,7 @@ import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.FeConstants;
import org.apache.doris.common.FeMetaVersion;
import org.apache.doris.common.MarkedCountDownLatch;
+import org.apache.doris.common.MetaNotFoundException;
import org.apache.doris.common.Pair;
import org.apache.doris.common.UserException;
import org.apache.doris.common.io.Text;
@@ -4894,6 +4896,10 @@ public class Catalog {
this.alter.processCreateMaterializedView(stmt);
}
+ public void dropMaterializedView(DropMaterializedViewStmt stmt) throws
DdlException, MetaNotFoundException {
+ this.alter.processDropMaterializedView(stmt);
+ }
+
/*
* used for handling CacnelAlterStmt (for client is the CANCEL ALTER
* command). including SchemaChangeHandler and RollupHandler
diff --git a/fe/src/main/java/org/apache/doris/catalog/OlapTable.java
b/fe/src/main/java/org/apache/doris/catalog/OlapTable.java
index 56b1a1f..595b8a7 100644
--- a/fe/src/main/java/org/apache/doris/catalog/OlapTable.java
+++ b/fe/src/main/java/org/apache/doris/catalog/OlapTable.java
@@ -1066,6 +1066,24 @@ public class OlapTable extends Table {
return dataSize;
}
+ public void checkStableAndNormal(String clusterName) throws DdlException {
+ if (state != OlapTableState.NORMAL) {
+ throw new DdlException("Table[" + name + "]'s state is not NORMAL.
"
+ + "Do not allow doing materialized view");
+ }
+ // check if all tablets are healthy, and no tablet is in tablet
scheduler
+ boolean isStable = isStable(Catalog.getCurrentSystemInfo(),
+ Catalog.getCurrentCatalog().getTabletScheduler(),
+ clusterName);
+ if (!isStable) {
+ throw new DdlException("table [" + name + "] is not stable."
+ + " Some tablets of this table may not be healthy or are
being "
+ + "scheduled."
+ + " You need to repair the table first"
+ + " or stop cluster balance. See 'help admin;'.");
+ }
+ }
+
public boolean isStable(SystemInfoService infoService, TabletScheduler
tabletScheduler, String clusterName) {
int availableBackendsNum =
infoService.getClusterBackendIds(clusterName, true).size();
for (Partition partition : idToPartition.values()) {
diff --git a/fe/src/main/java/org/apache/doris/qe/DdlExecutor.java
b/fe/src/main/java/org/apache/doris/qe/DdlExecutor.java
index ac2a0db..188c1f8 100644
--- a/fe/src/main/java/org/apache/doris/qe/DdlExecutor.java
+++ b/fe/src/main/java/org/apache/doris/qe/DdlExecutor.java
@@ -49,6 +49,7 @@ import org.apache.doris.analysis.DropClusterStmt;
import org.apache.doris.analysis.DropDbStmt;
import org.apache.doris.analysis.DropFileStmt;
import org.apache.doris.analysis.DropFunctionStmt;
+import org.apache.doris.analysis.DropMaterializedViewStmt;
import org.apache.doris.analysis.DropRepositoryStmt;
import org.apache.doris.analysis.DropRoleStmt;
import org.apache.doris.analysis.DropTableStmt;
@@ -101,6 +102,8 @@ public class DdlExecutor {
catalog.dropTable((DropTableStmt) ddlStmt);
} else if (ddlStmt instanceof CreateMaterializedViewStmt) {
catalog.createMaterializedView((CreateMaterializedViewStmt)
ddlStmt);
+ } else if (ddlStmt instanceof DropMaterializedViewStmt) {
+ catalog.dropMaterializedView((DropMaterializedViewStmt) ddlStmt);
} else if (ddlStmt instanceof AlterTableStmt) {
catalog.alterTable((AlterTableStmt) ddlStmt);
} else if (ddlStmt instanceof AlterViewStmt) {
diff --git
a/fe/src/test/java/org/apache/doris/alter/MaterializedViewHandlerTest.java
b/fe/src/test/java/org/apache/doris/alter/MaterializedViewHandlerTest.java
index 3ae3879..585d78b 100644
--- a/fe/src/test/java/org/apache/doris/alter/MaterializedViewHandlerTest.java
+++ b/fe/src/test/java/org/apache/doris/alter/MaterializedViewHandlerTest.java
@@ -273,4 +273,35 @@ public class MaterializedViewHandlerTest {
}
}
+ @Test
+ public void testCheckDropMaterializedView(@Injectable OlapTable olapTable,
@Injectable Partition partition,
+ @Injectable MaterializedIndex materializedIndex) {
+ String mvName = "mv_1";
+ new Expectations() {
+ {
+ olapTable.getState();
+ result = OlapTable.OlapTableState.NORMAL;
+ olapTable.getName();
+ result = "table1";
+ olapTable.hasMaterializedIndex(mvName);
+ result = true;
+ olapTable.getIndexIdByName(mvName);
+ result = 1L;
+ olapTable.getSchemaHashByIndexId(1L);
+ result = 1;
+ olapTable.getPartitions();
+ result = Lists.newArrayList(partition);
+ partition.getIndex(1L);
+ result = materializedIndex;
+ }
+ };
+ MaterializedViewHandler materializedViewHandler = new
MaterializedViewHandler();
+ try {
+ Deencapsulation.invoke(materializedViewHandler,
"checkDropMaterializedView", mvName, olapTable);
+ } catch (Exception e) {
+ Assert.fail(e.getMessage());
+ }
+
+ }
+
}
diff --git
a/fe/src/test/java/org/apache/doris/analysis/CreateMaterializedViewStmtTest.java
b/fe/src/test/java/org/apache/doris/analysis/CreateMaterializedViewStmtTest.java
index 5e58630..de6c5a3 100644
---
a/fe/src/test/java/org/apache/doris/analysis/CreateMaterializedViewStmtTest.java
+++
b/fe/src/test/java/org/apache/doris/analysis/CreateMaterializedViewStmtTest.java
@@ -252,8 +252,7 @@ public class CreateMaterializedViewStmtTest {
@Injectable SlotRef slotRef2,
@Injectable FunctionCallExpr
functionCallExpr,
@Injectable TableRef tableRef,
- @Injectable SelectStmt selectStmt,
- @Injectable GroupByClause groupByClause) throws UserException {
+ @Injectable SelectStmt selectStmt)
throws UserException {
SelectList selectList = new SelectList();
SelectListItem selectListItem1 = new SelectListItem(slotRef1, null);
selectList.addItem(selectListItem1);
@@ -262,8 +261,6 @@ public class CreateMaterializedViewStmtTest {
OrderByElement orderByElement1 = new OrderByElement(functionCallExpr,
false, false);
OrderByElement orderByElement2 = new OrderByElement(slotRef1, false,
false);
ArrayList<OrderByElement> orderByElementList =
Lists.newArrayList(orderByElement1, orderByElement2);
- List<Expr> groupByList = Lists.newArrayList();
- groupByList.add(slotRef1);
new Expectations() {
{
@@ -338,13 +335,58 @@ public class CreateMaterializedViewStmtTest {
}
@Test
+ public void testDuplicateColumn1(@Injectable SlotRef slotRef1, @Injectable
SlotRef slotRef2,
+ @Injectable FunctionCallExpr functionCallExpr1, @Injectable
FunctionCallExpr functionCallExpr2,
+ @Injectable SelectStmt selectStmt) throws UserException {
+ SelectList selectList = new SelectList();
+ SelectListItem selectListItem1 = new SelectListItem(slotRef1, null);
+ selectList.addItem(selectListItem1);
+ SelectListItem selectListItem2 = new SelectListItem(functionCallExpr1,
null);
+ selectList.addItem(selectListItem2);
+ SelectListItem selectListItem3 = new SelectListItem(functionCallExpr2,
null);
+ selectList.addItem(selectListItem3);
+
+ new Expectations() {
+ {
+ analyzer.getClusterName();
+ result = "default";
+ selectStmt.analyze(analyzer);
+ selectStmt.getSelectList();
+ result = selectList;
+ slotRef1.getColumnName();
+ result = "k1";
+ slotRef2.getColumnName();
+ result = "k2";
+ functionCallExpr1.getFnName().getFunction();
+ result = "sum";
+ functionCallExpr1.getChildren();
+ result = Lists.newArrayList(slotRef2);
+ functionCallExpr1.getChild(0);
+ result = slotRef2;
+ functionCallExpr2.getFnName().getFunction();
+ result = "max";
+ functionCallExpr2.getChildren();
+ result = Lists.newArrayList(slotRef2);
+ functionCallExpr2.getChild(0);
+ result = slotRef2;
+ }
+ };
+ CreateMaterializedViewStmt createMaterializedViewStmt = new
CreateMaterializedViewStmt("test", selectStmt, null);
+ try {
+ createMaterializedViewStmt.analyze(analyzer);
+ Assert.fail();
+ } catch (UserException e) {
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
public void testOrderByColumnsLessThenGroupByColumns(@Injectable SlotRef
slotRef1,
@Injectable SlotRef
slotRef2,
@Injectable
FunctionCallExpr functionCallExpr,
@Injectable SlotRef
functionChild0,
@Injectable TableRef
tableRef,
- @Injectable
SelectStmt selectStmt,
- @Injectable GroupByClause groupByClause) throws UserException {
+ @Injectable
SelectStmt selectStmt) throws UserException {
SelectList selectList = new SelectList();
SelectListItem selectListItem1 = new SelectListItem(slotRef1, null);
selectList.addItem(selectListItem1);
@@ -355,11 +397,6 @@ public class CreateMaterializedViewStmtTest {
OrderByElement orderByElement1 = new OrderByElement(slotRef1, false,
false);
ArrayList<OrderByElement> orderByElementList =
Lists.newArrayList(orderByElement1);
-
- List<Expr> groupByList = Lists.newArrayList();
- groupByList.add(slotRef1);
- groupByList.add(slotRef2);
-
new Expectations() {
{
analyzer.getClusterName();
@@ -407,7 +444,7 @@ public class CreateMaterializedViewStmtTest {
@Injectable SlotRef functionChild0,
@Injectable TableRef tableRef,
@Injectable SelectStmt selectStmt,
- @Injectable GroupByClause groupByClause) throws UserException {
+ @Injectable AggregateInfo aggregateInfo) throws UserException {
SelectList selectList = new SelectList();
SelectListItem selectListItem1 = new SelectListItem(slotRef1, null);
selectList.addItem(selectListItem1);
@@ -426,14 +463,12 @@ public class CreateMaterializedViewStmtTest {
final String columnName4 = "v1";
final String columnName5 = "sum_v2";
- List<Expr> groupByList = Lists.newArrayList();
- groupByList.add(slotRef1);
- groupByList.add(slotRef2);
- groupByList.add(slotRef3);
new Expectations() {
{
analyzer.getClusterName();
result = "default";
+ selectStmt.getAggInfo();
+ result = aggregateInfo;
selectStmt.getSelectList();
result = selectList;
selectStmt.getTableRefs();
@@ -470,6 +505,7 @@ public class CreateMaterializedViewStmtTest {
CreateMaterializedViewStmt createMaterializedViewStmt = new
CreateMaterializedViewStmt("test", selectStmt, null);
try {
createMaterializedViewStmt.analyze(analyzer);
+ Assert.assertEquals(KeysType.AGG_KEYS,
createMaterializedViewStmt.getMVKeysType());
List<MVColumnItem> mvColumns =
createMaterializedViewStmt.getMVColumnItemList();
Assert.assertEquals(5, mvColumns.size());
MVColumnItem mvColumn0 = mvColumns.get(0);
@@ -525,6 +561,8 @@ public class CreateMaterializedViewStmtTest {
{
analyzer.getClusterName();
result = "default";
+ selectStmt.getAggInfo();
+ result = null;
selectStmt.getSelectList();
result = selectList;
selectStmt.getTableRefs();
@@ -565,6 +603,7 @@ public class CreateMaterializedViewStmtTest {
CreateMaterializedViewStmt createMaterializedViewStmt = new
CreateMaterializedViewStmt("test", selectStmt, null);
try {
createMaterializedViewStmt.analyze(analyzer);
+ Assert.assertEquals(KeysType.DUP_KEYS,
createMaterializedViewStmt.getMVKeysType());
List<MVColumnItem> mvColumns =
createMaterializedViewStmt.getMVColumnItemList();
Assert.assertEquals(4, mvColumns.size());
MVColumnItem mvColumn0 = mvColumns.get(0);
@@ -599,7 +638,7 @@ public class CreateMaterializedViewStmtTest {
@Injectable SlotRef functionChild0,
@Injectable TableRef tableRef,
@Injectable SelectStmt selectStmt,
- @Injectable GroupByClause groupByClause) throws UserException {
+ @Injectable AggregateInfo aggregateInfo) throws UserException {
SelectList selectList = new SelectList();
SelectListItem selectListItem1 = new SelectListItem(slotRef1, null);
selectList.addItem(selectListItem1);
@@ -613,13 +652,12 @@ public class CreateMaterializedViewStmtTest {
final String columnName1 = "k1";
final String columnName2 = "v1";
final String columnName3 = "sum_v2";
- List<Expr> groupByList = Lists.newArrayList();
- groupByList.add(slotRef1);
- groupByList.add(slotRef2);
new Expectations() {
{
analyzer.getClusterName();
result = "default";
+ selectStmt.getAggInfo();
+ result = aggregateInfo;
selectStmt.getSelectList();
result = selectList;
selectStmt.getTableRefs();
@@ -651,6 +689,7 @@ public class CreateMaterializedViewStmtTest {
CreateMaterializedViewStmt createMaterializedViewStmt = new
CreateMaterializedViewStmt("test", selectStmt, null);
try {
createMaterializedViewStmt.analyze(analyzer);
+ Assert.assertEquals(KeysType.AGG_KEYS,
createMaterializedViewStmt.getMVKeysType());
List<MVColumnItem> mvColumns =
createMaterializedViewStmt.getMVColumnItemList();
Assert.assertEquals(3, mvColumns.size());
MVColumnItem mvColumn0 = mvColumns.get(0);
@@ -679,17 +718,17 @@ public class CreateMaterializedViewStmtTest {
public void testDeduplicateMV(@Injectable SlotRef slotRef1,
@Injectable TableRef tableRef,
@Injectable SelectStmt selectStmt,
- @Injectable GroupByClause groupByClause) throws UserException {
+ @Injectable AggregateInfo aggregateInfo) throws UserException {
SelectList selectList = new SelectList();
SelectListItem selectListItem1 = new SelectListItem(slotRef1, null);
selectList.addItem(selectListItem1);
final String columnName1 = "k1";
- List<Expr> groupByList = Lists.newArrayList();
- groupByList.add(slotRef1);
new Expectations() {
{
analyzer.getClusterName();
result = "default";
+ selectStmt.getAggInfo();
+ result = aggregateInfo;
selectStmt.getSelectList();
result = selectList;
selectStmt.analyze(analyzer);
@@ -709,7 +748,7 @@ public class CreateMaterializedViewStmtTest {
CreateMaterializedViewStmt createMaterializedViewStmt = new
CreateMaterializedViewStmt("test", selectStmt, null);
try {
createMaterializedViewStmt.analyze(analyzer);
- Assert.assertTrue(KeysType.AGG_KEYS ==
createMaterializedViewStmt.getMVKeysType());
+ Assert.assertEquals(KeysType.AGG_KEYS,
createMaterializedViewStmt.getMVKeysType());
List<MVColumnItem> mvSchema =
createMaterializedViewStmt.getMVColumnItemList();
Assert.assertEquals(1, mvSchema.size());
Assert.assertTrue(mvSchema.get(0).isKey());
diff --git
a/fe/src/test/java/org/apache/doris/analysis/DropMaterializedViewStmtTest.java
b/fe/src/test/java/org/apache/doris/analysis/DropMaterializedViewStmtTest.java
new file mode 100644
index 0000000..068a031
--- /dev/null
+++
b/fe/src/test/java/org/apache/doris/analysis/DropMaterializedViewStmtTest.java
@@ -0,0 +1,69 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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 org.apache.doris.analysis;
+
+import org.apache.doris.common.ErrorCode;
+import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.qe.ConnectContext;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import mockit.Expectations;
+import mockit.Injectable;
+import mockit.Mocked;
+
+public class DropMaterializedViewStmtTest {
+
+ @Mocked
+ Analyzer analyzer;
+ @Mocked
+ PaloAuth paloAuth;
+
+ @Test
+ public void testEmptyMVName(@Injectable TableName tableName) {
+ DropMaterializedViewStmt stmt = new DropMaterializedViewStmt(false,
"", tableName);
+ try {
+ stmt.analyze(analyzer);
+ Assert.fail();
+ } catch (UserException e) {
+ Assert.assertTrue(e.getMessage().contains("could not be empty"));
+ }
+ }
+
+ @Test
+ public void testNoPermission(@Injectable TableName tableName) {
+ new Expectations() {
+ {
+ paloAuth.checkTblPriv(ConnectContext.get(), tableName.getDb(),
+ tableName.getTbl(), PrivPredicate.DROP);
+ result = false;
+ }
+ };
+ DropMaterializedViewStmt stmt = new DropMaterializedViewStmt(false,
"test", tableName);
+ try {
+ stmt.analyze(analyzer);
+ Assert.fail();
+ } catch (UserException e) {
+ Assert.assertTrue(e.getMessage().contains("Access denied;"));
+ }
+
+ }
+}
diff --git
a/fe/src/test/java/org/apache/doris/planner/MaterializedViewFunctionTest.java
b/fe/src/test/java/org/apache/doris/planner/MaterializedViewFunctionTest.java
index 80e6ad4..43be8db 100644
---
a/fe/src/test/java/org/apache/doris/planner/MaterializedViewFunctionTest.java
+++
b/fe/src/test/java/org/apache/doris/planner/MaterializedViewFunctionTest.java
@@ -135,8 +135,8 @@ public class MaterializedViewFunctionTest {
@Test
public void testAggQueryOnAggMV1() throws Exception {
- String createMVSQL = "create materialized view " + EMPS_MV_NAME + " as
select deptno, sum(salary), max" + ""
- + "(salary) from " + EMPS_TABLE_NAME + " group by deptno;";
+ String createMVSQL = "create materialized view " + EMPS_MV_NAME + " as
select deptno, sum(salary), "
+ + "max(commission) from " + EMPS_TABLE_NAME + " group by
deptno;";
String query = "select sum(salary), deptno from " + EMPS_TABLE_NAME +
" group by deptno;";
dorisAssert.withMaterializedView(createMVSQL).query(query).explainContains(QUERY_USE_EMPS_MV);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]