branch-2.1: [fix](constant fold)Make sure FE cast double to varchar generate identical result with BE. #50425 (#50548)
Cherry-picked from #50425 Co-authored-by: James <lijibing@selectdb.com>
This commit is contained in:
committed by
GitHub
parent
dfc1dbfb59
commit
98be2cedcf
@ -78,6 +78,7 @@ import org.apache.doris.nereids.trees.expressions.literal.DateLiteral;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.DateTimeLiteral;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.DoubleLiteral;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.Literal;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.StringLikeLiteral;
|
||||
@ -448,6 +449,9 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule
|
||||
}
|
||||
Expression child = cast.child();
|
||||
DataType dataType = cast.getDataType();
|
||||
if (!safeToCast(cast)) {
|
||||
return cast;
|
||||
}
|
||||
// todo: process other null case
|
||||
if (child.isNullLiteral()) {
|
||||
return new NullLiteral(dataType);
|
||||
@ -473,6 +477,25 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the given literal value is safe to cast to the targetType.
|
||||
// We need to guarantee FE cast result is identical with BE cast result.
|
||||
// Otherwise, it's not safe.
|
||||
protected boolean safeToCast(Cast cast) {
|
||||
if (cast == null || cast.child() == null || cast.getDataType() == null) {
|
||||
return true;
|
||||
}
|
||||
// Check double type.
|
||||
if (cast.child() instanceof DoubleLiteral && cast.getDataType().isStringLikeType()) {
|
||||
Double value = ((DoubleLiteral) cast.child()).getValue();
|
||||
if (value.isInfinite() || value.isNaN()) {
|
||||
return true;
|
||||
}
|
||||
return -1E16 < value && value < 1E16;
|
||||
}
|
||||
// Check other types if needed.
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression visitBoundFunction(BoundFunction boundFunction, ExpressionRewriteContext context) {
|
||||
if (!boundFunction.foldable()) {
|
||||
|
||||
@ -49,4 +49,34 @@ public class DoubleLiteral extends FractionalLiteral {
|
||||
public LiteralExpr toLegacyLiteral() {
|
||||
return new FloatLiteral(value, Type.DOUBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStringValue() {
|
||||
Double num = getValue();
|
||||
if (Double.isNaN(num)) {
|
||||
return "nan";
|
||||
} else if (Double.isInfinite(num)) {
|
||||
return num > 0 ? "inf" : "-inf";
|
||||
}
|
||||
|
||||
// Use %.17g to format the result,replace 'E' with 'e'
|
||||
String formatted = String.format("%.17g", num).replace('E', 'e');
|
||||
|
||||
// Remove trailing .0 in scientific notation.
|
||||
if (formatted.contains("e")) {
|
||||
String[] parts = formatted.split("e");
|
||||
String mantissa = parts[0];
|
||||
String exponent = parts.length > 1 ? "e" + parts[1] : "";
|
||||
mantissa = mantissa.replaceAll("\\.?0+$", "");
|
||||
if (mantissa.isEmpty()) {
|
||||
mantissa = "0";
|
||||
}
|
||||
formatted = mantissa + exponent;
|
||||
} else if (formatted.contains(".")) {
|
||||
// remove trailing .0 in fixed-point representation
|
||||
formatted = formatted.replaceAll("\\.?0+$", "");
|
||||
}
|
||||
|
||||
return formatted;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.trees.expressions.literal;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class DoubleLiteralTest {
|
||||
|
||||
@Test
|
||||
public void testGetStringValue() {
|
||||
Assertions.assertEquals("0", new DoubleLiteral(0).getStringValue());
|
||||
Assertions.assertEquals("0", new DoubleLiteral(0.0).getStringValue());
|
||||
Assertions.assertEquals("0", new DoubleLiteral(-0).getStringValue());
|
||||
Assertions.assertEquals("1", new DoubleLiteral(1).getStringValue());
|
||||
Assertions.assertEquals("1", new DoubleLiteral(1.0).getStringValue());
|
||||
Assertions.assertEquals("-1", new DoubleLiteral(-1).getStringValue());
|
||||
Assertions.assertEquals("1.554", new DoubleLiteral(1.554).getStringValue());
|
||||
Assertions.assertEquals("0.338", new DoubleLiteral(0.338).getStringValue());
|
||||
Assertions.assertEquals("-1", new DoubleLiteral(-1.0).getStringValue());
|
||||
Assertions.assertEquals("1e+100", new DoubleLiteral(1e100).getStringValue());
|
||||
Assertions.assertEquals("1e-100", new DoubleLiteral(1e-100).getStringValue());
|
||||
Assertions.assertEquals("10000000000000000", new DoubleLiteral(1.0E16).getStringValue());
|
||||
Assertions.assertEquals("-10000000000000000", new DoubleLiteral(-1.0E16).getStringValue());
|
||||
Assertions.assertEquals("1e+17", new DoubleLiteral(1.0E17).getStringValue());
|
||||
Assertions.assertEquals("-1e+17", new DoubleLiteral(-1.0E17).getStringValue());
|
||||
Assertions.assertEquals("0.0001", new DoubleLiteral(0.0001).getStringValue());
|
||||
Assertions.assertEquals("1e+308", new DoubleLiteral(1e308).getStringValue());
|
||||
Assertions.assertEquals("-1e+308", new DoubleLiteral(-1e308).getStringValue());
|
||||
Assertions.assertEquals("inf", new DoubleLiteral(Double.POSITIVE_INFINITY).getStringValue());
|
||||
Assertions.assertEquals("-inf", new DoubleLiteral(Double.NEGATIVE_INFINITY).getStringValue());
|
||||
Assertions.assertEquals("nan", new DoubleLiteral(Double.NaN).getStringValue());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user