- * Different partitions may generate the same PartitionKeyDesc through logical calculations
- * (such as selecting only one column, or rolling up partitions), so it is a one to many relationship
- *
- * @return related PartitionKeyDesc ==> relatedPartitionIds
- * @throws AnalysisException
- */
- public Map> generateRelatedPartitionDescs() throws AnalysisException {
- if (mvPartitionInfo.getPartitionType() == MTMVPartitionType.SELF_MANAGE) {
- return Maps.newHashMap();
- }
- Map> res = new HashMap<>();
- int relatedColPos = mvPartitionInfo.getRelatedColPos();
- Map relatedPartitionItems = mvPartitionInfo.getRelatedTable()
- .getPartitionItemsByTimeFilter(relatedColPos,
- MTMVUtil.generateMTMVPartitionSyncConfigByProperties(mvProperties));
- for (Entry entry : relatedPartitionItems.entrySet()) {
- PartitionKeyDesc partitionKeyDesc = entry.getValue().toPartitionKeyDesc(relatedColPos);
- if (res.containsKey(partitionKeyDesc)) {
- res.get(partitionKeyDesc).add(entry.getKey());
- } else {
- res.put(partitionKeyDesc, Sets.newHashSet(entry.getKey()));
- }
- }
- return res;
- }
-
/**
* Calculate the partition and associated partition mapping relationship of the MTMV
* It is the result of real-time comparison calculation, so there may be some costs,
@@ -354,13 +324,19 @@ public class MTMV extends OlapTable {
if (mvPartitionInfo.getPartitionType() == MTMVPartitionType.SELF_MANAGE) {
return Maps.newHashMap();
}
+ long start = System.currentTimeMillis();
Map> res = Maps.newHashMap();
- Map> relatedPartitionDescs = generateRelatedPartitionDescs();
+ Map> relatedPartitionDescs = MTMVPartitionUtil
+ .generateRelatedPartitionDescs(mvPartitionInfo, mvProperties);
Map mvPartitionItems = getAndCopyPartitionItems();
for (Entry entry : mvPartitionItems.entrySet()) {
res.put(entry.getKey(),
relatedPartitionDescs.getOrDefault(entry.getValue().toPartitionKeyDesc(), Sets.newHashSet()));
}
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("calculatePartitionMappings use [{}] mills, mvName is [{}]",
+ System.currentTimeMillis() - start, name);
+ }
return res;
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/job/extensions/mtmv/MTMVTask.java b/fe/fe-core/src/main/java/org/apache/doris/job/extensions/mtmv/MTMVTask.java
index efcdc4f564..7a4c527759 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/job/extensions/mtmv/MTMVTask.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/job/extensions/mtmv/MTMVTask.java
@@ -170,7 +170,7 @@ public class MTMVTask extends AbstractTask {
// Now, the MTMV first ensures consistency with the data in the cache.
// To be completely consistent with hive, you need to manually refresh the cache
// refreshHmsTable();
- if (mtmv.getMvPartitionInfo().getPartitionType() == MTMVPartitionType.FOLLOW_BASE_TABLE) {
+ if (mtmv.getMvPartitionInfo().getPartitionType() != MTMVPartitionType.SELF_MANAGE) {
MTMVPartitionUtil.alignMvPartition(mtmv);
}
Map> partitionMappings = mtmv.calculatePartitionMappings();
@@ -225,7 +225,7 @@ public class MTMVTask extends AbstractTask {
lastQueryId = DebugUtil.printId(queryId);
// if SELF_MANAGE mv, only have default partition, will not have partitionItem, so we give empty set
UpdateMvByPartitionCommand command = UpdateMvByPartitionCommand
- .from(mtmv, mtmv.getMvPartitionInfo().getPartitionType() == MTMVPartitionType.FOLLOW_BASE_TABLE
+ .from(mtmv, mtmv.getMvPartitionInfo().getPartitionType() != MTMVPartitionType.SELF_MANAGE
? refreshPartitionIds : Sets.newHashSet(), tableWithPartKey);
executor = new StmtExecutor(ctx, new LogicalPlanAdapter(command, ctx.getStatementContext()));
ctx.setExecutor(executor);
@@ -400,7 +400,7 @@ public class MTMVTask extends AbstractTask {
private Map getIncrementalTableMap() throws AnalysisException {
Map tableWithPartKey = Maps.newHashMap();
- if (mtmv.getMvPartitionInfo().getPartitionType() == MTMVPartitionType.FOLLOW_BASE_TABLE) {
+ if (mtmv.getMvPartitionInfo().getPartitionType() != MTMVPartitionType.SELF_MANAGE) {
tableWithPartKey
.put(mtmv.getMvPartitionInfo().getRelatedTable(), mtmv.getMvPartitionInfo().getRelatedCol());
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionExprDateTrunc.java b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionExprDateTrunc.java
new file mode 100644
index 0000000000..e1991ab292
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionExprDateTrunc.java
@@ -0,0 +1,228 @@
+// 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.mtmv;
+
+import org.apache.doris.analysis.Expr;
+import org.apache.doris.analysis.FunctionCallExpr;
+import org.apache.doris.analysis.PartitionExprUtil;
+import org.apache.doris.analysis.PartitionKeyDesc;
+import org.apache.doris.analysis.PartitionValue;
+import org.apache.doris.analysis.StringLiteral;
+import org.apache.doris.catalog.PartitionType;
+import org.apache.doris.catalog.Type;
+import org.apache.doris.common.AnalysisException;
+import org.apache.doris.common.util.PropertyAnalyzer;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.functions.executable.DateTimeArithmetic;
+import org.apache.doris.nereids.trees.expressions.functions.executable.DateTimeExtractAndTransform;
+import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal;
+import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal;
+import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
+import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
+public class MTMVPartitionExprDateTrunc implements MTMVPartitionExprService {
+ private static Set timeUnits = ImmutableSet.of("year", "month", "day");
+ private String timeUnit;
+
+ public MTMVPartitionExprDateTrunc(FunctionCallExpr functionCallExpr) throws AnalysisException {
+ List paramsExprs = functionCallExpr.getParams().exprs();
+ if (paramsExprs.size() != 2) {
+ throw new AnalysisException("date_trunc params exprs size should be 2.");
+ }
+ Expr param = paramsExprs.get(1);
+ if (!(param instanceof StringLiteral)) {
+ throw new AnalysisException("date_trunc param of time unit is not string literal.");
+ }
+ this.timeUnit = param.getStringValue().toLowerCase();
+ }
+
+ @Override
+ public void analyze(MTMVPartitionInfo mvPartitionInfo) throws AnalysisException {
+ if (!timeUnits.contains(this.timeUnit)) {
+ throw new AnalysisException(
+ String.format("timeUnit not support: %s, only support: %s", this.timeUnit, timeUnits));
+ }
+ MTMVRelatedTableIf relatedTable = mvPartitionInfo.getRelatedTable();
+ PartitionType partitionType = relatedTable.getPartitionType();
+ if (partitionType == PartitionType.RANGE) {
+ Type partitionColumnType = MTMVPartitionUtil
+ .getPartitionColumnType(mvPartitionInfo.getRelatedTable(), mvPartitionInfo.getRelatedCol());
+ if (!partitionColumnType.isDateType()) {
+ throw new AnalysisException(
+ "partitionColumnType should be date/datetime "
+ + "when PartitionType is range and expr is date_trunc");
+ }
+ }
+ }
+
+ @Override
+ public String getRollUpIdentity(PartitionKeyDesc partitionKeyDesc, Map mvProperties)
+ throws AnalysisException {
+ String res = null;
+ Optional dateFormat = getDateFormat(mvProperties);
+ List> inValues = partitionKeyDesc.getInValues();
+ for (int i = 0; i < inValues.size(); i++) {
+ // mtmv only support one partition column
+ PartitionValue partitionValue = inValues.get(i).get(0);
+ if (partitionValue.isNullPartition()) {
+ throw new AnalysisException("date trunc not support null partition value");
+ }
+ String identity = dateTrunc(partitionValue.getStringValue(), dateFormat, false).toString();
+ if (i == 0) {
+ res = identity;
+ } else {
+ if (!Objects.equals(res, identity)) {
+ throw new AnalysisException(
+ String.format("partition values not equal, res: %s, identity: %s", res,
+ identity));
+ }
+ }
+ }
+ return res;
+ }
+
+ private Optional getDateFormat(Map mvProperties) {
+ Optional dateFormat =
+ StringUtils.isEmpty(mvProperties.get(PropertyAnalyzer.PROPERTIES_PARTITION_DATE_FORMAT))
+ ? Optional.empty()
+ : Optional.of(mvProperties.get(PropertyAnalyzer.PROPERTIES_PARTITION_DATE_FORMAT));
+ return dateFormat;
+ }
+
+ @Override
+ public PartitionKeyDesc generateRollUpPartitionKeyDesc(PartitionKeyDesc partitionKeyDesc,
+ MTMVPartitionInfo mvPartitionInfo) throws AnalysisException {
+ Type partitionColumnType = MTMVPartitionUtil
+ .getPartitionColumnType(mvPartitionInfo.getRelatedTable(), mvPartitionInfo.getRelatedCol());
+ // mtmv only support one partition column
+ Preconditions.checkState(partitionKeyDesc.getLowerValues().size() == 1,
+ "only support one partition column");
+ DateTimeV2Literal beginTime = dateTrunc(
+ partitionKeyDesc.getLowerValues().get(0).getStringValue(),
+ Optional.empty(), false);
+
+ PartitionValue lowerValue = new PartitionValue(dateTimeToStr(beginTime, partitionColumnType));
+ PartitionValue upperValue = getUpperValue(partitionKeyDesc.getUpperValues().get(0), beginTime,
+ partitionColumnType);
+ return PartitionKeyDesc.createFixed(
+ Collections.singletonList(lowerValue),
+ Collections.singletonList(upperValue));
+ }
+
+ private PartitionValue getUpperValue(PartitionValue upperValue, DateTimeV2Literal beginTruncTime,
+ Type partitionColumnType) throws AnalysisException {
+ if (upperValue.isMax()) {
+ throw new AnalysisException("date trunc not support MAXVALUE partition");
+ }
+ // begin time and end time dateTrunc should has same result
+ DateTimeV2Literal endTruncTime = dateTrunc(upperValue.getStringValue(), Optional.empty(), true);
+ if (!Objects.equals(beginTruncTime, endTruncTime)) {
+ throw new AnalysisException(
+ String.format("partition values not equal, beginTruncTime: %s, endTruncTime: %s", beginTruncTime,
+ endTruncTime));
+ }
+ DateTimeV2Literal endTime = dateIncrement(beginTruncTime);
+ return new PartitionValue(dateTimeToStr(endTime, partitionColumnType));
+ }
+
+ private DateTimeV2Literal dateTrunc(String value,
+ Optional dateFormat, boolean isUpper) throws AnalysisException {
+ DateTimeV2Literal dateTimeLiteral = strToDate(value, dateFormat);
+ // for (2020-01-31,2020-02-01),if not -1, lower value and upper value will not same after rollup
+ if (isUpper) {
+ dateTimeLiteral = (DateTimeV2Literal) DateTimeArithmetic.secondsSub(dateTimeLiteral, new IntegerLiteral(1));
+ }
+ Expression expression = DateTimeExtractAndTransform.dateTrunc(dateTimeLiteral, new VarcharLiteral(timeUnit));
+ if (!(expression instanceof DateTimeV2Literal)) {
+ throw new AnalysisException("dateTrunc() should return DateLiteral, expression: " + expression);
+ }
+ return (DateTimeV2Literal) expression;
+ }
+
+ private DateTimeV2Literal strToDate(String value,
+ Optional dateFormat) throws AnalysisException {
+ try {
+ return new DateTimeV2Literal(value);
+ } catch (Exception e) {
+ if (!dateFormat.isPresent()) {
+ throw e;
+ }
+ Expression strToDate = DateTimeExtractAndTransform
+ .strToDate(new VarcharLiteral(value),
+ new VarcharLiteral(dateFormat.get()));
+ if (strToDate instanceof DateV2Literal) {
+ DateV2Literal dateV2Literal = (DateV2Literal) strToDate;
+ return new DateTimeV2Literal(dateV2Literal.getYear(), dateV2Literal.getMonth(), dateV2Literal.getDay(),
+ 0, 0, 0);
+ } else if (strToDate instanceof DateTimeV2Literal) {
+ return (DateTimeV2Literal) strToDate;
+ } else {
+ throw new AnalysisException(
+ String.format("strToDate failed, stringValue: %s, dateFormat: %s", value,
+ dateFormat));
+ }
+ }
+ }
+
+ private DateTimeV2Literal dateIncrement(DateTimeV2Literal value) throws AnalysisException {
+ Expression result;
+ switch (timeUnit) {
+ case "year":
+ result = value.plusYears(1L);
+ break;
+ case "month":
+ result = value.plusMonths(1L);
+ break;
+ case "day":
+ result = value.plusDays(1L);
+ break;
+ default:
+ throw new AnalysisException("MTMV partition roll up not support timeUnit: " + timeUnit);
+ }
+ if (!(result instanceof DateTimeV2Literal)) {
+ throw new AnalysisException("sub() should return DateTimeLiteral, result: " + result);
+ }
+ return (DateTimeV2Literal) result;
+ }
+
+ private String dateTimeToStr(DateTimeV2Literal literal,
+ Type partitionColumnType) throws AnalysisException {
+ if (partitionColumnType.isDate() || partitionColumnType.isDateV2()) {
+ return String.format(PartitionExprUtil.DATE_FORMATTER, literal.getYear(), literal.getMonth(),
+ literal.getDay());
+ } else if (partitionColumnType.isDatetime() || partitionColumnType.isDatetimeV2()) {
+ return String.format(PartitionExprUtil.DATETIME_FORMATTER,
+ literal.getYear(), literal.getMonth(), literal.getDay(),
+ literal.getHour(), literal.getMinute(), literal.getSecond());
+ } else {
+ throw new AnalysisException(
+ "MTMV not support partition with column type : " + partitionColumnType);
+ }
+ }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionExprFactory.java b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionExprFactory.java
new file mode 100644
index 0000000000..0fc9a067fa
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionExprFactory.java
@@ -0,0 +1,39 @@
+// 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.mtmv;
+
+import org.apache.doris.analysis.Expr;
+import org.apache.doris.analysis.FunctionCallExpr;
+import org.apache.doris.common.AnalysisException;
+
+/**
+ * MTMV Partition Expr Factory
+ */
+public class MTMVPartitionExprFactory {
+ public static MTMVPartitionExprService getExprService(Expr expr) throws AnalysisException {
+ if (!(expr instanceof FunctionCallExpr)) {
+ throw new AnalysisException("now mtmv partition only support FunctionCallExpr");
+ }
+ FunctionCallExpr functionCallExpr = (FunctionCallExpr) expr;
+ String fnName = functionCallExpr.getFnName().getFunction().toLowerCase();
+ if ("date_trunc".equals(fnName)) {
+ return new MTMVPartitionExprDateTrunc(functionCallExpr);
+ }
+ throw new AnalysisException("MTMV partition not support function name: " + fnName);
+ }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionExprService.java b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionExprService.java
new file mode 100644
index 0000000000..e6974343ef
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionExprService.java
@@ -0,0 +1,60 @@
+// 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.mtmv;
+
+import org.apache.doris.analysis.PartitionKeyDesc;
+import org.apache.doris.common.AnalysisException;
+
+import java.util.Map;
+
+/**
+ * Interface for materialized view partitioning function
+ */
+public interface MTMVPartitionExprService {
+
+ /**
+ * for list partition, get identity by expr
+ *
+ * @param partitionKeyDesc
+ * @param mvProperties
+ * @return
+ * @throws AnalysisException
+ */
+ String getRollUpIdentity(PartitionKeyDesc partitionKeyDesc, Map mvProperties)
+ throws AnalysisException;
+
+ /**
+ * for range partition, get roll up PartitionKeyDesc by expr
+ *
+ * @param partitionKeyDesc
+ * @param mvPartitionInfo
+ * @return
+ * @throws AnalysisException
+ */
+ PartitionKeyDesc generateRollUpPartitionKeyDesc(
+ PartitionKeyDesc partitionKeyDesc, MTMVPartitionInfo mvPartitionInfo)
+ throws AnalysisException;
+
+ /**
+ * Check if user input is legal
+ *
+ * @param mtmvPartitionInfo
+ * @throws AnalysisException
+ */
+ void analyze(MTMVPartitionInfo mtmvPartitionInfo) throws AnalysisException;
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionInfo.java b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionInfo.java
index 348f6e4de9..7ca1b7e3e6 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionInfo.java
@@ -17,10 +17,16 @@
package org.apache.doris.mtmv;
+import org.apache.doris.analysis.Expr;
+import org.apache.doris.catalog.Column;
import org.apache.doris.common.AnalysisException;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSortedSet;
import com.google.gson.annotations.SerializedName;
+import java.util.List;
+
/**
* MTMVPartitionInfo
*/
@@ -28,17 +34,24 @@ public class MTMVPartitionInfo {
public enum MTMVPartitionType {
FOLLOW_BASE_TABLE,
+ EXPR,
SELF_MANAGE
}
+ public static final ImmutableSet MTMV_PARTITION_FUNCTIONS = new ImmutableSortedSet.Builder(
+ String.CASE_INSENSITIVE_ORDER).add("date_trunc")
+ .build();
+
@SerializedName("pt")
- MTMVPartitionType partitionType;
+ private MTMVPartitionType partitionType;
@SerializedName("rt")
- BaseTableInfo relatedTable;
+ private BaseTableInfo relatedTable;
@SerializedName("rc")
- String relatedCol;
+ private String relatedCol;
@SerializedName("pc")
- String partitionCol;
+ private String partitionCol;
+ @SerializedName("expr")
+ private Expr expr;
public MTMVPartitionInfo() {
}
@@ -89,6 +102,14 @@ public class MTMVPartitionInfo {
this.partitionCol = partitionCol;
}
+ public Expr getExpr() {
+ return expr;
+ }
+
+ public void setExpr(Expr expr) {
+ this.expr = expr;
+ }
+
/**
* Get the position of relatedCol in the relatedTable partition column
*
@@ -99,7 +120,15 @@ public class MTMVPartitionInfo {
if (partitionType == MTMVPartitionType.SELF_MANAGE) {
throw new AnalysisException("partitionType is: " + partitionType);
}
- return MTMVPartitionUtil.getPos(getRelatedTable(), relatedCol);
+ List partitionColumns = getRelatedTable().getPartitionColumns();
+ for (int i = 0; i < partitionColumns.size(); i++) {
+ if (partitionColumns.get(i).getName().equalsIgnoreCase(relatedCol)) {
+ return i;
+ }
+ }
+ throw new AnalysisException(
+ String.format("getRelatedColPos error, relatedCol: %s, partitionColumns: %s", relatedCol,
+ partitionColumns));
}
// toString() is not easy to find where to call the method
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionUtil.java b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionUtil.java
index b80c5fc283..cd0312c419 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionUtil.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPartitionUtil.java
@@ -27,12 +27,13 @@ import org.apache.doris.catalog.Database;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.MTMV;
import org.apache.doris.catalog.Partition;
-import org.apache.doris.catalog.PartitionItem;
import org.apache.doris.catalog.TableIf;
+import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.DdlException;
import org.apache.doris.mtmv.MTMVPartitionInfo.MTMVPartitionType;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@@ -56,6 +57,18 @@ public class MTMVPartitionUtil {
private static final Pattern PARTITION_NAME_PATTERN = Pattern.compile("[^a-zA-Z0-9,]");
private static final String PARTITION_NAME_PREFIX = "p_";
+ private static final List partitionDescGenerators = ImmutableList
+ .of(
+ // It is necessary to maintain this order,
+ // because some impl deal `PartitionItem`, and some impl deal `PartitionDesc`
+ // for example: if `MTMVRelatedPartitionDescOnePartitionColGenerator` not generate `PartitionDesc`,
+ // `MTMVRelatedPartitionDescRollUpGenerator` will not have parameter
+ new MTMVRelatedPartitionDescInitGenerator(),
+ new MTMVRelatedPartitionDescSyncLimitGenerator(),
+ new MTMVRelatedPartitionDescOnePartitionColGenerator(),
+ new MTMVRelatedPartitionDescRollUpGenerator()
+ );
+
/**
* Determine whether the partition is sync with retated partition and other baseTables
*
@@ -71,7 +84,7 @@ public class MTMVPartitionUtil {
Set tables,
Set excludedTriggerTables) throws AnalysisException {
boolean isSyncWithPartition = true;
- if (mtmv.getMvPartitionInfo().getPartitionType() == MTMVPartitionType.FOLLOW_BASE_TABLE) {
+ if (mtmv.getMvPartitionInfo().getPartitionType() != MTMVPartitionType.SELF_MANAGE) {
MTMVRelatedTableIf relatedTable = mtmv.getMvPartitionInfo().getRelatedTable();
// if follow base table, not need compare with related table, only should compare with related partition
excludedTriggerTables.add(relatedTable.getName());
@@ -96,7 +109,8 @@ public class MTMVPartitionUtil {
public static void alignMvPartition(MTMV mtmv)
throws DdlException, AnalysisException {
Map mtmvPartitionDescs = mtmv.generateMvPartitionDescs();
- Set relatedPartitionDescs = mtmv.generateRelatedPartitionDescs().keySet();
+ Set relatedPartitionDescs = generateRelatedPartitionDescs(mtmv.getMvPartitionInfo(),
+ mtmv.getMvProperties()).keySet();
// drop partition of mtmv
for (Entry entry : mtmvPartitionDescs.entrySet()) {
if (!relatedPartitionDescs.contains(entry.getValue())) {
@@ -115,19 +129,18 @@ public class MTMVPartitionUtil {
/**
* getPartitionDescsByRelatedTable when create MTMV
*
- * @param relatedTable
* @param tableProperties
- * @param relatedCol
+ * @param mvPartitionInfo
* @return
* @throws AnalysisException
*/
- public static List getPartitionDescsByRelatedTable(MTMVRelatedTableIf relatedTable,
- Map tableProperties, String relatedCol, Map mvProperties)
+ public static List getPartitionDescsByRelatedTable(
+ Map tableProperties, MTMVPartitionInfo mvPartitionInfo, Map mvProperties)
throws AnalysisException {
- HashMap partitionProperties = Maps.newHashMap();
List res = Lists.newArrayList();
- Set relatedPartitionDescs = getRelatedPartitionDescs(relatedTable, relatedCol,
- MTMVUtil.generateMTMVPartitionSyncConfigByProperties(mvProperties));
+ HashMap partitionProperties = Maps.newHashMap();
+ Set relatedPartitionDescs = generateRelatedPartitionDescs(mvPartitionInfo, mvProperties)
+ .keySet();
for (PartitionKeyDesc partitionKeyDesc : relatedPartitionDescs) {
SinglePartitionDesc singlePartitionDesc = new SinglePartitionDesc(true,
generatePartitionName(partitionKeyDesc),
@@ -139,28 +152,18 @@ public class MTMVPartitionUtil {
return res;
}
- private static Set getRelatedPartitionDescs(MTMVRelatedTableIf relatedTable, String relatedCol,
- MTMVPartitionSyncConfig config)
- throws AnalysisException {
- int pos = getPos(relatedTable, relatedCol);
- Set res = Sets.newHashSet();
- for (Entry entry : relatedTable.getPartitionItemsByTimeFilter(pos, config).entrySet()) {
- PartitionKeyDesc partitionKeyDesc = entry.getValue().toPartitionKeyDesc(pos);
- res.add(partitionKeyDesc);
+ public static Map> generateRelatedPartitionDescs(MTMVPartitionInfo mvPartitionInfo,
+ Map mvProperties) throws AnalysisException {
+ long start = System.currentTimeMillis();
+ RelatedPartitionDescResult result = new RelatedPartitionDescResult();
+ for (MTMVRelatedPartitionDescGeneratorService service : partitionDescGenerators) {
+ service.apply(mvPartitionInfo, mvProperties, result);
}
- return res;
- }
-
- public static int getPos(MTMVRelatedTableIf relatedTable, String relatedCol) throws AnalysisException {
- List partitionColumns = relatedTable.getPartitionColumns();
- for (int i = 0; i < partitionColumns.size(); i++) {
- if (partitionColumns.get(i).getName().equalsIgnoreCase(relatedCol)) {
- return i;
- }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("generateRelatedPartitionDescs use [{}] mills, mvPartitionInfo is [{}]",
+ System.currentTimeMillis() - start, mvPartitionInfo);
}
- throw new AnalysisException(
- String.format("getRelatedColPos error, relatedCol: %s, partitionColumns: %s", relatedCol,
- partitionColumns));
+ return result.getDescs();
}
public static List getPartitionNamesByIds(MTMV mtmv, Collection ids) throws AnalysisException {
@@ -258,7 +261,7 @@ public class MTMVPartitionUtil {
if (!mtmvRelatedTableIf.needAutoRefresh()) {
continue;
}
- if (mtmv.getMvPartitionInfo().getPartitionType() == MTMVPartitionType.FOLLOW_BASE_TABLE && mtmv
+ if (mtmv.getMvPartitionInfo().getPartitionType() != MTMVPartitionType.SELF_MANAGE && mtmv
.getMvPartitionInfo().getRelatedTableInfo().equals(baseTableInfo)) {
if (CollectionUtils.isEmpty(relatedPartitionIds)) {
throw new AnalysisException("can not found related partition");
@@ -469,7 +472,7 @@ public class MTMVPartitionUtil {
Set baseTables, Set relatedPartitionIds)
throws AnalysisException {
MTMVRefreshPartitionSnapshot refreshPartitionSnapshot = new MTMVRefreshPartitionSnapshot();
- if (mtmv.getMvPartitionInfo().getPartitionType() == MTMVPartitionType.FOLLOW_BASE_TABLE) {
+ if (mtmv.getMvPartitionInfo().getPartitionType() != MTMVPartitionType.SELF_MANAGE) {
MTMVRelatedTableIf relatedTable = mtmv.getMvPartitionInfo().getRelatedTable();
for (Long relatedPartitionId : relatedPartitionIds) {
MTMVSnapshotIf partitionSnapshot = relatedTable
@@ -479,7 +482,7 @@ public class MTMVPartitionUtil {
}
}
for (BaseTableInfo baseTableInfo : baseTables) {
- if (mtmv.getMvPartitionInfo().getPartitionType() == MTMVPartitionType.FOLLOW_BASE_TABLE && mtmv
+ if (mtmv.getMvPartitionInfo().getPartitionType() != MTMVPartitionType.SELF_MANAGE && mtmv
.getMvPartitionInfo().getRelatedTableInfo().equals(baseTableInfo)) {
continue;
}
@@ -491,4 +494,14 @@ public class MTMVPartitionUtil {
}
return refreshPartitionSnapshot;
}
+
+ public static Type getPartitionColumnType(MTMVRelatedTableIf relatedTable, String col) throws AnalysisException {
+ List partitionColumns = relatedTable.getPartitionColumns();
+ for (Column column : partitionColumns) {
+ if (column.getName().equals(col)) {
+ return column.getType();
+ }
+ }
+ throw new AnalysisException("can not getPartitionColumnType by:" + col);
+ }
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRelatedPartitionDescGeneratorService.java b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRelatedPartitionDescGeneratorService.java
new file mode 100644
index 0000000000..09d85576b5
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRelatedPartitionDescGeneratorService.java
@@ -0,0 +1,38 @@
+// 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.mtmv;
+
+import org.apache.doris.common.AnalysisException;
+
+import java.util.Map;
+
+/**
+ * Interface for a series of processes to generate PartitionDesc
+ */
+public interface MTMVRelatedPartitionDescGeneratorService {
+ /**
+ * generate related table PartitionDesc
+ *
+ * @param mvPartitionInfo PartitionInfo of MTMV
+ * @param mvProperties properties of MTMV
+ * @param lastResult the processing result of the previous process
+ * @throws AnalysisException
+ */
+ void apply(MTMVPartitionInfo mvPartitionInfo, Map mvProperties,
+ RelatedPartitionDescResult lastResult) throws AnalysisException;
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRelatedPartitionDescInitGenerator.java b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRelatedPartitionDescInitGenerator.java
new file mode 100644
index 0000000000..13b5823937
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRelatedPartitionDescInitGenerator.java
@@ -0,0 +1,34 @@
+// 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.mtmv;
+
+import org.apache.doris.common.AnalysisException;
+
+import java.util.Map;
+
+/**
+ * get all related partition descs
+ */
+public class MTMVRelatedPartitionDescInitGenerator implements MTMVRelatedPartitionDescGeneratorService {
+
+ @Override
+ public void apply(MTMVPartitionInfo mvPartitionInfo, Map mvProperties,
+ RelatedPartitionDescResult lastResult) throws AnalysisException {
+ lastResult.setItems(mvPartitionInfo.getRelatedTable().getAndCopyPartitionItems());
+ }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRelatedPartitionDescOnePartitionColGenerator.java b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRelatedPartitionDescOnePartitionColGenerator.java
new file mode 100644
index 0000000000..ab14f302e7
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRelatedPartitionDescOnePartitionColGenerator.java
@@ -0,0 +1,67 @@
+// 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.mtmv;
+
+import org.apache.doris.analysis.PartitionKeyDesc;
+import org.apache.doris.catalog.PartitionItem;
+import org.apache.doris.common.AnalysisException;
+import org.apache.doris.mtmv.MTMVPartitionInfo.MTMVPartitionType;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * For example, the related table is partitioned by `date` and `region`, with the following 6 partitions
+ *
+ * If the MTMV is partitioned by `date`, then the MTMV will have three partitions: 20200101, 202000102, 20200103
+ *
+ * If the MTMV is partitioned by `region`, then the MTMV will have two partitions: beijing, shanghai
+ */
+public class MTMVRelatedPartitionDescOnePartitionColGenerator implements MTMVRelatedPartitionDescGeneratorService {
+
+ @Override
+ public void apply(MTMVPartitionInfo mvPartitionInfo, Map mvProperties,
+ RelatedPartitionDescResult lastResult) throws AnalysisException {
+ if (mvPartitionInfo.getPartitionType() == MTMVPartitionType.SELF_MANAGE) {
+ return;
+ }
+ Map> res = Maps.newHashMap();
+ Map relatedPartitionItems = lastResult.getItems();
+ int relatedColPos = mvPartitionInfo.getRelatedColPos();
+ for (Entry entry : relatedPartitionItems.entrySet()) {
+ PartitionKeyDesc partitionKeyDesc = entry.getValue().toPartitionKeyDesc(relatedColPos);
+ if (res.containsKey(partitionKeyDesc)) {
+ res.get(partitionKeyDesc).add(entry.getKey());
+ } else {
+ res.put(partitionKeyDesc, Sets.newHashSet(entry.getKey()));
+ }
+ }
+ lastResult.setDescs(res);
+ }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRelatedPartitionDescRollUpGenerator.java b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRelatedPartitionDescRollUpGenerator.java
new file mode 100644
index 0000000000..e9b4b1fe6a
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRelatedPartitionDescRollUpGenerator.java
@@ -0,0 +1,142 @@
+// 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.mtmv;
+
+import org.apache.doris.analysis.PartitionKeyDesc;
+import org.apache.doris.analysis.PartitionValue;
+import org.apache.doris.catalog.PartitionType;
+import org.apache.doris.common.AnalysisException;
+import org.apache.doris.mtmv.MTMVPartitionInfo.MTMVPartitionType;
+
+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;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * Roll up some partitions into one partition
+ */
+public class MTMVRelatedPartitionDescRollUpGenerator implements MTMVRelatedPartitionDescGeneratorService {
+
+ @Override
+ public void apply(MTMVPartitionInfo mvPartitionInfo, Map mvProperties,
+ RelatedPartitionDescResult lastResult) throws AnalysisException {
+ if (mvPartitionInfo.getPartitionType() != MTMVPartitionType.EXPR) {
+ return;
+ }
+ MTMVRelatedTableIf relatedTable = mvPartitionInfo.getRelatedTable();
+ PartitionType partitionType = relatedTable.getPartitionType();
+ if (partitionType == PartitionType.RANGE) {
+ lastResult.setDescs(rollUpRange(lastResult.getDescs(), mvPartitionInfo));
+ } else if (partitionType == PartitionType.LIST) {
+ lastResult.setDescs(rollUpList(lastResult.getDescs(), mvPartitionInfo, mvProperties));
+ } else {
+ throw new AnalysisException("only RANGE/LIST partition support roll up");
+ }
+ }
+
+ /**
+ * when related table has 3 partitions:(20200101),(20200102),(20200201)
+ *
+ * if expr is `date_trunc(month)`
+ * then,MTMV will have 2 partitions (20200101,20200102),(20200201)
+ *