MTMVPartitionCheckUtil.java
// 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.PartitionExprUtil;
import org.apache.doris.analysis.PartitionExprUtil.FunctionIntervalInfo;
import org.apache.doris.catalog.DynamicPartitionProperty;
import org.apache.doris.catalog.OlapTable;
import org.apache.doris.catalog.PartitionType;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.Pair;
import org.apache.doris.common.util.DynamicPartitionUtil;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import java.util.List;
import java.util.Objects;
public class MTMVPartitionCheckUtil {
/**
* Check if the partitioning method of the table meets the requirements for multi table partitioning updates
*
* @param relatedTable base table of materialized view
* @return Inspection results and reasons
*/
public static Pair<Boolean, String> checkIfAllowMultiTablePartitionRefresh(MTMVRelatedTableIf relatedTable) {
if (!(relatedTable instanceof OlapTable)) {
return Pair.of(false, "only support OlapTable");
}
OlapTable olapTable = (OlapTable) relatedTable;
if (olapTable.getPartitionType() != PartitionType.RANGE) {
return Pair.of(false, "only support range partition");
}
boolean isDynamicOrAuto = isDynamicPartition(olapTable) || isAutoPartition(olapTable);
if (!isDynamicOrAuto) {
return Pair.of(false, "only support dynamic/auto partition");
}
return Pair.of(true, "");
}
/**
* Compare whether the partitioning rules of two tables are consistent
*
* @param originalTable partition table of materialized view
* @param relatedTable Partition refresh table for materialized views
* @return Inspection results and reasons
* @throws AnalysisException The preconditions are not met
*/
public static Pair<Boolean, String> compareOriginalTableAndRelatedTable(OlapTable originalTable,
OlapTable relatedTable) throws AnalysisException {
if (isDynamicPartition(originalTable)) {
return compareDynamicPartition(originalTable, relatedTable);
} else if (isAutoPartition(originalTable)) {
return compareAutoPartition(originalTable, relatedTable);
} else {
throw new AnalysisException("only support dynamic/auto partition");
}
}
/**
* Determine which related table partitioning rules are consistent with the original table
*
* @param originalTable partition table of materialized view
* @param relatedTables Partition refresh table for materialized views
* @return Inspection results and reasons
* @throws AnalysisException The preconditions are not met
*/
public static List<Pair<Boolean, String>> compareOriginalTableAndRelatedTables(OlapTable originalTable,
List<OlapTable> relatedTables) throws AnalysisException {
List<Pair<Boolean, String>> res = Lists.newArrayListWithCapacity(relatedTables.size());
for (OlapTable relatedTable : relatedTables) {
res.add(compareOriginalTableAndRelatedTable(originalTable, relatedTable));
}
return res;
}
@VisibleForTesting
public static Pair<Boolean, String> compareDynamicPartition(OlapTable originalTable,
OlapTable relatedTable) throws AnalysisException {
if (!isDynamicPartition(relatedTable)) {
return Pair.of(false, "relatedTable is not dynamic partition.");
}
DynamicPartitionProperty originalDynamicProperty = originalTable.getTableProperty()
.getDynamicPartitionProperty();
DynamicPartitionProperty relatedDynamicProperty = relatedTable.getTableProperty().getDynamicPartitionProperty();
if (originalDynamicProperty == null || relatedDynamicProperty == null) {
throw new AnalysisException("dynamicProperty is null");
}
if (originalDynamicProperty.getTimeZone() != relatedDynamicProperty.getTimeZone()) {
return Pair.of(false, "timeZone not equal.");
}
if (originalDynamicProperty.getTimeUnit() != relatedDynamicProperty.getTimeUnit()) {
return Pair.of(false, "timeUnit not equal.");
}
if (!originalDynamicProperty.getStartOfMonth().equals(relatedDynamicProperty.getStartOfMonth())) {
return Pair.of(false, "startOfMonth not equal.");
}
if (!originalDynamicProperty.getStartOfWeek().equals(relatedDynamicProperty.getStartOfWeek())) {
return Pair.of(false, "startOfWeek not equal.");
}
return Pair.of(true, "");
}
@VisibleForTesting
public static Pair<Boolean, String> compareAutoPartition(OlapTable originalTable,
OlapTable relatedTable) throws AnalysisException {
if (!isDynamicPartition(relatedTable)) {
return Pair.of(false, "relatedTable is not dynamic partition.");
}
FunctionIntervalInfo originalFunctionIntervalInfo = PartitionExprUtil.getFunctionIntervalInfo(
originalTable.getPartitionInfo().getPartitionExprs(), originalTable.getPartitionType());
FunctionIntervalInfo relatedFunctionIntervalInfo = PartitionExprUtil.getFunctionIntervalInfo(
relatedTable.getPartitionInfo().getPartitionExprs(), relatedTable.getPartitionType());
boolean equals = Objects.equals(originalFunctionIntervalInfo, relatedFunctionIntervalInfo);
if (!equals) {
return Pair.of(false, "functionIntervalInfo not equal.");
}
return Pair.of(true, "");
}
private static boolean isDynamicPartition(OlapTable olapTable) {
return DynamicPartitionUtil.isDynamicPartitionTable(olapTable);
}
private static boolean isAutoPartition(OlapTable olapTable) {
return olapTable.getPartitionInfo().enableAutomaticPartition();
}
}