[fix](Nereids) decimalv3 cast in fe produce wrong data (#29808)
case: ``` MySQL root@127.0.0.1:test> select cast(12 as decimalv3(2,1)) +-----------------------------+ | cast(12 as DECIMALV3(2, 1)) | +-----------------------------+ | 12.0 | +-----------------------------+ ``` decimalv2 literal will generate wrong result too. But it is not only bugs in planner, but also have bugs in executor. So we need fix executor bug in another PR.
This commit is contained in:
@ -82,14 +82,15 @@ public class SimplifyCastRule extends AbstractExpressionRewriteRule {
|
||||
((VarcharType) castType).getLen());
|
||||
}
|
||||
} else if (castType instanceof DecimalV2Type) {
|
||||
DecimalV2Type decimalV2Type = (DecimalV2Type) castType;
|
||||
if (child instanceof TinyIntLiteral) {
|
||||
return new DecimalLiteral(new BigDecimal(((TinyIntLiteral) child).getValue()));
|
||||
return new DecimalLiteral(decimalV2Type, new BigDecimal(((TinyIntLiteral) child).getValue()));
|
||||
} else if (child instanceof SmallIntLiteral) {
|
||||
return new DecimalLiteral(new BigDecimal(((SmallIntLiteral) child).getValue()));
|
||||
return new DecimalLiteral(decimalV2Type, new BigDecimal(((SmallIntLiteral) child).getValue()));
|
||||
} else if (child instanceof IntegerLiteral) {
|
||||
return new DecimalLiteral(new BigDecimal(((IntegerLiteral) child).getValue()));
|
||||
return new DecimalLiteral(decimalV2Type, new BigDecimal(((IntegerLiteral) child).getValue()));
|
||||
} else if (child instanceof BigIntLiteral) {
|
||||
return new DecimalLiteral(new BigDecimal(((BigIntLiteral) child).getValue()));
|
||||
return new DecimalLiteral(decimalV2Type, new BigDecimal(((BigIntLiteral) child).getValue()));
|
||||
}
|
||||
} else if (castType instanceof DecimalV3Type) {
|
||||
DecimalV3Type decimalV3Type = (DecimalV3Type) castType;
|
||||
|
||||
@ -81,6 +81,7 @@ public class DecimalLiteral extends Literal {
|
||||
boolean valid = true;
|
||||
if (precision != -1 && scale != -1) {
|
||||
if (precision < realPrecision || scale < realScale
|
||||
|| realPrecision - realScale > precision - scale
|
||||
|| realPrecision - realScale > DecimalV2Type.MAX_PRECISION - DecimalV2Type.MAX_SCALE) {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ public class DecimalV3Literal extends Literal {
|
||||
int realScale = value.scale();
|
||||
boolean valid = true;
|
||||
if (precision != -1 && scale != -1) {
|
||||
if (precision < realPrecision || scale < realScale) {
|
||||
if (precision < realPrecision || scale < realScale || precision - scale < realPrecision - realScale) {
|
||||
valid = false;
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -200,13 +200,13 @@ class ExpressionRewriteTest extends ExpressionRewriteTestHelper {
|
||||
|
||||
// decimal literal
|
||||
assertRewrite(new Cast(new TinyIntLiteral((byte) 1), DecimalV2Type.createDecimalV2Type(15, 9)),
|
||||
new DecimalLiteral(new BigDecimal(1)));
|
||||
new DecimalLiteral(new BigDecimal("1.000000000")));
|
||||
assertRewrite(new Cast(new SmallIntLiteral((short) 1), DecimalV2Type.createDecimalV2Type(15, 9)),
|
||||
new DecimalLiteral(new BigDecimal(1)));
|
||||
new DecimalLiteral(new BigDecimal("1.000000000")));
|
||||
assertRewrite(new Cast(new IntegerLiteral(1), DecimalV2Type.createDecimalV2Type(15, 9)),
|
||||
new DecimalLiteral(new BigDecimal(1)));
|
||||
new DecimalLiteral(new BigDecimal("1.000000000")));
|
||||
assertRewrite(new Cast(new BigIntLiteral(1L), DecimalV2Type.createDecimalV2Type(15, 9)),
|
||||
new DecimalLiteral(new BigDecimal(1)));
|
||||
new DecimalLiteral(new BigDecimal("1.000000000")));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@ -233,6 +233,11 @@ suite("cast") {
|
||||
sql """select cast(k5 as time) ct from test order by ct;"""
|
||||
exception "cannot cast"
|
||||
}
|
||||
test {
|
||||
sql "select cast(12 as decimalv3(2,1))"
|
||||
exception "Arithmetic overflow"
|
||||
}
|
||||
|
||||
// date
|
||||
test {
|
||||
sql """select cast(k10 as time) ct from test order by ct;"""
|
||||
|
||||
Reference in New Issue
Block a user