@@ -59,7 +59,7 @@ object Cast {
59
59
case (StringType , TimestampType ) => true
60
60
case (BooleanType , TimestampType ) => true
61
61
case (DateType , TimestampType ) => true
62
- case (_ : NumericType , TimestampType ) => true
62
+ case (_ : FractionalType , TimestampType ) => true
63
63
64
64
case (StringType , DateType ) => true
65
65
case (TimestampType , DateType ) => true
@@ -138,10 +138,8 @@ object Cast {
138
138
case (_ : CalendarIntervalType , StringType ) => true
139
139
case (NullType , _) => true
140
140
141
- // Spark supports casting between long and timestamp, please see `longToTimestamp` and
142
- // `timestampToLong` for details.
141
+ // spark forbid casting from integral to timestamp, more details in [SPARK-31790]
143
142
case (TimestampType , LongType ) => true
144
- case (LongType , TimestampType ) => true
145
143
146
144
case (ArrayType (fromType, fn), ArrayType (toType, tn)) =>
147
145
resolvableNullability(fn, tn) && canUpCast(fromType, toType)
@@ -266,7 +264,12 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit
266
264
TypeCheckResult .TypeCheckSuccess
267
265
} else {
268
266
TypeCheckResult .TypeCheckFailure (
269
- s " cannot cast ${child.dataType.catalogString} to ${dataType.catalogString}" )
267
+ if (child.dataType.isInstanceOf [IntegralType ] && dataType.isInstanceOf [TimestampType ]) {
268
+ s " cannot cast ${child.dataType.catalogString} to ${dataType.catalogString}, " +
269
+ s " please use function TIMESTAMP_SECONDS/TIMESTAMP_MILLIS/TIMESTAMP_MICROS instand "
270
+ } else {
271
+ s " cannot cast ${child.dataType.catalogString} to ${dataType.catalogString}"
272
+ })
270
273
}
271
274
}
272
275
@@ -425,14 +428,6 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit
425
428
buildCast[UTF8String ](_, utfs => DateTimeUtils .stringToTimestamp(utfs, zoneId).orNull)
426
429
case BooleanType =>
427
430
buildCast[Boolean ](_, b => if (b) 1L else 0 )
428
- case LongType =>
429
- buildCast[Long ](_, l => longToTimestamp(l))
430
- case IntegerType =>
431
- buildCast[Int ](_, i => longToTimestamp(i.toLong))
432
- case ShortType =>
433
- buildCast[Short ](_, s => longToTimestamp(s.toLong))
434
- case ByteType =>
435
- buildCast[Byte ](_, b => longToTimestamp(b.toLong))
436
431
case DateType =>
437
432
buildCast[Int ](_, d => epochDaysToMicros(d, zoneId))
438
433
// TimestampWritable.decimalToTimestamp
@@ -453,8 +448,6 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit
453
448
if (d.isNaN || d.isInfinite) null else (d * MICROS_PER_SECOND ).toLong
454
449
}
455
450
456
- // converting seconds to us
457
- private [this ] def longToTimestamp (t : Long ): Long = SECONDS .toMicros(t)
458
451
// converting us to seconds
459
452
private [this ] def timestampToLong (ts : Long ): Long = {
460
453
Math .floorDiv(ts, MICROS_PER_SECOND )
@@ -1229,8 +1222,6 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit
1229
1222
"""
1230
1223
case BooleanType =>
1231
1224
(c, evPrim, evNull) => code " $evPrim = $c ? 1L : 0L; "
1232
- case _ : IntegralType =>
1233
- (c, evPrim, evNull) => code " $evPrim = ${longToTimeStampCode(c)}; "
1234
1225
case DateType =>
1235
1226
val zoneIdClass = classOf [ZoneId ]
1236
1227
val zid = JavaCode .global(
@@ -1277,7 +1268,6 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit
1277
1268
val block = inline " new java.math.BigDecimal( $MICROS_PER_SECOND) "
1278
1269
code " ( $d.toBigDecimal().bigDecimal().multiply( $block)).longValue() "
1279
1270
}
1280
- private [this ] def longToTimeStampCode (l : ExprValue ): Block = code " $l * (long) $MICROS_PER_SECOND"
1281
1271
private [this ] def timestampToLongCode (ts : ExprValue ): Block =
1282
1272
code " java.lang.Math.floorDiv( $ts, $MICROS_PER_SECOND) "
1283
1273
private [this ] def timestampToDoubleCode (ts : ExprValue ): Block =
0 commit comments