[feat](Nereids): add is null predicate for the first partition when updating mv by partition (#32463)
This commit is contained in:
@ -49,12 +49,15 @@ import org.apache.doris.nereids.util.ExpressionUtils;
|
||||
import org.apache.doris.nereids.util.RelationUtil;
|
||||
import org.apache.doris.qe.ConnectContext;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Range;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@ -111,11 +114,27 @@ public class UpdateMvByPartitionCommand extends InsertOverwriteTableCommand {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static Set<Expression> constructPredicates(Set<PartitionItem> partitions, String colName) {
|
||||
/**
|
||||
* construct predicates for partition items, the min key is the min key of range items.
|
||||
* For list partition or less than partition items, the min key is null.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public static Set<Expression> constructPredicates(Set<PartitionItem> partitions, String colName) {
|
||||
Set<Expression> predicates = new HashSet<>();
|
||||
UnboundSlot slot = new UnboundSlot(colName);
|
||||
return partitions.stream()
|
||||
.map(item -> convertPartitionItemToPredicate(item, slot))
|
||||
.collect(ImmutableSet.toImmutableSet());
|
||||
if (partitions.isEmpty()) {
|
||||
return Sets.newHashSet(BooleanLiteral.TRUE);
|
||||
}
|
||||
if (partitions.iterator().next() instanceof ListPartitionItem) {
|
||||
for (PartitionItem item : partitions) {
|
||||
predicates.add(convertListPartitionToIn(item, slot));
|
||||
}
|
||||
} else {
|
||||
for (PartitionItem item : partitions) {
|
||||
predicates.add(convertRangePartitionToCompare(item, slot));
|
||||
}
|
||||
}
|
||||
return predicates;
|
||||
}
|
||||
|
||||
private static Expression convertPartitionKeyToLiteral(PartitionKey key) {
|
||||
@ -123,42 +142,48 @@ public class UpdateMvByPartitionCommand extends InsertOverwriteTableCommand {
|
||||
Type.fromPrimitiveType(key.getTypes().get(0)));
|
||||
}
|
||||
|
||||
private static Expression convertPartitionItemToPredicate(PartitionItem item, Slot col) {
|
||||
if (item instanceof ListPartitionItem) {
|
||||
List<Expression> inValues = ((ListPartitionItem) item).getItems().stream()
|
||||
.map(UpdateMvByPartitionCommand::convertPartitionKeyToLiteral)
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
List<Expression> predicates = new ArrayList<>();
|
||||
if (inValues.stream().anyMatch(NullLiteral.class::isInstance)) {
|
||||
inValues = inValues.stream()
|
||||
.filter(e -> !(e instanceof NullLiteral))
|
||||
.collect(Collectors.toList());
|
||||
Expression isNullPredicate = new IsNull(col);
|
||||
predicates.add(isNullPredicate);
|
||||
}
|
||||
if (!inValues.isEmpty()) {
|
||||
predicates.add(new InPredicate(col, inValues));
|
||||
}
|
||||
if (predicates.isEmpty()) {
|
||||
return BooleanLiteral.of(true);
|
||||
}
|
||||
return ExpressionUtils.or(predicates);
|
||||
} else {
|
||||
Range<PartitionKey> range = item.getItems();
|
||||
List<Expression> exprs = new ArrayList<>();
|
||||
if (range.hasLowerBound() && !range.lowerEndpoint().isMinValue()) {
|
||||
PartitionKey key = range.lowerEndpoint();
|
||||
exprs.add(new GreaterThanEqual(col, convertPartitionKeyToLiteral(key)));
|
||||
}
|
||||
if (range.hasUpperBound() && !range.upperEndpoint().isMaxValue()) {
|
||||
PartitionKey key = range.upperEndpoint();
|
||||
exprs.add(new LessThan(col, convertPartitionKeyToLiteral(key)));
|
||||
}
|
||||
if (exprs.isEmpty()) {
|
||||
return BooleanLiteral.of(true);
|
||||
}
|
||||
return ExpressionUtils.and(exprs);
|
||||
private static Expression convertListPartitionToIn(PartitionItem item, Slot col) {
|
||||
List<Expression> inValues = ((ListPartitionItem) item).getItems().stream()
|
||||
.map(UpdateMvByPartitionCommand::convertPartitionKeyToLiteral)
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
List<Expression> predicates = new ArrayList<>();
|
||||
if (inValues.stream().anyMatch(NullLiteral.class::isInstance)) {
|
||||
inValues = inValues.stream()
|
||||
.filter(e -> !(e instanceof NullLiteral))
|
||||
.collect(Collectors.toList());
|
||||
Expression isNullPredicate = new IsNull(col);
|
||||
predicates.add(isNullPredicate);
|
||||
}
|
||||
if (!inValues.isEmpty()) {
|
||||
predicates.add(new InPredicate(col, inValues));
|
||||
}
|
||||
if (predicates.isEmpty()) {
|
||||
return BooleanLiteral.of(true);
|
||||
}
|
||||
return ExpressionUtils.or(predicates);
|
||||
}
|
||||
|
||||
private static Expression convertRangePartitionToCompare(PartitionItem item, Slot col) {
|
||||
Range<PartitionKey> range = item.getItems();
|
||||
List<Expression> expressions = new ArrayList<>();
|
||||
if (range.hasLowerBound() && !range.lowerEndpoint().isMinValue()) {
|
||||
PartitionKey key = range.lowerEndpoint();
|
||||
expressions.add(new GreaterThanEqual(col, convertPartitionKeyToLiteral(key)));
|
||||
}
|
||||
if (range.hasUpperBound() && !range.upperEndpoint().isMaxValue()) {
|
||||
PartitionKey key = range.upperEndpoint();
|
||||
expressions.add(new LessThan(col, convertPartitionKeyToLiteral(key)));
|
||||
}
|
||||
if (expressions.isEmpty()) {
|
||||
return BooleanLiteral.of(true);
|
||||
}
|
||||
Expression predicate = ExpressionUtils.and(expressions);
|
||||
// The partition without can be the first partition of LESS THAN PARTITIONS
|
||||
// The null value can insert into this partition, so we need to add or is null condition
|
||||
if (!range.hasLowerBound()) {
|
||||
predicate = ExpressionUtils.or(predicate, new IsNull(col));
|
||||
}
|
||||
return predicate;
|
||||
}
|
||||
|
||||
static class PredicateAdder extends DefaultPlanRewriter<Map<TableIf, Set<Expression>>> {
|
||||
|
||||
Reference in New Issue
Block a user