[fix] (inverted index) fix the error result in the query when using count on index (#41375) (#41690)
## Proposed changes pick from master #41375 <!--Describe your changes.-->
This commit is contained in:
@ -40,6 +40,7 @@ import org.apache.doris.nereids.trees.expressions.Cast;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.IsNull;
|
||||
import org.apache.doris.nereids.trees.expressions.NamedExpression;
|
||||
import org.apache.doris.nereids.trees.expressions.Or;
|
||||
import org.apache.doris.nereids.trees.expressions.OrderExpression;
|
||||
import org.apache.doris.nereids.trees.expressions.Slot;
|
||||
import org.apache.doris.nereids.trees.expressions.SlotReference;
|
||||
@ -111,42 +112,66 @@ public class AggregateStrategies implements ImplementationRuleFactory {
|
||||
logicalAggregate(
|
||||
logicalFilter(
|
||||
logicalOlapScan().when(this::isDupOrMowKeyTable).when(this::isInvertedIndexEnabledOnTable)
|
||||
).when(filter -> !filter.getConjuncts().isEmpty()))
|
||||
.when(agg -> enablePushDownCountOnIndex())
|
||||
.when(agg -> agg.getGroupByExpressions().isEmpty())
|
||||
.when(agg -> {
|
||||
Set<AggregateFunction> funcs = agg.getAggregateFunctions();
|
||||
return !funcs.isEmpty() && funcs.stream()
|
||||
.allMatch(f -> f instanceof Count && !f.isDistinct() && (((Count) f).isCountStar()
|
||||
|| f.child(0) instanceof Slot));
|
||||
})
|
||||
.thenApply(ctx -> {
|
||||
LogicalAggregate<LogicalFilter<LogicalOlapScan>> agg = ctx.root;
|
||||
LogicalFilter<LogicalOlapScan> filter = agg.child();
|
||||
LogicalOlapScan olapScan = filter.child();
|
||||
return pushdownCountOnIndex(agg, null, filter, olapScan, ctx.cascadesContext);
|
||||
})
|
||||
)
|
||||
)
|
||||
.when(agg -> enablePushDownCountOnIndex())
|
||||
.when(agg -> agg.getGroupByExpressions().isEmpty())
|
||||
.when(agg -> {
|
||||
Set<AggregateFunction> funcs = agg.getAggregateFunctions();
|
||||
if (funcs.isEmpty() || !funcs.stream().allMatch(f -> f instanceof Count && !f.isDistinct()
|
||||
&& (((Count) f).isCountStar() || f.child(0) instanceof Slot))) {
|
||||
return false;
|
||||
}
|
||||
Set<Expression> conjuncts = agg.child().getConjuncts();
|
||||
if (conjuncts.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Set<Slot> aggSlots = funcs.stream()
|
||||
.flatMap(f -> f.getInputSlots().stream())
|
||||
.collect(Collectors.toSet());
|
||||
return conjuncts.stream().allMatch(expr -> checkSlotInOrExpression(expr, aggSlots));
|
||||
})
|
||||
.thenApply(ctx -> {
|
||||
LogicalAggregate<LogicalFilter<LogicalOlapScan>> agg = ctx.root;
|
||||
LogicalFilter<LogicalOlapScan> filter = agg.child();
|
||||
LogicalOlapScan olapScan = filter.child();
|
||||
return pushdownCountOnIndex(agg, null, filter, olapScan, ctx.cascadesContext);
|
||||
})
|
||||
),
|
||||
RuleType.COUNT_ON_INDEX.build(
|
||||
logicalAggregate(
|
||||
logicalProject(
|
||||
logicalFilter(
|
||||
logicalOlapScan().when(this::isDupOrMowKeyTable).when(this::isInvertedIndexEnabledOnTable)
|
||||
).when(filter -> !filter.getConjuncts().isEmpty())))
|
||||
.when(agg -> enablePushDownCountOnIndex())
|
||||
.when(agg -> agg.getGroupByExpressions().isEmpty())
|
||||
.when(agg -> {
|
||||
Set<AggregateFunction> funcs = agg.getAggregateFunctions();
|
||||
return !funcs.isEmpty() && funcs.stream().allMatch(f -> f instanceof Count && !f.isDistinct()
|
||||
&& (((Count) f).isCountStar() || f.child(0) instanceof Slot));
|
||||
})
|
||||
.thenApply(ctx -> {
|
||||
LogicalAggregate<LogicalProject<LogicalFilter<LogicalOlapScan>>> agg = ctx.root;
|
||||
LogicalProject<LogicalFilter<LogicalOlapScan>> project = agg.child();
|
||||
LogicalFilter<LogicalOlapScan> filter = project.child();
|
||||
LogicalOlapScan olapScan = filter.child();
|
||||
return pushdownCountOnIndex(agg, project, filter, olapScan, ctx.cascadesContext);
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
.when(agg -> enablePushDownCountOnIndex())
|
||||
.when(agg -> agg.getGroupByExpressions().isEmpty())
|
||||
.when(agg -> {
|
||||
Set<AggregateFunction> funcs = agg.getAggregateFunctions();
|
||||
if (funcs.isEmpty() || !funcs.stream().allMatch(f -> f instanceof Count && !f.isDistinct()
|
||||
&& (((Count) f).isCountStar() || f.child(0) instanceof Slot))) {
|
||||
return false;
|
||||
}
|
||||
Set<Expression> conjuncts = agg.child().child().getConjuncts();
|
||||
if (conjuncts.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Set<Slot> aggSlots = funcs.stream()
|
||||
.flatMap(f -> f.getInputSlots().stream())
|
||||
.collect(Collectors.toSet());
|
||||
return conjuncts.stream().allMatch(expr -> checkSlotInOrExpression(expr, aggSlots));
|
||||
})
|
||||
.thenApply(ctx -> {
|
||||
LogicalAggregate<LogicalProject<LogicalFilter<LogicalOlapScan>>> agg = ctx.root;
|
||||
LogicalProject<LogicalFilter<LogicalOlapScan>> project = agg.child();
|
||||
LogicalFilter<LogicalOlapScan> filter = project.child();
|
||||
LogicalOlapScan olapScan = filter.child();
|
||||
return pushdownCountOnIndex(agg, project, filter, olapScan, ctx.cascadesContext);
|
||||
})
|
||||
),
|
||||
RuleType.STORAGE_LAYER_AGGREGATE_MINMAX_ON_UNIQUE_WITHOUT_PROJECT.build(
|
||||
logicalAggregate(
|
||||
@ -411,6 +436,22 @@ public class AggregateStrategies implements ImplementationRuleFactory {
|
||||
return connectContext != null && connectContext.getSessionVariable().isEnablePushDownCountOnIndex();
|
||||
}
|
||||
|
||||
private boolean checkSlotInOrExpression(Expression expr, Set<Slot> aggSlots) {
|
||||
if (expr instanceof Or) {
|
||||
Set<Slot> slots = expr.getInputSlots();
|
||||
if (!slots.stream().allMatch(aggSlots::contains)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
for (Expression child : expr.children()) {
|
||||
if (!checkSlotInOrExpression(child, aggSlots)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isDupOrMowKeyTable(LogicalOlapScan logicalScan) {
|
||||
if (logicalScan != null) {
|
||||
KeysType keysType = logicalScan.getTable().getKeysType();
|
||||
|
||||
Reference in New Issue
Block a user