github-actions[bot] commented on code in PR #62607:
URL: https://github.com/apache/doris/pull/62607#discussion_r3333783233
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/AbstractMaterializedViewWindowRule.java:
##########
@@ -96,28 +113,291 @@ protected Plan rewriteQueryByView(MatchMode matchMode,
StructInfo queryStructInf
viewToQuerySlotMapping,
tempRewrittenPlan.treeString()));
return null;
}
+ Map<Expression, Expression> mvExprToMvScanExprQueryBased =
+
materializationContext.getShuttledExprToScanExprMapping().keyPermute(viewToQuerySlotMapping)
+ .flattenMap().get(0);
+ List<? extends Expression> expressionsToRewrite =
getWindowRewriteExpressions(queryStructInfo);
+ if (expressionsToRewrite.isEmpty()) {
+ materializationContext.recordFailReason(queryStructInfo,
+ "Rewrite expressions by view in window scan fail, no
expressions to rewrite",
+ () -> String.format("topPlan = %s",
queryStructInfo.getTopPlan().treeString()));
+ return null;
+ }
+ Plan expressionSourcePlan = queryStructInfo.getOriginalPlan();
// Rewrite top projects, represent the query projects by view
List<Expression> expressionsRewritten = rewriteExpression(
- queryStructInfo.getExpressions(),
- queryStructInfo.getTopPlan(),
+ expressionsToRewrite,
+ expressionSourcePlan,
materializationContext.getShuttledExprToScanExprMapping(),
viewToQuerySlotMapping,
ImmutableMap.of(), cascadesContext
);
- // Can not rewrite, bail out
+ // If generic rewrite fails, try roll up from query expressions.
if (expressionsRewritten.isEmpty()) {
- materializationContext.recordFailReason(queryStructInfo,
- "Rewrite expressions by view in window scan fail",
- () -> String.format("expressionToRewritten is %s,\n
mvExprToMvScanExprMapping is %s,\n"
- + "targetToSourceMapping = %s",
queryStructInfo.getExpressions(),
-
materializationContext.getShuttledExprToScanExprMapping(),
- viewToQuerySlotMapping));
- return null;
+ expressionsRewritten =
rollupWindowAggregateFunctions(expressionsToRewrite,
+ expressionSourcePlan, mvExprToMvScanExprQueryBased, true,
false);
+ if (expressionsRewritten.isEmpty()) {
+ materializationContext.recordFailReason(queryStructInfo,
+ "Rewrite expressions by view in window scan fail",
+ () -> String.format("expressionToRewritten is %s,\n
mvExprToMvScanExprMapping is %s,\n"
+ + "targetToSourceMapping = %s",
expressionsToRewrite,
+
materializationContext.getShuttledExprToScanExprMapping(),
+ viewToQuerySlotMapping));
+ return null;
+ }
+ }
+ return buildRewrittenPlanFromExpressions(expressionsRewritten,
tempRewrittenPlan);
+ }
+
+ private static Plan buildRewrittenPlanFromExpressions(List<Expression>
expressionsRewritten, Plan mvScan) {
+ boolean hasAggregateFunction = expressionsRewritten.stream()
+ .anyMatch(expression ->
expression.containsType(AggregateFunction.class));
+ if (!hasAggregateFunction) {
+ return new
LogicalProject<>(toNamedExpressions(expressionsRewritten), mvScan);
+ }
+ List<Expression> groupByExpressions = new ArrayList<>();
+ List<NamedExpression> aggregateOutputExpressions = new ArrayList<>();
+ for (Expression expression : expressionsRewritten) {
+ if (expression.containsType(AggregateFunction.class)) {
+ aggregateOutputExpressions.add(toNamedExpression(expression));
+ } else if (!(expression instanceof Literal)) {
+ if (!groupByExpressions.contains(expression)) {
+ groupByExpressions.add(expression);
+
aggregateOutputExpressions.add(toNamedExpression(expression));
+ }
+ }
+ }
+ LogicalAggregate<Plan> aggregate = new
LogicalAggregate<>(groupByExpressions, aggregateOutputExpressions,
+ mvScan);
+ List<Slot> aggregateOutput = aggregate.getOutput();
+ int groupByOutputSize = groupByExpressions.size();
+ int groupByOutputIndex = 0;
+ int aggregateFunctionOutputIndex = 0;
+ List<NamedExpression> projectExpressions = new
ArrayList<>(expressionsRewritten.size());
+ for (Expression expression : expressionsRewritten) {
+ if (expression instanceof Literal) {
+ projectExpressions.add(toNamedExpression(expression));
+ } else if (expression.containsType(AggregateFunction.class)) {
+ projectExpressions.add(new
Alias(aggregateOutput.get(groupByOutputSize
+ + aggregateFunctionOutputIndex++)));
Review Comment:
`LogicalAggregate.computeOutput()` preserves `aggregateOutputExpressions`
order, but the projection below assumes the output is laid out as all group-by
slots first and aggregate-function slots after them. When the rewritten select
list starts with the rollup aggregate, e.g. `SELECT bitmap_union_count(...)
OVER (...), dt ...`, `aggregateOutputExpressions` is `[agg, dt]` while
`groupByOutputSize` is 1, so this reads slot 1 for the aggregate and slot 0 for
`dt`. That swaps outputs or causes a type mismatch for valid projection orders.
Please build the aggregate outputs in the same grouped order the projection
assumes, or keep an explicit expression-to-output mapping.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]