1919import com .google .cloud .spanner .Type ;
2020import com .google .cloud .spanner .Type .Code ;
2121import com .google .common .base .Preconditions ;
22+ import java .math .BigDecimal ;
23+ import java .math .BigInteger ;
2224import java .sql .Date ;
2325import java .sql .SQLException ;
2426import java .sql .SQLFeatureNotSupportedException ;
@@ -44,6 +46,7 @@ static int extractColumnType(Type type) {
4446 if (type .equals (Type .date ())) return Types .DATE ;
4547 if (type .equals (Type .float64 ())) return Types .DOUBLE ;
4648 if (type .equals (Type .int64 ())) return Types .BIGINT ;
49+ if (type .equals (Type .numeric ())) return Types .NUMERIC ;
4750 if (type .equals (Type .string ())) return Types .NVARCHAR ;
4851 if (type .equals (Type .timestamp ())) return Types .TIMESTAMP ;
4952 if (type .getCode () == Code .ARRAY ) return Types .ARRAY ;
@@ -60,6 +63,8 @@ static String getSpannerTypeName(int sqlType) {
6063 || sqlType == Types .INTEGER
6164 || sqlType == Types .SMALLINT
6265 || sqlType == Types .TINYINT ) return Type .int64 ().getCode ().name ();
66+ if (sqlType == Types .NUMERIC || sqlType == Types .DECIMAL )
67+ return Type .numeric ().getCode ().name ();
6368 if (sqlType == Types .NVARCHAR ) return Type .string ().getCode ().name ();
6469 if (sqlType == Types .TIMESTAMP ) return Type .timestamp ().getCode ().name ();
6570 if (sqlType == Types .ARRAY ) return Code .ARRAY .name ();
@@ -77,6 +82,7 @@ static String getClassName(int sqlType) {
7782 || sqlType == Types .INTEGER
7883 || sqlType == Types .SMALLINT
7984 || sqlType == Types .TINYINT ) return Long .class .getName ();
85+ if (sqlType == Types .NUMERIC || sqlType == Types .DECIMAL ) return BigDecimal .class .getName ();
8086 if (sqlType == Types .NVARCHAR ) return String .class .getName ();
8187 if (sqlType == Types .TIMESTAMP ) return Timestamp .class .getName ();
8288 if (sqlType == Types .ARRAY ) return Object .class .getName ();
@@ -96,6 +102,7 @@ static String getClassName(Type type) {
96102 if (type == Type .date ()) return Date .class .getName ();
97103 if (type == Type .float64 ()) return Double .class .getName ();
98104 if (type == Type .int64 ()) return Long .class .getName ();
105+ if (type == Type .numeric ()) return BigDecimal .class .getName ();
99106 if (type == Type .string ()) return String .class .getName ();
100107 if (type == Type .timestamp ()) return Timestamp .class .getName ();
101108 if (type .getCode () == Code .ARRAY ) {
@@ -104,6 +111,7 @@ static String getClassName(Type type) {
104111 if (type .getArrayElementType () == Type .date ()) return Date [].class .getName ();
105112 if (type .getArrayElementType () == Type .float64 ()) return Double [].class .getName ();
106113 if (type .getArrayElementType () == Type .int64 ()) return Long [].class .getName ();
114+ if (type .getArrayElementType () == Type .numeric ()) return BigDecimal [].class .getName ();
107115 if (type .getArrayElementType () == Type .string ()) return String [].class .getName ();
108116 if (type .getArrayElementType () == Type .timestamp ()) return Timestamp [].class .getName ();
109117 }
@@ -122,6 +130,16 @@ static byte checkedCastToByte(long val) throws SQLException {
122130 return (byte ) val ;
123131 }
124132
133+ /** Cast value and throw {@link SQLException} if out-of-range. */
134+ static byte checkedCastToByte (BigDecimal val ) throws SQLException {
135+ try {
136+ return val .byteValueExact ();
137+ } catch (ArithmeticException e ) {
138+ throw JdbcSqlExceptionFactory .of (
139+ String .format (OUT_OF_RANGE_MSG , "byte" , val ), com .google .rpc .Code .OUT_OF_RANGE );
140+ }
141+ }
142+
125143 /** Cast value and throw {@link SQLException} if out-of-range. */
126144 static short checkedCastToShort (long val ) throws SQLException {
127145 if (val > Short .MAX_VALUE || val < Short .MIN_VALUE ) {
@@ -131,6 +149,16 @@ static short checkedCastToShort(long val) throws SQLException {
131149 return (short ) val ;
132150 }
133151
152+ /** Cast value and throw {@link SQLException} if out-of-range. */
153+ static short checkedCastToShort (BigDecimal val ) throws SQLException {
154+ try {
155+ return val .shortValueExact ();
156+ } catch (ArithmeticException e ) {
157+ throw JdbcSqlExceptionFactory .of (
158+ String .format (OUT_OF_RANGE_MSG , "short" , val ), com .google .rpc .Code .OUT_OF_RANGE );
159+ }
160+ }
161+
134162 /** Cast value and throw {@link SQLException} if out-of-range. */
135163 static int checkedCastToInt (long val ) throws SQLException {
136164 if (val > Integer .MAX_VALUE || val < Integer .MIN_VALUE ) {
@@ -140,6 +168,16 @@ static int checkedCastToInt(long val) throws SQLException {
140168 return (int ) val ;
141169 }
142170
171+ /** Cast value and throw {@link SQLException} if out-of-range. */
172+ static int checkedCastToInt (BigDecimal val ) throws SQLException {
173+ try {
174+ return val .intValueExact ();
175+ } catch (ArithmeticException e ) {
176+ throw JdbcSqlExceptionFactory .of (
177+ String .format (OUT_OF_RANGE_MSG , "int" , val ), com .google .rpc .Code .OUT_OF_RANGE );
178+ }
179+ }
180+
143181 /** Cast value and throw {@link SQLException} if out-of-range. */
144182 static float checkedCastToFloat (double val ) throws SQLException {
145183 if (val > Float .MAX_VALUE || val < -Float .MAX_VALUE ) {
@@ -163,6 +201,26 @@ static long parseLong(String val) throws SQLException {
163201 }
164202 }
165203
204+ /** Cast value and throw {@link SQLException} if out-of-range. */
205+ static BigInteger checkedCastToBigInteger (BigDecimal val ) throws SQLException {
206+ try {
207+ return val .toBigIntegerExact ();
208+ } catch (ArithmeticException e ) {
209+ throw JdbcSqlExceptionFactory .of (
210+ String .format (OUT_OF_RANGE_MSG , "BigInteger" , val ), com .google .rpc .Code .OUT_OF_RANGE );
211+ }
212+ }
213+
214+ /** Cast value and throw {@link SQLException} if out-of-range. */
215+ static long checkedCastToLong (BigDecimal val ) throws SQLException {
216+ try {
217+ return val .longValueExact ();
218+ } catch (ArithmeticException e ) {
219+ throw JdbcSqlExceptionFactory .of (
220+ String .format (OUT_OF_RANGE_MSG , "long" , val ), com .google .rpc .Code .OUT_OF_RANGE );
221+ }
222+ }
223+
166224 /**
167225 * Parses the given string value as a double. Throws {@link SQLException} if the string is not a
168226 * valid double value.
0 commit comments