@@ -45,6 +45,19 @@ public abstract class CometVector extends ColumnVector {
45
45
private final byte [] DECIMAL_BYTES = new byte [DECIMAL_BYTE_WIDTH ];
46
46
protected final boolean useDecimal128 ;
47
47
48
+ private static final long decimalValOffset ;
49
+
50
+ static {
51
+ try {
52
+ java .lang .reflect .Field unsafeField = sun .misc .Unsafe .class .getDeclaredField ("theUnsafe" );
53
+ unsafeField .setAccessible (true );
54
+ final sun .misc .Unsafe unsafe = (sun .misc .Unsafe ) unsafeField .get (null );
55
+ decimalValOffset = unsafe .objectFieldOffset (Decimal .class .getDeclaredField ("decimalVal" ));
56
+ } catch (Throwable e ) {
57
+ throw new RuntimeException (e );
58
+ }
59
+ }
60
+
48
61
protected CometVector (DataType type , boolean useDecimal128 ) {
49
62
super (type );
50
63
this .useDecimal128 = useDecimal128 ;
@@ -73,31 +86,35 @@ public boolean isFixedLength() {
73
86
@ Override
74
87
public Decimal getDecimal (int i , int precision , int scale ) {
75
88
if (!useDecimal128 && precision <= Decimal .MAX_INT_DIGITS () && type instanceof IntegerType ) {
76
- return Decimal . createUnsafe (getInt (i ), precision , scale );
89
+ return createDecimal (getInt (i ), precision , scale );
77
90
} else if (!useDecimal128 && precision <= Decimal .MAX_LONG_DIGITS ()) {
78
- return Decimal . createUnsafe (getLong (i ), precision , scale );
91
+ return createDecimal (getLong (i ), precision , scale );
79
92
} else {
80
93
byte [] bytes = getBinaryDecimal (i );
81
94
BigInteger bigInteger = new BigInteger (bytes );
82
95
BigDecimal javaDecimal = new BigDecimal (bigInteger , scale );
83
- try {
84
- return Decimal .apply (javaDecimal , precision , scale );
85
- } catch (ArithmeticException e ) {
86
- throw new ArithmeticException (
87
- "Cannot convert "
88
- + javaDecimal
89
- + " (bytes: "
90
- + bytes
91
- + ", integer: "
92
- + bigInteger
93
- + ") to decimal with precision: "
94
- + precision
95
- + " and scale: "
96
- + scale );
97
- }
96
+ return createDecimal (javaDecimal , precision , scale );
98
97
}
99
98
}
100
99
100
+ /** This method skips the negative scale check, otherwise the same as Decimal.createUnsafe(). */
101
+ private Decimal createDecimal (long unscaled , int precision , int scale ) {
102
+ Decimal dec = new Decimal ();
103
+ dec .org$apache$spark$sql$types$Decimal$$longVal_$eq (unscaled );
104
+ dec .org$apache$spark$sql$types$Decimal$$_precision_$eq (precision );
105
+ dec .org$apache$spark$sql$types$Decimal$$_scale_$eq (scale );
106
+ return dec ;
107
+ }
108
+
109
+ /** This method skips a few checks, otherwise the same as Decimal.apply(). */
110
+ private Decimal createDecimal (BigDecimal value , int precision , int scale ) {
111
+ Decimal dec = new Decimal ();
112
+ Platform .putObjectVolatile (dec , decimalValOffset , new scala .math .BigDecimal (value ));
113
+ dec .org$apache$spark$sql$types$Decimal$$_precision_$eq (precision );
114
+ dec .org$apache$spark$sql$types$Decimal$$_scale_$eq (scale );
115
+ return dec ;
116
+ }
117
+
101
118
/**
102
119
* Reads a 16-byte byte array which are encoded big-endian for decimal128 into internal byte
103
120
* array.
0 commit comments