[feature](nereids)support decimalv2 (#28726)
This commit is contained in:
@ -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) {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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,
|
||||
|
||||
Reference in New Issue
Block a user