@@ -425,29 +425,54 @@ object Cast {
425425 }
426426}
427427
428- abstract class CastBase extends UnaryExpression
429- with TimeZoneAwareExpression
430- with NullIntolerant
431- with SupportQueryContext {
428+ /**
429+ * Cast the child expression to the target data type.
430+ *
431+ * When cast from/to timezone related types, we need timeZoneId, which will be resolved with
432+ * session local timezone by an analyzer [[ResolveTimeZone ]].
433+ */
434+ @ ExpressionDescription (
435+ usage = " _FUNC_(expr AS type) - Casts the value `expr` to the target data type `type`." ,
436+ examples = """
437+ Examples:
438+ > SELECT _FUNC_('10' as int);
439+ 10
440+ """ ,
441+ since = " 1.0.0" ,
442+ group = " conversion_funcs" )
443+ case class Cast (
444+ child : Expression ,
445+ dataType : DataType ,
446+ timeZoneId : Option [String ] = None ,
447+ ansiEnabled : Boolean = SQLConf .get.ansiEnabled) extends UnaryExpression
448+ with TimeZoneAwareExpression with NullIntolerant with SupportQueryContext {
432449
433- def child : Expression
450+ def this (child : Expression , dataType : DataType , timeZoneId : Option [String ]) =
451+ this (child, dataType, timeZoneId, ansiEnabled = SQLConf .get.ansiEnabled)
434452
435- def dataType : DataType
453+ override def withTimeZone (timeZoneId : String ): TimeZoneAwareExpression =
454+ copy(timeZoneId = Option (timeZoneId))
436455
437- /**
438- * Returns true iff we can cast `from` type to `to` type.
439- */
440- def canCast (from : DataType , to : DataType ): Boolean
456+ override protected def withNewChildInternal (newChild : Expression ): Cast = copy(child = newChild)
441457
442- /**
443- * Returns the error message if casting from one type to another one is invalid.
444- */
445- def typeCheckFailureMessage : String
458+ final override def nodePatternsInternal (): Seq [TreePattern ] = Seq (CAST )
446459
447- override def toString : String = s " cast( $child as ${dataType.simpleString}) "
460+ private def typeCheckFailureMessage : String = if (ansiEnabled) {
461+ if (getTagValue(Cast .BY_TABLE_INSERTION ).isDefined) {
462+ Cast .typeCheckFailureMessage(child.dataType, dataType,
463+ Some (SQLConf .STORE_ASSIGNMENT_POLICY .key -> SQLConf .StoreAssignmentPolicy .LEGACY .toString))
464+ } else {
465+ Cast .typeCheckFailureMessage(child.dataType, dataType,
466+ Some (SQLConf .ANSI_ENABLED .key -> " false" ))
467+ }
468+ } else {
469+ s " cannot cast ${child.dataType.catalogString} to ${dataType.catalogString}"
470+ }
448471
449472 override def checkInputDataTypes (): TypeCheckResult = {
450- if (canCast(child.dataType, dataType)) {
473+ if (ansiEnabled && Cast .canAnsiCast(child.dataType, dataType)) {
474+ TypeCheckResult .TypeCheckSuccess
475+ } else if (! ansiEnabled && Cast .canCast(child.dataType, dataType)) {
451476 TypeCheckResult .TypeCheckSuccess
452477 } else {
453478 TypeCheckResult .TypeCheckFailure (typeCheckFailureMessage)
@@ -456,8 +481,6 @@ abstract class CastBase extends UnaryExpression
456481
457482 override def nullable : Boolean = child.nullable || Cast .forceNullable(child.dataType, dataType)
458483
459- protected def ansiEnabled : Boolean
460-
461484 override def initQueryContext (): String = if (ansiEnabled) {
462485 origin.context
463486 } else {
@@ -470,7 +493,7 @@ abstract class CastBase extends UnaryExpression
470493 childrenResolved && checkInputDataTypes().isSuccess && (! needsTimeZone || timeZoneId.isDefined)
471494
472495 override lazy val preCanonicalized : Expression = {
473- val basic = withNewChildren(Seq (child.preCanonicalized)).asInstanceOf [CastBase ]
496+ val basic = withNewChildren(Seq (child.preCanonicalized)).asInstanceOf [Cast ]
474497 if (timeZoneId.isDefined && ! needsTimeZone) {
475498 basic.withTimeZone(null )
476499 } else {
@@ -2246,6 +2269,8 @@ abstract class CastBase extends UnaryExpression
22462269 """
22472270 }
22482271
2272+ override def toString : String = s " cast( $child as ${dataType.simpleString}) "
2273+
22492274 override def sql : String = dataType match {
22502275 // HiveQL doesn't allow casting to complex types. For logical plans translated from HiveQL, this
22512276 // type of casting can only be introduced by the analyzer, and can be omitted when converting
@@ -2255,57 +2280,6 @@ abstract class CastBase extends UnaryExpression
22552280 }
22562281}
22572282
2258- /**
2259- * Cast the child expression to the target data type.
2260- *
2261- * When cast from/to timezone related types, we need timeZoneId, which will be resolved with
2262- * session local timezone by an analyzer [[ResolveTimeZone ]].
2263- */
2264- @ ExpressionDescription (
2265- usage = " _FUNC_(expr AS type) - Casts the value `expr` to the target data type `type`." ,
2266- examples = """
2267- Examples:
2268- > SELECT _FUNC_('10' as int);
2269- 10
2270- """ ,
2271- since = " 1.0.0" ,
2272- group = " conversion_funcs" )
2273- case class Cast (
2274- child : Expression ,
2275- dataType : DataType ,
2276- timeZoneId : Option [String ] = None ,
2277- override val ansiEnabled : Boolean = SQLConf .get.ansiEnabled)
2278- extends CastBase {
2279-
2280- def this (child : Expression , dataType : DataType , timeZoneId : Option [String ]) =
2281- this (child, dataType, timeZoneId, ansiEnabled = SQLConf .get.ansiEnabled)
2282-
2283- override def withTimeZone (timeZoneId : String ): TimeZoneAwareExpression =
2284- copy(timeZoneId = Option (timeZoneId))
2285-
2286- final override def nodePatternsInternal (): Seq [TreePattern ] = Seq (CAST )
2287-
2288- override def canCast (from : DataType , to : DataType ): Boolean = if (ansiEnabled) {
2289- Cast .canAnsiCast(from, to)
2290- } else {
2291- Cast .canCast(from, to)
2292- }
2293-
2294- override def typeCheckFailureMessage : String = if (ansiEnabled) {
2295- if (getTagValue(Cast .BY_TABLE_INSERTION ).isDefined) {
2296- Cast .typeCheckFailureMessage(child.dataType, dataType,
2297- Some (SQLConf .STORE_ASSIGNMENT_POLICY .key -> SQLConf .StoreAssignmentPolicy .LEGACY .toString))
2298- } else {
2299- Cast .typeCheckFailureMessage(child.dataType, dataType,
2300- Some (SQLConf .ANSI_ENABLED .key -> " false" ))
2301- }
2302- } else {
2303- s " cannot cast ${child.dataType.catalogString} to ${dataType.catalogString}"
2304- }
2305-
2306- override protected def withNewChildInternal (newChild : Expression ): Cast = copy(child = newChild)
2307- }
2308-
23092283/**
23102284 * Cast the child expression to the target data type, but will throw error if the cast might
23112285 * truncate, e.g. long -> int, timestamp -> data.
0 commit comments