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 60a44e7426..96f0d74f2f 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 @@ -1826,10 +1826,7 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor { Optional aggClause, Optional havingClause) { return ParserUtils.withOrigin(ctx, () -> { - // TODO: add lateral views - // from -> where -> group by -> having -> select - LogicalPlan filter = withFilter(inputRelation, whereClause); SelectColumnClauseContext selectColumnCtx = selectClause.selectColumnClause(); LogicalPlan aggregate = withAggregate(filter, selectColumnCtx, aggClause); @@ -1838,7 +1835,6 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor { throw new ParseException("cannot combine SELECT DISTINCT with aggregate functions or GROUP BY", selectClause); } - // TODO: replace and process having at this position if (!(aggregate instanceof Aggregate) && havingClause.isPresent()) { // create a project node for pattern match of ProjectToGlobalAggregate rule // then ProjectToGlobalAggregate rule can insert agg node as LogicalHaving node's child @@ -1849,10 +1845,10 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor { throw new ParseException("only column name is supported in except clause", selectColumnCtx); } project = new LogicalProject<>(ImmutableList.of(new UnboundStar(ImmutableList.of())), - expressions, aggregate, isDistinct); + expressions, isDistinct, aggregate); } else { List projects = getNamedExpressions(selectColumnCtx.namedExpressionSeq()); - project = new LogicalProject<>(projects, ImmutableList.of(), aggregate, isDistinct); + project = new LogicalProject<>(projects, ImmutableList.of(), isDistinct, aggregate); } return new LogicalHaving<>(ExpressionUtils.extractConjunctionToSet( getExpression((havingClause.get().booleanExpression()))), project); @@ -2011,7 +2007,6 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor { private LogicalPlan withProjection(LogicalPlan input, SelectColumnClauseContext selectCtx, Optional aggCtx, boolean isDistinct) { return ParserUtils.withOrigin(selectCtx, () -> { - // TODO: skip if havingClause exists if (aggCtx.isPresent()) { return input; } else { @@ -2021,10 +2016,10 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor { throw new ParseException("only column name is supported in except clause", selectCtx); } return new LogicalProject<>(ImmutableList.of(new UnboundStar(ImmutableList.of())), - expressions, input, isDistinct); + expressions, isDistinct, input); } else { List projects = getNamedExpressions(selectCtx.namedExpressionSeq()); - return new LogicalProject<>(projects, Collections.emptyList(), input, isDistinct); + return new LogicalProject<>(projects, Collections.emptyList(), isDistinct, input); } } }); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java index be5c9f460a..9623b25419 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java @@ -133,21 +133,23 @@ public class BindExpression implements AnalysisRuleFactory { logicalProject().thenApply(ctx -> { LogicalProject project = ctx.root; List boundProjections = - bindSlot(project.getProjects(), project.children(), ctx.cascadesContext); - List boundExceptions = bindSlot(project.getExcepts(), project.children(), - ctx.cascadesContext); - boundProjections = flatBoundStar(boundProjections, boundExceptions); + bindSlot(project.getProjects(), project.child(), ctx.cascadesContext); + if (boundProjections.stream().anyMatch(BoundStar.class::isInstance)) { + List boundExceptions = project.getExcepts().isEmpty() ? ImmutableList.of() + : bindSlot(project.getExcepts(), project.child(), ctx.cascadesContext); + boundProjections = flatBoundStar(boundProjections, boundExceptions); + } boundProjections = boundProjections.stream() .map(expr -> bindFunction(expr, ctx.cascadesContext)) .collect(ImmutableList.toImmutableList()); - return new LogicalProject<>(boundProjections, project.child(), project.isDistinct()); + return new LogicalProject<>(boundProjections, project.isDistinct(), project.child()); }) ), RuleType.BINDING_FILTER_SLOT.build( logicalFilter().thenApply(ctx -> { LogicalFilter filter = ctx.root; Set boundConjuncts = filter.getConjuncts().stream() - .map(expr -> bindSlot(expr, filter.children(), ctx.cascadesContext)) + .map(expr -> bindSlot(expr, filter.child(), ctx.cascadesContext)) .map(expr -> bindFunction(expr, ctx.cascadesContext)) .collect(ImmutableSet.toImmutableSet()); return new LogicalFilter<>(boundConjuncts, filter.child()); @@ -216,7 +218,7 @@ public class BindExpression implements AnalysisRuleFactory { logicalAggregate().thenApply(ctx -> { LogicalAggregate agg = ctx.root; List output = agg.getOutputExpressions().stream() - .map(expr -> bindSlot(expr, agg.children(), ctx.cascadesContext)) + .map(expr -> bindSlot(expr, agg.child(), ctx.cascadesContext)) .map(expr -> bindFunction(expr, ctx.cascadesContext)) .collect(ImmutableList.toImmutableList()); @@ -348,7 +350,7 @@ public class BindExpression implements AnalysisRuleFactory { logicalRepeat().thenApply(ctx -> { LogicalRepeat repeat = ctx.root; List output = repeat.getOutputExpressions().stream() - .map(expr -> bindSlot(expr, repeat.children(), ctx.cascadesContext)) + .map(expr -> bindSlot(expr, repeat.child(), ctx.cascadesContext)) .map(expr -> bindFunction(expr, ctx.cascadesContext)) .collect(ImmutableList.toImmutableList()); @@ -381,7 +383,7 @@ public class BindExpression implements AnalysisRuleFactory { List> groupingSets = replacedGroupingSets .stream() .map(groupingSet -> groupingSet.stream() - .map(expr -> bindSlot(expr, repeat.children(), ctx.cascadesContext)) + .map(expr -> bindSlot(expr, repeat.child(), ctx.cascadesContext)) .map(expr -> bindFunction(expr, ctx.cascadesContext)) .collect(ImmutableList.toImmutableList())) .collect(ImmutableList.toImmutableList()); @@ -449,7 +451,7 @@ public class BindExpression implements AnalysisRuleFactory { Aggregate childPlan = having.child(); Set boundConjuncts = having.getConjuncts().stream() .map(expr -> { - expr = bindSlot(expr, childPlan.children(), ctx.cascadesContext, false); + expr = bindSlot(expr, childPlan.child(), ctx.cascadesContext, false); return bindSlot(expr, childPlan, ctx.cascadesContext, false); }) .map(expr -> bindFunction(expr, ctx.cascadesContext)) @@ -527,7 +529,7 @@ public class BindExpression implements AnalysisRuleFactory { logicalGenerate().thenApply(ctx -> { LogicalGenerate generate = ctx.root; List boundSlotGenerators - = bindSlot(generate.getGenerators(), generate.children(), ctx.cascadesContext); + = bindSlot(generate.getGenerators(), generate.child(), ctx.cascadesContext); List boundFunctionGenerators = boundSlotGenerators.stream() .map(f -> bindTableGeneratingFunction((UnboundFunction) f, ctx.cascadesContext)) .collect(Collectors.toList()); @@ -612,10 +614,10 @@ public class BindExpression implements AnalysisRuleFactory { } private List bindSlot( - List exprList, List inputs, CascadesContext cascadesContext) { + List exprList, Plan input, CascadesContext cascadesContext) { List slots = new ArrayList<>(exprList.size()); for (E expr : exprList) { - E result = bindSlot(expr, inputs, cascadesContext); + E result = bindSlot(expr, input, cascadesContext); slots.add(result); } return slots; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/stats/ExpressionEstimation.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/stats/ExpressionEstimation.java index d7d9397d1a..50f27dc2a9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/stats/ExpressionEstimation.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/stats/ExpressionEstimation.java @@ -155,26 +155,33 @@ public class ExpressionEstimation extends ExpressionVisitor extends LogicalUnary projects; private final List excepts; - + private final boolean isDistinct; // For project nodes under union, erasure cannot be configured, so add this flag. private final boolean canEliminate; - private final boolean isDistinct; - public LogicalProject(List projects, CHILD_TYPE child) { - this(projects, ImmutableList.of(), true, child, false); + this(projects, ImmutableList.of(), false, true, child); } + /** + * only for test. + */ public LogicalProject(List projects, List excepts, CHILD_TYPE child) { - this(projects, excepts, true, child, false); + this(projects, excepts, false, true, child); + } + + public LogicalProject(List projects, boolean isDistinct, CHILD_TYPE child) { + this(projects, ImmutableList.of(), isDistinct, true, child); } public LogicalProject(List projects, List excepts, - boolean canEliminate, CHILD_TYPE child) { - this(projects, excepts, canEliminate, Optional.empty(), Optional.empty(), child, false); - } - - public LogicalProject(List projects, CHILD_TYPE child, boolean isDistinct) { - this(projects, ImmutableList.of(), true, child, isDistinct); - } - - public LogicalProject(List projects, List excepts, CHILD_TYPE child, - boolean isDistinct) { - this(projects, excepts, true, child, isDistinct); + boolean isDistinct, CHILD_TYPE child) { + this(projects, excepts, isDistinct, true, child); } private LogicalProject(List projects, List excepts, - boolean canEliminate, CHILD_TYPE child, boolean isDistinct) { - this(projects, excepts, canEliminate, Optional.empty(), Optional.empty(), child, isDistinct); + boolean isDistinct, boolean canEliminate, CHILD_TYPE child) { + this(projects, excepts, isDistinct, canEliminate, Optional.empty(), Optional.empty(), child); } - private LogicalProject(List projects, List excepts, boolean canEliminate, - Optional groupExpression, Optional logicalProperties, - CHILD_TYPE child, boolean isDistinct) { + private LogicalProject(List projects, List excepts, boolean isDistinct, + boolean canEliminate, Optional groupExpression, + Optional logicalProperties, CHILD_TYPE child) { super(PlanType.LOGICAL_PROJECT, groupExpression, logicalProperties, child); Preconditions.checkArgument(projects != null, "projects can not be null"); // only ColumnPrune rule may produce empty projects, this happens in rewrite phase @@ -94,8 +90,8 @@ public class LogicalProject extends LogicalUnary extends LogicalUnary extends LogicalUnary withChildren(List children) { Preconditions.checkArgument(children.size() == 1); - return new LogicalProject<>(projects, excepts, canEliminate, children.get(0), isDistinct); + return new LogicalProject<>(projects, excepts, isDistinct, canEliminate, children.get(0)); } @Override public LogicalProject withGroupExpression(Optional groupExpression) { - return new LogicalProject<>(projects, excepts, canEliminate, - groupExpression, Optional.of(getLogicalProperties()), child(), isDistinct); + return new LogicalProject<>(projects, excepts, isDistinct, canEliminate, + groupExpression, Optional.of(getLogicalProperties()), child()); } @Override public Plan withGroupExprLogicalPropChildren(Optional groupExpression, Optional logicalProperties, List children) { Preconditions.checkArgument(children.size() == 1); - return new LogicalProject<>(projects, excepts, canEliminate, - groupExpression, logicalProperties, children.get(0), isDistinct); + return new LogicalProject<>(projects, excepts, isDistinct, canEliminate, + groupExpression, logicalProperties, children.get(0)); } public LogicalProject withEliminate(boolean isEliminate) { - return new LogicalProject<>(projects, excepts, isEliminate, child(), isDistinct); + return new LogicalProject<>(projects, excepts, isDistinct, isEliminate, child()); } public LogicalProject withProjects(List projects) { - return new LogicalProject<>(projects, excepts, canEliminate, child(), isDistinct); + return new LogicalProject<>(projects, excepts, isDistinct, canEliminate, child()); } public LogicalProject withProjectsAndChild(List projects, Plan child) { - return new LogicalProject<>(projects, excepts, canEliminate, child, isDistinct); - } - - public boolean canEliminate() { - return canEliminate; + return new LogicalProject<>(projects, excepts, isDistinct, canEliminate, child); } public boolean isDistinct() { return isDistinct; } + public boolean canEliminate() { + return canEliminate; + } + @Override public List getOutputs() { return projects; @@ -229,9 +225,4 @@ public class LogicalProject extends LogicalUnary readFromJson(JSONObject logicalProject) { - return new LogicalProject<>(ImmutableList.of(new UnboundStar(ImmutableList.of())), - null, null, isDistinct); - } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java index 185c445647..6099891fa4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/TypeCoercionUtils.java @@ -91,7 +91,9 @@ import org.apache.doris.nereids.types.TimeType; import org.apache.doris.nereids.types.TimeV2Type; import org.apache.doris.nereids.types.TinyIntType; import org.apache.doris.nereids.types.VarcharType; +import org.apache.doris.nereids.types.coercion.AnyDataType; import org.apache.doris.nereids.types.coercion.CharacterType; +import org.apache.doris.nereids.types.coercion.FollowToAnyDataType; import org.apache.doris.nereids.types.coercion.FractionalType; import org.apache.doris.nereids.types.coercion.IntegralType; import org.apache.doris.nereids.types.coercion.NumericType; @@ -183,7 +185,9 @@ public class TypeCoercionUtils { // TODO: complete the cast logic like FunctionCallExpr.analyzeImpl boolean legacyCastCompatible = false; try { - legacyCastCompatible = !input.toCatalogDataType().matchesType(expected.toCatalogDataType()); + if (!(expected instanceof AnyDataType) && !(expected instanceof FollowToAnyDataType)) { + legacyCastCompatible = !input.toCatalogDataType().matchesType(expected.toCatalogDataType()); + } } catch (Throwable t) { // ignore. }