Skip to content

Commit

Permalink
fix: skip negative scale checks for creating decimals (apache#723)
Browse files Browse the repository at this point in the history
(cherry picked from commit fbe86d0)
  • Loading branch information
kazuyukitanimura authored and huaxingao committed Aug 7, 2024
1 parent 2fcf189 commit ab420d2
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class CometDictionary implements AutoCloseable {
private final int numValues;

/** Decoded dictionary values. We only need to copy values for decimal type. */
private ByteArrayWrapper[] binaries;
private volatile ByteArrayWrapper[] binaries;

public CometDictionary(CometPlainVector values) {
this.values = values;
Expand Down
51 changes: 34 additions & 17 deletions common/src/main/java/org/apache/comet/vector/CometVector.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ public abstract class CometVector extends ColumnVector {
private final byte[] DECIMAL_BYTES = new byte[DECIMAL_BYTE_WIDTH];
protected final boolean useDecimal128;

private static final long decimalValOffset;

static {
try {
java.lang.reflect.Field unsafeField = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
final sun.misc.Unsafe unsafe = (sun.misc.Unsafe) unsafeField.get(null);
decimalValOffset = unsafe.objectFieldOffset(Decimal.class.getDeclaredField("decimalVal"));
} catch (Throwable e) {
throw new RuntimeException(e);
}
}

protected CometVector(DataType type, boolean useDecimal128) {
super(type);
this.useDecimal128 = useDecimal128;
Expand Down Expand Up @@ -73,31 +86,35 @@ public boolean isFixedLength() {
@Override
public Decimal getDecimal(int i, int precision, int scale) {
if (!useDecimal128 && precision <= Decimal.MAX_INT_DIGITS() && type instanceof IntegerType) {
return Decimal.createUnsafe(getInt(i), precision, scale);
return createDecimal(getInt(i), precision, scale);
} else if (!useDecimal128 && precision <= Decimal.MAX_LONG_DIGITS()) {
return Decimal.createUnsafe(getLong(i), precision, scale);
return createDecimal(getLong(i), precision, scale);
} else {
byte[] bytes = getBinaryDecimal(i);
BigInteger bigInteger = new BigInteger(bytes);
BigDecimal javaDecimal = new BigDecimal(bigInteger, scale);
try {
return Decimal.apply(javaDecimal, precision, scale);
} catch (ArithmeticException e) {
throw new ArithmeticException(
"Cannot convert "
+ javaDecimal
+ " (bytes: "
+ bytes
+ ", integer: "
+ bigInteger
+ ") to decimal with precision: "
+ precision
+ " and scale: "
+ scale);
}
return createDecimal(javaDecimal, precision, scale);
}
}

/** This method skips the negative scale check, otherwise the same as Decimal.createUnsafe(). */
private Decimal createDecimal(long unscaled, int precision, int scale) {
Decimal dec = new Decimal();
dec.org$apache$spark$sql$types$Decimal$$longVal_$eq(unscaled);
dec.org$apache$spark$sql$types$Decimal$$_precision_$eq(precision);
dec.org$apache$spark$sql$types$Decimal$$_scale_$eq(scale);
return dec;
}

/** This method skips a few checks, otherwise the same as Decimal.apply(). */
private Decimal createDecimal(BigDecimal value, int precision, int scale) {
Decimal dec = new Decimal();
Platform.putObjectVolatile(dec, decimalValOffset, new scala.math.BigDecimal(value));
dec.org$apache$spark$sql$types$Decimal$$_precision_$eq(precision);
dec.org$apache$spark$sql$types$Decimal$$_scale_$eq(scale);
return dec;
}

/**
* Reads a 16-byte byte array which are encoded big-endian for decimal128 into internal byte
* array.
Expand Down
1 change: 0 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,6 @@ under the License.
</execution>
</executions>
<configuration>
-->
<scalaVersion>${scala.version}</scalaVersion>
<checkMultipleScalaVersions>true</checkMultipleScalaVersions>
<failOnMultipleScalaVersions>true</failOnMultipleScalaVersions>
Expand Down

0 comments on commit ab420d2

Please sign in to comment.