diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java index 58692e451d..e933b0fdd8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java @@ -541,7 +541,7 @@ public class BuiltinScalarFunctions implements FunctionHelper { scalar(MonthCeil.class, "month_ceil"), scalar(MonthFloor.class, "month_floor"), scalar(MonthName.class, "monthname"), - scalar(MonthsAdd.class, "months_add"), + scalar(MonthsAdd.class, "months_add", "add_months"), scalar(MonthsDiff.class, "months_diff"), scalar(MonthsSub.class, "months_sub"), scalar(MultiMatchAny.class, "multi_match_any"), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/GroupExpression.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/GroupExpression.java index afa6d51f9b..7acb1cb4eb 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/GroupExpression.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/GroupExpression.java @@ -32,7 +32,9 @@ import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.util.Utils; import org.apache.doris.statistics.Statistics; +import com.google.common.base.Joiner; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -42,6 +44,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; /** * Representation for group expression in cascades optimizer. @@ -202,6 +205,11 @@ public class GroupExpression { return lowestCostTable.get(require).second; } + public List getInputPropertiesListOrEmpty(PhysicalProperties require) { + Pair> costAndChildRequire = lowestCostTable.get(require); + return costAndChildRequire == null ? ImmutableList.of() : costAndChildRequire.second; + } + /** * Add a (outputProperties) -> (cost, childrenInputProperties) in lowestCostTable. * if the outputProperties exists, will be covered. @@ -318,9 +326,8 @@ public class GroupExpression { builder.append(" cost=").append(format.format((long) cost)); builder.append(" estRows=").append(format.format(estOutputRowCount)); builder.append(" (plan=").append(plan.toString()).append(") children=["); - for (Group group : children) { - builder.append(group.getGroupId()).append(" "); - } + builder.append(Joiner.on(", ").join( + children.stream().map(Group::getGroupId).collect(Collectors.toList()))); builder.append("]"); return builder.toString(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Memo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Memo.java index 6011508bd2..f8d7694dcc 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Memo.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Memo.java @@ -717,13 +717,16 @@ public class Memo { } } - builder.append(" lowest Plan(cost, properties, plan)"); + builder.append(" lowest Plan(cost, properties, plan, childrenRequires)"); group.getAllProperties().forEach( prop -> { Optional> costAndGroupExpression = group.getLowestCostPlan(prop); if (costAndGroupExpression.isPresent()) { - builder.append("\n " + costAndGroupExpression.get().first.getValue() + " " + prop) - .append("\n ").append(costAndGroupExpression.get().second); + Cost cost = costAndGroupExpression.get().first; + GroupExpression child = costAndGroupExpression.get().second; + builder.append("\n " + cost.getValue() + " " + prop) + .append("\n ").append(child) + .append("\n " + child.getInputPropertiesListOrEmpty(prop)); } } ); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/ChildOutputPropertyDeriver.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/ChildOutputPropertyDeriver.java index 467bdc004c..7cfffe090e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/ChildOutputPropertyDeriver.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/ChildOutputPropertyDeriver.java @@ -21,8 +21,11 @@ import org.apache.doris.nereids.PlanContext; import org.apache.doris.nereids.memo.GroupExpression; import org.apache.doris.nereids.properties.DistributionSpecHash.ShuffleType; import org.apache.doris.nereids.trees.expressions.Alias; +import org.apache.doris.nereids.trees.expressions.Cast; import org.apache.doris.nereids.trees.expressions.ExprId; +import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.NamedExpression; +import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.expressions.SlotReference; import org.apache.doris.nereids.trees.expressions.functions.table.TableValuedFunction; import org.apache.doris.nereids.trees.plans.Plan; @@ -43,6 +46,7 @@ import org.apache.doris.nereids.trees.plans.physical.PhysicalProject; import org.apache.doris.nereids.trees.plans.physical.PhysicalStorageLayerAggregate; import org.apache.doris.nereids.trees.plans.physical.PhysicalTVFRelation; import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor; +import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.util.JoinUtils; import org.apache.doris.qe.ConnectContext; @@ -137,11 +141,16 @@ public class ChildOutputPropertyDeriver extends PlanVisitor= originType.width() || castType.width() < 0)) { + return true; + } else { + return false; + } + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/ChildrenPropertiesRegulator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/ChildrenPropertiesRegulator.java index b2343bb501..35d4b367a0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/ChildrenPropertiesRegulator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/ChildrenPropertiesRegulator.java @@ -126,8 +126,8 @@ public class ChildrenPropertiesRegulator extends PlanVisitor { if (ConnectContext.get().getSessionVariable().isEnableBucketShuffleJoin()) { // We need to recalculate the required property of right child, // to make right child compatible with left child. - PhysicalProperties rightRequireProperties = calRightRequiredOfBucketShuffleJoin(leftHashSpec, - rightHashSpec); + PhysicalProperties rightRequireProperties = calRightRequiredOfBucketShuffleJoin( + leftHashSpec, rightHashSpec); if (!rightOutput.equals(rightRequireProperties)) { updateChildEnforceAndCost(rightChild, rightOutput, (DistributionSpecHash) rightRequireProperties.getDistributionSpec(), rightLowest.first); @@ -193,8 +193,8 @@ public class ChildrenPropertiesRegulator extends PlanVisitor { GroupExpression enforcer = outputDistributionSpec.addEnforcer(child.getOwnerGroup()); jobContext.getCascadesContext().getMemo().addEnforcerPlan(enforcer, child.getOwnerGroup()); Cost totalCost = CostCalculator.addChildCost(enforcer.getPlan(), - currentCost, CostCalculator.calculateCost(enforcer, Lists.newArrayList(childOutput)), + currentCost, 0); if (enforcer.updateLowestCostTable(newOutputProperty, diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java index 2c9cf77878..109357499f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java @@ -33,8 +33,6 @@ import org.apache.doris.nereids.types.LargeIntType; import org.apache.doris.nereids.types.StringType; import org.apache.doris.nereids.types.VarcharType; -import org.apache.commons.lang3.StringUtils; - import java.math.BigDecimal; import java.math.BigInteger; import java.util.Locale; @@ -137,45 +135,7 @@ public abstract class Literal extends Expression implements LeafExpression, Comp */ @Override public int compareTo(Literal other) { - if (isNullLiteral() && other.isNullLiteral()) { - return 0; - } else if (isNullLiteral() || other.isNullLiteral()) { - return isNullLiteral() ? -1 : 1; - } - - DataType oType = other.getDataType(); - DataType type = getDataType(); - - if (type.isVarcharType() && oType.isVarcharType()) { - // VarChar type can be different, e.g., VarChar(1) = VarChar(2) - return StringUtils.compare((String) getValue(), (String) other.getValue()); - } else if (!type.equals(oType)) { - throw new RuntimeException("data type not equal!"); - } else if (type.isBooleanType()) { - return Boolean.compare((boolean) getValue(), (boolean) other.getValue()); - } else if (type.isTinyIntType()) { - return Byte.compare((byte) getValue(), (byte) other.getValue()); - } else if (type.isSmallIntType()) { - return Short.compare((short) getValue(), (short) other.getValue()); - } else if (type.isIntegerType()) { - return Integer.compare((int) getValue(), (int) other.getValue()); - } else if (type.isBigIntType()) { - return Long.compare((long) getValue(), (long) other.getValue()); - } else if (type.isLargeIntType()) { - return ((BigInteger) getValue()).compareTo((BigInteger) other.getValue()); - } else if (type.isFloatType()) { - return Float.compare((float) getValue(), (float) other.getValue()); - } else if (type.isDoubleType()) { - return Double.compare((double) getValue(), (double) other.getValue()); - } else if (type.isDateLikeType()) { - return Long.compare((Long) getValue(), (Long) other.getValue()); - } else if (type.isDecimalV2Type()) { - return ((BigDecimal) getValue()).compareTo((BigDecimal) other.getValue()); - } else if (type.isStringLikeType()) { - return StringUtils.compare((String) getValue(), (String) other.getValue()); - } else { - throw new RuntimeException(String.format("Literal {} is not supported!", type.toString())); - } + return toLegacyLiteral().compareLiteral(other.toLegacyLiteral()); } /** @@ -268,10 +228,6 @@ public abstract class Literal extends Expression implements LeafExpression, Comp throw new AnalysisException("cannot cast " + desc + " from type " + this.dataType + " to type " + targetType); } - public boolean isCharacterLiteral() { - return this instanceof StringLiteral || this instanceof CharLiteral || this instanceof VarcharLiteral; - } - /** fromLegacyLiteral */ public static Literal fromLegacyLiteral(LiteralExpr literalExpr, Type type) { DataType dataType = DataType.fromCatalogType(type); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java index 7e296b55ae..175541fbc9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java @@ -367,6 +367,10 @@ public abstract class DataType implements AbstractDataType { return this instanceof IntegralType && !(this instanceof LargeIntType); } + public boolean isFloatLikeType() { + return this.isFloatType() || isDoubleType() || isDecimalLikeType(); + } + public boolean isTinyIntType() { return this instanceof TinyIntType; } 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 6b616dc84f..ce573d587a 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 @@ -296,11 +296,13 @@ public class TypeCoercionUtils { // process by constant folding return (T) op.withChildren(left, right); } - if (left instanceof Literal && ((Literal) left).isCharacterLiteral()) { + if (left instanceof Literal && ((Literal) left).isStringLikeLiteral() + && !right.getDataType().isStringLikeType()) { left = TypeCoercionUtils.characterLiteralTypeCoercion( ((Literal) left).getStringValue(), right.getDataType()).orElse(left); } - if (right instanceof Literal && ((Literal) right).isCharacterLiteral()) { + if (right instanceof Literal && ((Literal) right).isStringLikeLiteral() + && !left.getDataType().isStringLikeType()) { right = TypeCoercionUtils.characterLiteralTypeCoercion( ((Literal) right).getStringValue(), left.getDataType()).orElse(right); diff --git a/fe/fe-core/src/main/java/org/apache/doris/statistics/Statistics.java b/fe/fe-core/src/main/java/org/apache/doris/statistics/Statistics.java index 977a6da2c1..d10ef620b9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/statistics/Statistics.java +++ b/fe/fe-core/src/main/java/org/apache/doris/statistics/Statistics.java @@ -154,6 +154,15 @@ public class Statistics { @Override public String toString() { + if (Double.isNaN(rowCount)) { + return "NaN"; + } + if (Double.POSITIVE_INFINITY == rowCount) { + return "Infinite"; + } + if (Double.NEGATIVE_INFINITY == rowCount) { + return "-Infinite"; + } DecimalFormat format = new DecimalFormat("#,###.##"); return format.format(rowCount); } diff --git a/regression-test/suites/nereids_syntax_p0/type_cast.groovy b/regression-test/suites/nereids_syntax_p0/type_cast.groovy index 96356bd1d5..f57634f66f 100644 --- a/regression-test/suites/nereids_syntax_p0/type_cast.groovy +++ b/regression-test/suites/nereids_syntax_p0/type_cast.groovy @@ -46,4 +46,9 @@ suite("type_cast") { where case when id > 0 then 2 else 'abc' end = '2'""") result([[1]]) } + + test { + sql("select '12' = id from (select '1' as id)a") + result([[false]]) + } }