Skip to content

Commit

Permalink
ARROW-15501: [Java] Support validating decimal vectors
Browse files Browse the repository at this point in the history
Support validating decimal vectors and check precisions.

Closes apache#12294 from liyafan82/fly_0129_dec

Authored-by: liyafan82 <[email protected]>
Signed-off-by: liyafan82 <[email protected]>
  • Loading branch information
liyafan82 committed Feb 18, 2022
1 parent f49547b commit 2a19660
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
* maintained to track which elements in the vector are null.
*/
public final class Decimal256Vector extends BaseFixedWidthVector {
public static final int MAX_PRECISION = 76;
public static final byte TYPE_WIDTH = 32;
private static final boolean LITTLE_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN;
private final FieldReader reader;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
* maintained to track which elements in the vector are null.
*/
public final class DecimalVector extends BaseFixedWidthVector {
public static final int MAX_PRECISION = 38;
public static final byte TYPE_WIDTH = 16;
private static final boolean LITTLE_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN;
private final FieldReader reader;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,28 @@ private void validateDateVector(ValueVector vector, DateUnit expectedDateUnit) {
"Expecting date unit %s, actual date unit %s.", expectedDateUnit, dateType.getUnit());
}

private void validateDecimalVector(ValueVector vector) {
validateOrThrow(vector.getField().getFieldType().getType() instanceof ArrowType.Decimal,
"Vector %s is not a decimal vector", vector.getClass());
ArrowType.Decimal decimalType = (ArrowType.Decimal) vector.getField().getFieldType().getType();
validateOrThrow(decimalType.getScale() >= 0, "The scale of decimal %s is negative.", decimalType.getScale());
validateOrThrow(decimalType.getScale() <= decimalType.getPrecision(),
"The scale of decimal %s is greater than the precision %s.",
decimalType.getScale(), decimalType.getPrecision());
switch (decimalType.getBitWidth()) {
case DecimalVector.TYPE_WIDTH * 8:
validateOrThrow(decimalType.getPrecision() >= 1 && decimalType.getPrecision() <= DecimalVector.MAX_PRECISION,
"Invalid precision %s for decimal 128.", decimalType.getPrecision());
break;
case Decimal256Vector.TYPE_WIDTH * 8:
validateOrThrow(decimalType.getPrecision() >= 1 && decimalType.getPrecision() <= Decimal256Vector.MAX_PRECISION,
"Invalid precision %s for decimal 256.", decimalType.getPrecision());
break;
default:
throw new ValidateUtil.ValidateException("Only decimal 128 or decimal 256 are supported for decimal types");
}
}

private void validateTimeVector(ValueVector vector, TimeUnit expectedTimeUnit, int expectedBitWidth) {
validateOrThrow(vector.getField().getFieldType().getType() instanceof ArrowType.Time,
"Vector %s is not a time vector.", vector.getClass());
Expand Down Expand Up @@ -188,10 +210,7 @@ public Void visit(BaseFixedWidthVector vector, Void value) {
validateVectorCommon(vector, ArrowType.Bool.class);
} else if (vector instanceof DecimalVector || vector instanceof Decimal256Vector) {
validateVectorCommon(vector, ArrowType.Decimal.class);
ArrowType.Decimal arrowType = (ArrowType.Decimal) vector.getField().getType();
validateOrThrow(arrowType.getScale() > 0, "The scale of decimal %s is not positive.", arrowType.getScale());
validateOrThrow(arrowType.getPrecision() > 0, "The precision of decimal %S is not positive.",
arrowType.getPrecision());
validateDecimalVector(vector);
} else if (vector instanceof DateDayVector) {
validateVectorCommon(vector, ArrowType.Date.class);
validateDateVector(vector, DateUnit.DAY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.apache.arrow.vector.BitVector;
import org.apache.arrow.vector.DateDayVector;
import org.apache.arrow.vector.DateMilliVector;
import org.apache.arrow.vector.Decimal256Vector;
import org.apache.arrow.vector.DecimalVector;
import org.apache.arrow.vector.DurationVector;
import org.apache.arrow.vector.FixedSizeBinaryVector;
Expand Down Expand Up @@ -227,6 +228,30 @@ public void testFixedWidthVectorsNegative() {
() -> new TimeStampSecVector("vector", FieldType.nullable(Types.MinorType.BIGINT.getType()), allocator));
}

@Test
public void testDecimalVector() {
testPositiveCase(() ->
new DecimalVector("dec", FieldType.nullable(ArrowType.Decimal.createDecimal(10, 10, 128)), allocator));
testPositiveCase(() ->
new DecimalVector("dec", FieldType.nullable(ArrowType.Decimal.createDecimal(38, 10, 128)), allocator));
testPositiveCase(() ->
new Decimal256Vector("dec", FieldType.nullable(ArrowType.Decimal.createDecimal(50, 10, 256)), allocator));
testPositiveCase(() ->
new Decimal256Vector("dec", FieldType.nullable(ArrowType.Decimal.createDecimal(76, 10, 256)), allocator));
testNegativeCase(() ->
new DecimalVector("dec", FieldType.nullable(ArrowType.Decimal.createDecimal(50, 10, 128)), allocator));
testNegativeCase(() ->
new Decimal256Vector("dec", FieldType.nullable(ArrowType.Decimal.createDecimal(100, 10, 256)), allocator));
testNegativeCase(() ->
new DecimalVector("dec", FieldType.nullable(ArrowType.Decimal.createDecimal(0, 10, 128)), allocator));
testNegativeCase(() ->
new Decimal256Vector("dec", FieldType.nullable(ArrowType.Decimal.createDecimal(-1, 10, 256)), allocator));
testNegativeCase(() ->
new Decimal256Vector("dec", FieldType.nullable(ArrowType.Decimal.createDecimal(30, 10, 64)), allocator));
testNegativeCase(() ->
new Decimal256Vector("dec", FieldType.nullable(ArrowType.Decimal.createDecimal(10, 20, 256)), allocator));
}

@Test
public void testVariableWidthVectorsPositive() {
testPositiveCase(() -> new VarCharVector("vector", allocator));
Expand Down

0 comments on commit 2a19660

Please sign in to comment.