[feature](nereids)support decimalv2 (#28726)

This commit is contained in:
starocean999
2023-12-25 11:23:27 +08:00
committed by GitHub
parent 99755920e2
commit c53611dcb3
9 changed files with 236 additions and 18 deletions

View File

@ -570,6 +570,9 @@ public class NumericArithmetic {
return new DoubleLiteral(result);
}
/**
* Executable arithmetic functions divide
*/
@ExecFunction(name = "divide", argTypes = {"DECIMAL", "DECIMAL"}, returnType = "DECIMAL")
public static Expression divideDecimal(DecimalLiteral first, DecimalLiteral second) {
if (first.getValue().compareTo(BigDecimal.ZERO) == 0) {

View File

@ -74,13 +74,14 @@ public class DecimalLiteral extends Literal {
/**
* check precision and scale is enough for value.
*/
public static void checkPrecisionAndScale(int precision, int scale, BigDecimal value) throws AnalysisException {
private static void checkPrecisionAndScale(int precision, int scale, BigDecimal value) throws AnalysisException {
Preconditions.checkNotNull(value);
int realPrecision = value.precision();
int realScale = value.scale();
boolean valid = true;
if (precision != -1 && scale != -1) {
if (precision < realPrecision || scale < realScale) {
if (precision < realPrecision || scale < realScale
|| realPrecision - realScale > DecimalV2Type.MAX_PRECISION - DecimalV2Type.MAX_SCALE) {
valid = false;
}
} else {

View File

@ -18,9 +18,12 @@
package org.apache.doris.nereids.trees.expressions.literal;
import org.apache.doris.analysis.LiteralExpr;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.DecimalV3Type;
import com.google.common.base.Preconditions;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;
@ -43,7 +46,7 @@ public class DecimalV3Literal extends Literal {
public DecimalV3Literal(DecimalV3Type dataType, BigDecimal value) {
super(DecimalV3Type.createDecimalV3TypeLooseCheck(dataType.getPrecision(), dataType.getScale()));
Objects.requireNonNull(value, "value not be null");
DecimalLiteral.checkPrecisionAndScale(dataType.getPrecision(), dataType.getScale(), value);
checkPrecisionAndScale(dataType.getPrecision(), dataType.getScale(), value);
BigDecimal adjustedValue = value.scale() < 0 ? value
: value.setScale(dataType.getScale(), RoundingMode.HALF_UP);
this.value = Objects.requireNonNull(adjustedValue);
@ -80,4 +83,27 @@ public class DecimalV3Literal extends Literal {
.createDecimalV3Type(((DecimalV3Type) dataType).getPrecision(), newScale),
value.setScale(newScale, RoundingMode.FLOOR));
}
/**
* check precision and scale is enough for value.
*/
private static void checkPrecisionAndScale(int precision, int scale, BigDecimal value) throws AnalysisException {
Preconditions.checkNotNull(value);
int realPrecision = value.precision();
int realScale = value.scale();
boolean valid = true;
if (precision != -1 && scale != -1) {
if (precision < realPrecision || scale < realScale) {
valid = false;
}
} else {
valid = false;
}
if (!valid) {
throw new AnalysisException(
String.format("Invalid precision and scale - expect (%d, %d), but (%d, %d)",
precision, scale, realPrecision, realScale));
}
}
}

View File

@ -156,6 +156,24 @@ public abstract class DataType {
throw new AnalysisException("Nereids do not support type: " + type);
}
break;
case "decimalv2":
// NOTICE, maybe convert to decimalv3, so do not truc here.
switch (types.size()) {
case 1:
dataType = DecimalV2Type.CATALOG_DEFAULT_NOT_CONVERSION;
break;
case 2:
dataType = DecimalV2Type.createDecimalV2TypeWithoutTruncate(
Integer.parseInt(types.get(1)), 0, false);
break;
case 3:
dataType = DecimalV2Type.createDecimalV2TypeWithoutTruncate(
Integer.parseInt(types.get(1)), Integer.parseInt(types.get(2)), false);
break;
default:
throw new AnalysisException("Nereids do not support type: " + type);
}
break;
case "decimalv3":
switch (types.size()) {
case 1:

View File

@ -37,17 +37,21 @@ public class DecimalV2Type extends FractionalType {
public static int MAX_PRECISION = 27;
public static int MAX_SCALE = 9;
public static final DecimalV2Type SYSTEM_DEFAULT = new DecimalV2Type(MAX_PRECISION, MAX_SCALE);
public static final DecimalV2Type CATALOG_DEFAULT = new DecimalV2Type(DEFAULT_PRECISION, DEFAULT_SCALE);
public static final DecimalV2Type SYSTEM_DEFAULT = new DecimalV2Type(MAX_PRECISION, MAX_SCALE, true);
public static final DecimalV2Type SYSTEM_DEFAULT_NOT_CONVERSION =
new DecimalV2Type(MAX_PRECISION, MAX_SCALE, false);
public static final DecimalV2Type CATALOG_DEFAULT = new DecimalV2Type(DEFAULT_PRECISION, DEFAULT_SCALE, true);
public static final DecimalV2Type CATALOG_DEFAULT_NOT_CONVERSION =
new DecimalV2Type(DEFAULT_PRECISION, DEFAULT_SCALE, false);
private static final DecimalV2Type BOOLEAN_DECIMAL = new DecimalV2Type(1, 0);
private static final DecimalV2Type TINYINT_DECIMAL = new DecimalV2Type(3, 0);
private static final DecimalV2Type SMALLINT_DECIMAL = new DecimalV2Type(5, 0);
private static final DecimalV2Type INTEGER_DECIMAL = new DecimalV2Type(10, 0);
private static final DecimalV2Type BIGINT_DECIMAL = new DecimalV2Type(20, 0);
private static final DecimalV2Type LARGEINT_DECIMAL = new DecimalV2Type(27, 0);
private static final DecimalV2Type FLOAT_DECIMAL = new DecimalV2Type(14, 7);
private static final DecimalV2Type DOUBLE_DECIMAL = new DecimalV2Type(27, 9);
private static final DecimalV2Type BOOLEAN_DECIMAL = new DecimalV2Type(1, 0, true);
private static final DecimalV2Type TINYINT_DECIMAL = new DecimalV2Type(3, 0, true);
private static final DecimalV2Type SMALLINT_DECIMAL = new DecimalV2Type(5, 0, true);
private static final DecimalV2Type INTEGER_DECIMAL = new DecimalV2Type(10, 0, true);
private static final DecimalV2Type BIGINT_DECIMAL = new DecimalV2Type(20, 0, true);
private static final DecimalV2Type LARGEINT_DECIMAL = new DecimalV2Type(27, 0, true);
private static final DecimalV2Type FLOAT_DECIMAL = new DecimalV2Type(14, 7, true);
private static final DecimalV2Type DOUBLE_DECIMAL = new DecimalV2Type(27, 9, true);
private static final int WIDTH = 16;
@ -68,14 +72,17 @@ public class DecimalV2Type extends FractionalType {
private final int precision;
private final int scale;
private final boolean shouldConversion;
/**
* constructors.
*/
private DecimalV2Type(int precision, int scale) {
private DecimalV2Type(int precision, int scale, boolean shouldConversion) {
Preconditions.checkArgument(precision >= scale, "precision should not smaller than scale,"
+ " but precision is " + precision, ", scale is " + scale);
this.precision = precision;
this.scale = scale;
this.shouldConversion = shouldConversion;
}
/** createDecimalV2Type. */
@ -86,7 +93,7 @@ public class DecimalV2Type extends FractionalType {
if (precision == CATALOG_DEFAULT.precision && scale == CATALOG_DEFAULT.scale) {
return CATALOG_DEFAULT;
}
return new DecimalV2Type(Math.min(precision, MAX_PRECISION), Math.min(scale, MAX_SCALE));
return new DecimalV2Type(Math.min(precision, MAX_PRECISION), Math.min(scale, MAX_SCALE), true);
}
public static DecimalV2Type createDecimalV2Type(BigDecimal bigDecimal) {
@ -105,7 +112,22 @@ public class DecimalV2Type extends FractionalType {
if (precision == CATALOG_DEFAULT.precision && scale == CATALOG_DEFAULT.scale) {
return CATALOG_DEFAULT;
}
return new DecimalV2Type(precision, scale);
return new DecimalV2Type(precision, scale, true);
}
/**
* create DecimalV2Type with appropriate scale, precision and shouldConversion flag,
* not truncate to MAX_PRECISION, MAX_SCALE.
*/
public static DecimalV2Type createDecimalV2TypeWithoutTruncate(int precision, int scale,
boolean shouldConversion) {
if (precision == SYSTEM_DEFAULT.precision && scale == SYSTEM_DEFAULT.scale) {
return shouldConversion ? SYSTEM_DEFAULT : SYSTEM_DEFAULT_NOT_CONVERSION;
}
if (precision == CATALOG_DEFAULT.precision && scale == CATALOG_DEFAULT.scale) {
return shouldConversion ? CATALOG_DEFAULT : CATALOG_DEFAULT_NOT_CONVERSION;
}
return new DecimalV2Type(precision, scale, shouldConversion);
}
/**
@ -153,7 +175,7 @@ public class DecimalV2Type extends FractionalType {
@Override
public DataType conversion() {
if (Config.enable_decimal_conversion) {
if (Config.enable_decimal_conversion && shouldConversion) {
return DecimalV3Type.createDecimalV3Type(precision, scale);
}
Preconditions.checkArgument(precision > 0 && precision <= MAX_PRECISION,