@@ -32,11 +32,22 @@ import org.apache.spark.sql.catalyst.util.DateTimeUtils
3232import org .apache .spark .sql .catalyst .util .TimeFormatter
3333import org .apache .spark .sql .catalyst .util .TypeUtils .ordinalNumber
3434import org .apache .spark .sql .errors .{QueryCompilationErrors , QueryExecutionErrors }
35+ import org .apache .spark .sql .internal .SQLConf
3536import org .apache .spark .sql .internal .types .StringTypeWithCollation
3637import org .apache .spark .sql .types .{AbstractDataType , AnyTimeType , ByteType , DataType , DayTimeIntervalType , DecimalType , IntegerType , IntegralType , LongType , NumericType , ObjectType , TimeType }
3738import org .apache .spark .sql .types .DayTimeIntervalType .{HOUR , SECOND }
3839import org .apache .spark .unsafe .types .UTF8String
3940
41+ trait TimeExpression extends Expression {
42+ override def checkInputDataTypes (): TypeCheckResult = {
43+ if (SQLConf .get.isTimeTypeEnabled) {
44+ super .checkInputDataTypes()
45+ } else {
46+ throw QueryCompilationErrors .unsupportedTimeTypeError()
47+ }
48+ }
49+ }
50+
4051/**
4152 * Parses a column to a time based on the given format.
4253 */
@@ -64,7 +75,7 @@ import org.apache.spark.unsafe.types.UTF8String
6475 since = " 4.1.0" )
6576// scalastyle:on line.size.limit
6677case class ToTime (str : Expression , format : Option [Expression ])
67- extends RuntimeReplaceable with ExpectsInputTypes {
78+ extends RuntimeReplaceable with ExpectsInputTypes with TimeExpression {
6879
6980 def this (str : Expression , format : Expression ) = this (str, Option (format))
7081 def this (str : Expression ) = this (str, None )
@@ -200,7 +211,7 @@ object TryToTimeExpressionBuilder extends ExpressionBuilder {
200211// scalastyle:on line.size.limit
201212case class MinutesOfTime (child : Expression )
202213 extends RuntimeReplaceable
203- with ExpectsInputTypes {
214+ with ExpectsInputTypes with TimeExpression {
204215
205216 override def replacement : Expression = StaticInvoke (
206217 classOf [DateTimeUtils .type ],
@@ -259,7 +270,7 @@ object MinuteExpressionBuilder extends ExpressionBuilder {
259270
260271case class HoursOfTime (child : Expression )
261272 extends RuntimeReplaceable
262- with ExpectsInputTypes {
273+ with ExpectsInputTypes with TimeExpression {
263274
264275 override def replacement : Expression = StaticInvoke (
265276 classOf [DateTimeUtils .type ],
@@ -316,7 +327,7 @@ object HourExpressionBuilder extends ExpressionBuilder {
316327
317328case class SecondsOfTimeWithFraction (child : Expression )
318329 extends RuntimeReplaceable
319- with ExpectsInputTypes {
330+ with ExpectsInputTypes with TimeExpression {
320331 override def replacement : Expression = {
321332 val precision = child.dataType match {
322333 case TimeType (p) => p
@@ -342,7 +353,7 @@ case class SecondsOfTimeWithFraction(child: Expression)
342353
343354case class SecondsOfTime (child : Expression )
344355 extends RuntimeReplaceable
345- with ExpectsInputTypes {
356+ with ExpectsInputTypes with TimeExpression {
346357
347358 override def replacement : Expression = StaticInvoke (
348359 classOf [DateTimeUtils .type ],
@@ -433,7 +444,8 @@ object SecondExpressionBuilder extends ExpressionBuilder {
433444case class CurrentTime (
434445 child : Expression = Literal (TimeType .MICROS_PRECISION ),
435446 timeZoneId : Option [String ] = None ) extends UnaryExpression
436- with TimeZoneAwareExpression with ImplicitCastInputTypes with CodegenFallback {
447+ with TimeZoneAwareExpression with ImplicitCastInputTypes with CodegenFallback
448+ with TimeExpression {
437449
438450 def this () = {
439451 this (Literal (TimeType .MICROS_PRECISION ), None )
@@ -545,7 +557,7 @@ case class MakeTime(
545557 secsAndMicros : Expression )
546558 extends RuntimeReplaceable
547559 with ImplicitCastInputTypes
548- with ExpectsInputTypes {
560+ with ExpectsInputTypes with TimeExpression {
549561
550562 // Accept `sec` as DecimalType to avoid loosing precision of microseconds while converting
551563 // it to the fractional part of `sec`. If `sec` is an IntegerType, it can be cast into decimal
@@ -570,7 +582,8 @@ case class MakeTime(
570582 * Adds day-time interval to time.
571583 */
572584case class TimeAddInterval (time : Expression , interval : Expression )
573- extends BinaryExpression with RuntimeReplaceable with ExpectsInputTypes {
585+ extends BinaryExpression with RuntimeReplaceable with ExpectsInputTypes
586+ with TimeExpression {
574587 override def nullIntolerant : Boolean = true
575588
576589 override def left : Expression = time
@@ -611,7 +624,8 @@ case class TimeAddInterval(time: Expression, interval: Expression)
611624 * Returns a day-time interval between time values.
612625 */
613626case class SubtractTimes (left : Expression , right : Expression )
614- extends BinaryExpression with RuntimeReplaceable with ExpectsInputTypes {
627+ extends BinaryExpression with RuntimeReplaceable with ExpectsInputTypes
628+ with TimeExpression {
615629 override def nullIntolerant : Boolean = true
616630 override def inputTypes : Seq [AbstractDataType ] = Seq (AnyTimeType , AnyTimeType )
617631
@@ -668,7 +682,8 @@ case class TimeDiff(
668682 end : Expression )
669683 extends TernaryExpression
670684 with RuntimeReplaceable
671- with ImplicitCastInputTypes {
685+ with ImplicitCastInputTypes
686+ with TimeExpression {
672687
673688 override def first : Expression = unit
674689 override def second : Expression = start
@@ -723,7 +738,8 @@ case class TimeDiff(
723738 since = " 4.1.0" )
724739// scalastyle:on line.size.limit
725740case class TimeTrunc (unit : Expression , time : Expression )
726- extends BinaryExpression with RuntimeReplaceable with ImplicitCastInputTypes {
741+ extends BinaryExpression with RuntimeReplaceable with ImplicitCastInputTypes
742+ with TimeExpression {
727743
728744 override def left : Expression = unit
729745 override def right : Expression = time
@@ -750,7 +766,8 @@ case class TimeTrunc(unit: Expression, time: Expression)
750766 }
751767}
752768
753- abstract class TimeFromBase extends UnaryExpression with RuntimeReplaceable with ExpectsInputTypes {
769+ abstract class TimeFromBase extends UnaryExpression with RuntimeReplaceable with ExpectsInputTypes
770+ with TimeExpression {
754771 protected def timeConversionMethod : String
755772
756773 override def inputTypes : Seq [AbstractDataType ] = Seq (IntegralType )
@@ -854,7 +871,8 @@ case class TimeFromMicros(child: Expression) extends TimeFromBase {
854871 copy(child = newChild)
855872}
856873
857- abstract class TimeToBase extends UnaryExpression with RuntimeReplaceable with ExpectsInputTypes {
874+ abstract class TimeToBase extends UnaryExpression with RuntimeReplaceable with ExpectsInputTypes
875+ with TimeExpression {
858876 protected def timeConversionMethod : String
859877
860878 override def inputTypes : Seq [AbstractDataType ] = Seq (AnyTimeType )
@@ -891,8 +909,7 @@ abstract class TimeToBase extends UnaryExpression with RuntimeReplaceable with E
891909 since = " 4.2.0" ,
892910 group = " datetime_funcs" )
893911// scalastyle:on line.size.limit
894- case class TimeToSeconds (child : Expression )
895- extends TimeToBase with ImplicitCastInputTypes {
912+ case class TimeToSeconds (child : Expression ) extends TimeToBase {
896913
897914 override def dataType : DataType = DecimalType (14 , 6 )
898915 override def prettyName : String = " time_to_seconds"
0 commit comments