[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:
morrySnow
2024-01-11 13:54:05 +08:00
committed by yiguolei
parent 22c134fa0a
commit eed72a101e
5 changed files with 16 additions and 9 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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 {

View File

@ -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

View File

@ -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;"""