From 511eedb4ffd5167517ec80992b956d53d15cddf9 Mon Sep 17 00:00:00 2001 From: starocean999 <40539150+starocean999@users.noreply.github.com> Date: Thu, 23 Nov 2023 18:41:59 +0800 Subject: [PATCH] [fix](nereids)select base index if mv's data type is different from base table (#27387) normally, mv column's data type should be same as base table. This pr plays as a fail-safe, if mv column's data type is different from base table accidentally, fall back to select base table to make the query works. --- ...lectMaterializedIndexWithoutAggregate.java | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/SelectMaterializedIndexWithoutAggregate.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/SelectMaterializedIndexWithoutAggregate.java index 7787df22c7..d5e9600579 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/SelectMaterializedIndexWithoutAggregate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/SelectMaterializedIndexWithoutAggregate.java @@ -21,6 +21,7 @@ import org.apache.doris.catalog.Column; import org.apache.doris.catalog.KeysType; import org.apache.doris.catalog.MaterializedIndex; import org.apache.doris.catalog.OlapTable; +import org.apache.doris.catalog.PrimitiveType; import org.apache.doris.nereids.rules.Rule; import org.apache.doris.nereids.rules.RuleType; import org.apache.doris.nereids.rules.rewrite.RewriteRuleFactory; @@ -32,12 +33,14 @@ import org.apache.doris.nereids.trees.plans.PreAggStatus; import org.apache.doris.nereids.trees.plans.logical.LogicalFilter; import org.apache.doris.nereids.trees.plans.logical.LogicalOlapScan; import org.apache.doris.nereids.trees.plans.logical.LogicalProject; +import org.apache.doris.nereids.util.ExpressionUtils; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -184,6 +187,11 @@ public class SelectMaterializedIndexWithoutAggregate extends AbstractSelectMater default: throw new RuntimeException("Not supported keys type: " + keysType); } + + Set requiredSlots = new HashSet<>(); + requiredSlots.addAll(requiredScanOutputSupplier.get()); + requiredSlots.addAll(ExpressionUtils.getInputSlotSet(requiredExpr)); + requiredSlots.addAll(ExpressionUtils.getInputSlotSet(predicatesSupplier.get())); if (scan.getTable().isDupKeysOrMergeOnWrite()) { // Set pre-aggregation to `on` to keep consistency with legacy logic. List candidates = scan @@ -192,6 +200,9 @@ public class SelectMaterializedIndexWithoutAggregate extends AbstractSelectMater scan, requiredScanOutputSupplier.get(), requiredExpr, predicatesSupplier.get())) .collect(Collectors.toList()); long bestIndex = selectBestIndex(candidates, scan, predicatesSupplier.get()); + // this is fail-safe for select mv + // select baseIndex if bestIndex's slots' data types are different from baseIndex + bestIndex = isSameDataType(scan, bestIndex, requiredSlots) ? bestIndex : baseIndexId; return scan.withMaterializedIndexSelected(PreAggStatus.on(), bestIndex); } else { final PreAggStatus preAggStatus; @@ -219,12 +230,30 @@ public class SelectMaterializedIndexWithoutAggregate extends AbstractSelectMater // `candidates` only have base index. return scan.withMaterializedIndexSelected(preAggStatus, baseIndexId); } else { - return scan.withMaterializedIndexSelected(preAggStatus, - selectBestIndex(candidates, scan, predicatesSupplier.get())); + long bestIndex = selectBestIndex(candidates, scan, predicatesSupplier.get()); + // this is fail-safe for select mv + // select baseIndex if bestIndex's slots' data types are different from baseIndex + bestIndex = isSameDataType(scan, bestIndex, requiredSlots) ? bestIndex : baseIndexId; + return scan.withMaterializedIndexSelected(preAggStatus, bestIndex); } } } + private boolean isSameDataType(LogicalOlapScan scan, long selectIndex, Set slots) { + if (selectIndex != scan.getTable().getBaseIndexId()) { + Map columnTypes = + scan.getTable().getSchemaByIndexId(selectIndex).stream().collect(Collectors + .toMap(Column::getNameWithoutMvPrefix, column -> column.getDataType())); + return slots.stream().allMatch(slot -> { + PrimitiveType dataType = + columnTypes.getOrDefault(slot.getName(), PrimitiveType.NULL_TYPE); + return dataType == PrimitiveType.NULL_TYPE + || dataType == slot.getDataType().toCatalogDataType().getPrimitiveType(); + }); + } + return true; + } + private boolean indexHasAggregate(MaterializedIndex index, LogicalOlapScan scan) { return scan.getTable().getSchemaByIndexId(index.getId()) .stream()