This is an automated email from the ASF dual-hosted git repository. kxiao pushed a commit to branch branch-2.0 in repository https://gitbox.apache.org/repos/asf/doris.git
commit 937952b5547d38e47bfc8c563165b73008bb68d4 Author: morrySnow <101034200+morrys...@users.noreply.github.com> AuthorDate: Mon Sep 4 10:41:48 2023 +0800 [opt](Nereids) use avl tree to construct continuous union operand (#23763) --- .../doris/nereids/parser/LogicalPlanBuilder.java | 84 ++++++++++++++++------ 1 file changed, 63 insertions(+), 21 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java index 25a8274d65..06a49abb79 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java @@ -80,6 +80,7 @@ import org.apache.doris.nereids.DorisParser.PrimitiveDataTypeContext; import org.apache.doris.nereids.DorisParser.QualifiedNameContext; import org.apache.doris.nereids.DorisParser.QueryContext; import org.apache.doris.nereids.DorisParser.QueryOrganizationContext; +import org.apache.doris.nereids.DorisParser.QueryTermContext; import org.apache.doris.nereids.DorisParser.RegularQuerySpecificationContext; import org.apache.doris.nereids.DorisParser.RelationContext; import org.apache.doris.nereids.DorisParser.SelectClauseContext; @@ -487,34 +488,75 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { @Override public LogicalPlan visitSetOperation(SetOperationContext ctx) { return ParserUtils.withOrigin(ctx, () -> { - LogicalPlan leftQuery = plan(ctx.left); - LogicalPlan rightQuery = plan(ctx.right); - Qualifier qualifier; - if (ctx.setQuantifier() == null || ctx.setQuantifier().DISTINCT() != null) { - qualifier = Qualifier.DISTINCT; - } else { - qualifier = Qualifier.ALL; - } - List<Plan> newChildren = new ImmutableList.Builder<Plan>() - .add(leftQuery) - .add(rightQuery) - .build(); - - LogicalPlan plan; if (ctx.UNION() != null) { - plan = new LogicalUnion(qualifier, newChildren); - } else if (ctx.EXCEPT() != null) { - plan = new LogicalExcept(qualifier, newChildren); - } else if (ctx.INTERSECT() != null) { - plan = new LogicalIntersect(qualifier, newChildren); + Qualifier qualifier = getQualifier(ctx); + List<QueryTermContext> contexts = Lists.newArrayList(ctx.right); + QueryTermContext current = ctx.left; + while (true) { + if (current instanceof SetOperationContext + && getQualifier((SetOperationContext) current) == qualifier + && ((SetOperationContext) current).UNION() != null) { + contexts.add(((SetOperationContext) current).right); + current = ((SetOperationContext) current).left; + } else { + contexts.add(current); + break; + } + } + Collections.reverse(contexts); + List<LogicalPlan> logicalPlans = contexts.stream().map(this::plan).collect(Collectors.toList()); + return reduceToLogicalPlanTree(0, logicalPlans.size() - 1, logicalPlans, qualifier); } else { - throw new ParseException("not support", ctx); + LogicalPlan leftQuery = plan(ctx.left); + LogicalPlan rightQuery = plan(ctx.right); + Qualifier qualifier = getQualifier(ctx); + + List<Plan> newChildren = ImmutableList.of(leftQuery, rightQuery); + LogicalPlan plan; + if (ctx.UNION() != null) { + plan = new LogicalUnion(qualifier, newChildren); + } else if (ctx.EXCEPT() != null) { + plan = new LogicalExcept(qualifier, newChildren); + } else if (ctx.INTERSECT() != null) { + plan = new LogicalIntersect(qualifier, newChildren); + } else { + throw new ParseException("not support", ctx); + } + return plan; } - return plan; }); } + private Qualifier getQualifier(SetOperationContext ctx) { + if (ctx.setQuantifier() == null || ctx.setQuantifier().DISTINCT() != null) { + return Qualifier.DISTINCT; + } else { + return Qualifier.ALL; + } + } + + private LogicalPlan logicalPlanCombiner(LogicalPlan left, LogicalPlan right, Qualifier qualifier) { + return new LogicalUnion(qualifier, ImmutableList.of(left, right)); + } + + private LogicalPlan reduceToLogicalPlanTree(int low, int high, + List<LogicalPlan> logicalPlans, Qualifier qualifier) { + switch (high - low) { + case 0: + return logicalPlans.get(low); + case 1: + return logicalPlanCombiner(logicalPlans.get(low), logicalPlans.get(high), qualifier); + default: + int mid = low + (high - low) / 2; + return logicalPlanCombiner( + reduceToLogicalPlanTree(low, mid, logicalPlans, qualifier), + reduceToLogicalPlanTree(mid + 1, high, logicalPlans, qualifier), + qualifier + ); + } + } + @Override public LogicalPlan visitSubquery(SubqueryContext ctx) { return ParserUtils.withOrigin(ctx, () -> plan(ctx.query())); --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org