10
10
11
11
import java .sql .Date ;
12
12
import java .sql .JDBCType ;
13
- import java .sql .SQLDataException ;
14
13
import java .sql .SQLException ;
15
14
import java .sql .SQLFeatureNotSupportedException ;
16
15
import java .sql .Time ;
@@ -56,9 +55,10 @@ private TypeConverter() {
56
55
57
56
}
58
57
59
- private static final long DAY_IN_MILLIS = 60 * 60 * 24 ;
58
+ private static final long DAY_IN_MILLIS = 60 * 60 * 24 * 1000 ;
60
59
private static final Map <Class <?>, JDBCType > javaToJDBC ;
61
60
61
+
62
62
static {
63
63
Map <Class <?>, JDBCType > aMap = Arrays .stream (DataType .values ())
64
64
.filter (dataType -> dataType .javaClass () != null
@@ -120,6 +120,7 @@ private static <T> T dateTimeConvert(Long millis, Calendar c, Function<Calendar,
120
120
}
121
121
}
122
122
123
+
123
124
static long convertFromCalendarToUTC (long value , Calendar cal ) {
124
125
if (cal == null ) {
125
126
return value ;
@@ -143,11 +144,15 @@ static <T> T convert(Object val, JDBCType columnType, Class<T> type) throws SQLE
143
144
return (T ) convert (val , columnType );
144
145
}
145
146
146
- if (type .isInstance (val )) {
147
+ // converting a Long to a Timestamp shouldn't be possible according to the spec,
148
+ // it feels a little brittle to check this scenario here and I don't particularly like it
149
+ // TODO: can we do any better or should we go over the spec and allow getLong(date) to be valid?
150
+ if (!(type == Long .class && columnType == JDBCType .TIMESTAMP ) && type .isInstance (val )) {
147
151
try {
148
152
return type .cast (val );
149
153
} catch (ClassCastException cce ) {
150
- throw new SQLDataException ("Unable to convert " + val .getClass ().getName () + " to " + columnType , cce );
154
+ throw new SQLException (format (Locale .ROOT , "Unable to convert value [%.128s] of type [%s] to a %s" , val ,
155
+ columnType .getName (), type .getName ()), cce );
151
156
}
152
157
}
153
158
@@ -205,7 +210,8 @@ static <T> T convert(Object val, JDBCType columnType, Class<T> type) throws SQLE
205
210
if (type == OffsetDateTime .class ) {
206
211
return (T ) asOffsetDateTime (val , columnType );
207
212
}
208
- throw new SQLException ("Conversion from type [" + columnType + "] to [" + type .getName () + "] not supported" );
213
+ throw new SQLException (format (Locale .ROOT , "Unable to convert value [%.128s] of type [%s] to a %s" , val ,
214
+ columnType .getName (), type .getName ()));
209
215
}
210
216
211
217
/**
@@ -336,8 +342,11 @@ private static Boolean asBoolean(Object val, JDBCType columnType) throws SQLExce
336
342
case FLOAT :
337
343
case DOUBLE :
338
344
return Boolean .valueOf (Integer .signum (((Number ) val ).intValue ()) != 0 );
345
+ case VARCHAR :
346
+ return Boolean .valueOf ((String ) val );
339
347
default :
340
- throw new SQLException ("Conversion from type [" + columnType + "] to [Boolean] not supported" );
348
+ throw new SQLException (
349
+ format (Locale .ROOT , "Unable to convert value [%.128s] of type [%s] to a Boolean" , val , columnType .getName ()));
341
350
342
351
}
343
352
}
@@ -355,10 +364,16 @@ private static Byte asByte(Object val, JDBCType columnType) throws SQLException
355
364
case FLOAT :
356
365
case DOUBLE :
357
366
return safeToByte (safeToLong (((Number ) val ).doubleValue ()));
367
+ case VARCHAR :
368
+ try {
369
+ return Byte .valueOf ((String ) val );
370
+ } catch (NumberFormatException e ) {
371
+ throw new SQLException (format (Locale .ROOT , "Unable to convert value [%.128s] of type [VARCHAR] to a Byte" , val ), e );
372
+ }
358
373
default :
359
374
}
360
375
361
- throw new SQLException ("Conversion from type [" + columnType + " ] to [ Byte] not supported" );
376
+ throw new SQLException (format ( Locale . ROOT , "Unable to convert value [%.128s] of type [%s ] to a Byte" , val , columnType . getName ()) );
362
377
}
363
378
364
379
private static Short asShort (Object val , JDBCType columnType ) throws SQLException {
@@ -374,10 +389,16 @@ private static Short asShort(Object val, JDBCType columnType) throws SQLExceptio
374
389
case FLOAT :
375
390
case DOUBLE :
376
391
return safeToShort (safeToLong (((Number ) val ).doubleValue ()));
392
+ case VARCHAR :
393
+ try {
394
+ return Short .valueOf ((String ) val );
395
+ } catch (NumberFormatException e ) {
396
+ throw new SQLException (format (Locale .ROOT , "Unable to convert value [%.128s] of type [VARCHAR] to a Short" , val ), e );
397
+ }
377
398
default :
378
399
}
379
400
380
- throw new SQLException ("Conversion from type [" + columnType + " ] to [ Short] not supported" );
401
+ throw new SQLException (format ( Locale . ROOT , "Unable to convert value [%.128s] of type [%s ] to a Short" , val , columnType . getName ()) );
381
402
}
382
403
383
404
private static Integer asInteger (Object val , JDBCType columnType ) throws SQLException {
@@ -393,10 +414,18 @@ private static Integer asInteger(Object val, JDBCType columnType) throws SQLExce
393
414
case FLOAT :
394
415
case DOUBLE :
395
416
return safeToInt (safeToLong (((Number ) val ).doubleValue ()));
417
+ case VARCHAR :
418
+ try {
419
+ return Integer .valueOf ((String ) val );
420
+ } catch (NumberFormatException e ) {
421
+ throw new SQLException (
422
+ format (Locale .ROOT , "Unable to convert value [%.128s] of type [VARCHAR] to an Integer" , val ), e );
423
+ }
396
424
default :
397
425
}
398
426
399
- throw new SQLException ("Conversion from type [" + columnType + "] to [Integer] not supported" );
427
+ throw new SQLException (
428
+ format (Locale .ROOT , "Unable to convert value [%.128s] of type [%s] to an Integer" , val , columnType .getName ()));
400
429
}
401
430
402
431
private static Long asLong (Object val , JDBCType columnType ) throws SQLException {
@@ -412,12 +441,21 @@ private static Long asLong(Object val, JDBCType columnType) throws SQLException
412
441
case FLOAT :
413
442
case DOUBLE :
414
443
return safeToLong (((Number ) val ).doubleValue ());
415
- case TIMESTAMP :
416
- return ((Number ) val ).longValue ();
444
+ //TODO: should we support conversion to TIMESTAMP?
445
+ //The spec says that getLong() should support the following types conversions:
446
+ //TINYINT, SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, BOOLEAN, CHAR, VARCHAR, LONGVARCHAR
447
+ //case TIMESTAMP:
448
+ // return ((Number) val).longValue();
449
+ case VARCHAR :
450
+ try {
451
+ return Long .valueOf ((String ) val );
452
+ } catch (NumberFormatException e ) {
453
+ throw new SQLException (format (Locale .ROOT , "Unable to convert value [%.128s] of type [VARCHAR] to a Long" , val ), e );
454
+ }
417
455
default :
418
456
}
419
457
420
- throw new SQLException ("Conversion from type [" + columnType + " ] to [ Long] not supported" );
458
+ throw new SQLException (format ( Locale . ROOT , "Unable to convert value [%.128s] of type [%s ] to a Long" , val , columnType . getName ()) );
421
459
}
422
460
423
461
private static Float asFloat (Object val , JDBCType columnType ) throws SQLException {
@@ -433,10 +471,16 @@ private static Float asFloat(Object val, JDBCType columnType) throws SQLExceptio
433
471
case FLOAT :
434
472
case DOUBLE :
435
473
return Float .valueOf ((((float ) ((Number ) val ).doubleValue ())));
474
+ case VARCHAR :
475
+ try {
476
+ return Float .valueOf ((String ) val );
477
+ } catch (NumberFormatException e ) {
478
+ throw new SQLException (format (Locale .ROOT , "Unable to convert value [%.128s] of type [VARCHAR] to a Float" , val ), e );
479
+ }
436
480
default :
437
481
}
438
482
439
- throw new SQLException ("Conversion from type [" + columnType + " ] to [ Float] not supported" );
483
+ throw new SQLException (format ( Locale . ROOT , "Unable to convert value [%.128s] of type [%s ] to a Float" , val , columnType . getName ()) );
440
484
}
441
485
442
486
private static Double asDouble (Object val , JDBCType columnType ) throws SQLException {
@@ -451,32 +495,41 @@ private static Double asDouble(Object val, JDBCType columnType) throws SQLExcept
451
495
case REAL :
452
496
case FLOAT :
453
497
case DOUBLE :
498
+
454
499
return Double .valueOf (((Number ) val ).doubleValue ());
500
+ case VARCHAR :
501
+ try {
502
+ return Double .valueOf ((String ) val );
503
+ } catch (NumberFormatException e ) {
504
+ throw new SQLException (format (Locale .ROOT , "Unable to convert value [%.128s] of type [VARCHAR] to a Double" , val ), e );
505
+ }
455
506
default :
456
507
}
457
508
458
- throw new SQLException ("Conversion from type [" + columnType + "] to [Double] not supported" );
509
+ throw new SQLException (
510
+ format (Locale .ROOT , "Unable to convert value [%.128s] of type [%s] to a Double" , val , columnType .getName ()));
459
511
}
460
512
461
513
private static Date asDate (Object val , JDBCType columnType ) throws SQLException {
462
514
if (columnType == JDBCType .TIMESTAMP ) {
463
515
return new Date (utcMillisRemoveTime (((Number ) val ).longValue ()));
464
516
}
465
- throw new SQLException ("Conversion from type [" + columnType + " ] to [ Date] not supported" );
517
+ throw new SQLException (format ( Locale . ROOT , "Unable to convert value [%.128s] of type [%s ] to a Date" , val , columnType . getName ()) );
466
518
}
467
519
468
520
private static Time asTime (Object val , JDBCType columnType ) throws SQLException {
469
521
if (columnType == JDBCType .TIMESTAMP ) {
470
522
return new Time (utcMillisRemoveDate (((Number ) val ).longValue ()));
471
523
}
472
- throw new SQLException ("Conversion from type [" + columnType + " ] to [ Time] not supported" );
524
+ throw new SQLException (format ( Locale . ROOT , "Unable to convert value [%.128s] of type [%s ] to a Time" , val , columnType . getName ()) );
473
525
}
474
526
475
527
private static Timestamp asTimestamp (Object val , JDBCType columnType ) throws SQLException {
476
528
if (columnType == JDBCType .TIMESTAMP ) {
477
529
return new Timestamp (((Number ) val ).longValue ());
478
530
}
479
- throw new SQLException ("Conversion from type [" + columnType + "] to [Timestamp] not supported" );
531
+ throw new SQLException (
532
+ format (Locale .ROOT , "Unable to convert value [%.128s] of type [%s] to a Timestamp" , val , columnType .getName ()));
480
533
}
481
534
482
535
private static byte [] asByteArray (Object val , JDBCType columnType ) {
0 commit comments