From b51dc708268a88eed8e7a463c72381cb04c140ca Mon Sep 17 00:00:00 2001 From: starocean999 <40539150+starocean999@users.noreply.github.com> Date: Fri, 1 Dec 2023 20:05:21 +0800 Subject: [PATCH] [fix](nereids) set operation's result type is wrong if decimal overflows (#27872) pick from master #27870 --- .../plans/logical/LogicalSetOperation.java | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalSetOperation.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalSetOperation.java index c58b0aa0688a94..1835363bce826b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalSetOperation.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalSetOperation.java @@ -17,6 +17,7 @@ package org.apache.doris.nereids.trees.plans.logical; +import org.apache.doris.catalog.ScalarType; import org.apache.doris.catalog.Type; import org.apache.doris.nereids.memo.GroupExpression; import org.apache.doris.nereids.properties.LogicalProperties; @@ -137,10 +138,7 @@ private List> castCommonDataTypeOutputs() { for (int i = 0; i < child(0).getOutput().size(); ++i) { Slot left = child(0).getOutput().get(i); Slot right = child(1).getOutput().get(i); - DataType compatibleType = DataType.fromCatalogType(Type.getAssignmentCompatibleType( - left.getDataType().toCatalogDataType(), - right.getDataType().toCatalogDataType(), - false)); + DataType compatibleType = getAssignmentCompatibleType(left.getDataType(), right.getDataType()); Expression newLeft = TypeCoercionUtils.castIfNotSameType(left, compatibleType); Expression newRight = TypeCoercionUtils.castIfNotSameType(right, compatibleType); if (newLeft instanceof Cast) { @@ -211,4 +209,30 @@ public abstract LogicalSetOperation withChildrenAndTheirOutputs( public int getArity() { return children.size(); } + + private DataType getAssignmentCompatibleType(DataType left, DataType right) { + if (left.isNullType()) { + return right; + } + if (right.isNullType()) { + return left; + } + if (left.equals(right)) { + return left; + } + Type resultType = Type.getAssignmentCompatibleType(left.toCatalogDataType(), + right.toCatalogDataType(), false); + if (resultType.isDecimalV3()) { + int oldPrecision = resultType.getPrecision(); + int oldScale = resultType.getDecimalDigits(); + int integerPart = oldPrecision - oldScale; + int maxPrecision = ScalarType.MAX_DECIMAL128_PRECISION; + if (oldPrecision > maxPrecision) { + int newScale = maxPrecision - integerPart; + resultType = + ScalarType.createDecimalType(maxPrecision, newScale < 0 ? 0 : newScale); + } + } + return DataType.fromCatalogType(resultType); + } }