Skip to content

Commit fd5e76e

Browse files
committed
Adds type coersion rule
1 parent 4239bef commit fd5e76e

File tree

7 files changed

+43
-94
lines changed

7 files changed

+43
-94
lines changed

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,6 @@ class Analyzer(override val catalogManager: CatalogManager) extends RuleExecutor
483483
ResolveWithCTE,
484484
ExtractDistributedSequenceID) ++
485485
Seq(ResolveUpdateEventTimeWatermarkColumn) ++
486-
Seq(RewriteTimeCastToTimestampNTZ) ++
487486
extendedResolutionRules : _*),
488487
Batch("Remove TempResolvedColumn", Once, RemoveTempResolvedColumn),
489488
Batch("Post-Hoc Resolution", Once,

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/AnsiTypeCoercion.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ object AnsiTypeCoercion extends TypeCoercionBase {
9393
StackCoercion ::
9494
Division ::
9595
IntegralDivision ::
96+
RewriteTimeCastToTimestampNTZ ::
9697
ImplicitTypeCasts ::
9798
DateTimeOperations ::
9899
WindowFrameCoercion ::

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/RewriteTimeCastToTimestampNTZ.scala

Lines changed: 0 additions & 54 deletions
This file was deleted.

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/TypeCoercion.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ object TypeCoercion extends TypeCoercionBase {
6666
StackCoercion ::
6767
Division ::
6868
IntegralDivision ::
69+
RewriteTimeCastToTimestampNTZ ::
6970
ImplicitTypeCasts ::
7071
DateTimeOperations ::
7172
WindowFrameCoercion ::

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/TypeCoercionBase.scala

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ import org.apache.spark.sql.catalyst.expressions.{
2525
CaseWhen,
2626
Cast,
2727
Concat,
28+
CurrentDate,
2829
Elt,
2930
Expression,
31+
MakeTimestampNTZ,
3032
MapZipWith,
3133
Stack,
3234
WindowSpecDefinition
@@ -51,7 +53,7 @@ import org.apache.spark.sql.catalyst.util.ResolveDefaultColumns
5153
import org.apache.spark.sql.connector.catalog.CatalogV2Implicits.MultipartIdentifierHelper
5254
import org.apache.spark.sql.connector.catalog.procedures.BoundProcedure
5355
import org.apache.spark.sql.errors.DataTypeErrors.cannotMergeIncompatibleDataTypesError
54-
import org.apache.spark.sql.types.DataType
56+
import org.apache.spark.sql.types.{DataType, TimestampNTZType, TimeType}
5557

5658
abstract class TypeCoercionBase extends TypeCoercionHelper {
5759

@@ -480,4 +482,35 @@ abstract class TypeCoercionBase extends TypeCoercionHelper {
480482
case withChildrenResolved => StringLiteralTypeCoercion(withChildrenResolved)
481483
}
482484
}
485+
486+
/**
487+
* Rewrites a cast from [[TimeType]] to [[TimestampNTZType]] into a [[MakeTimestampNTZ]]
488+
* expression.
489+
*
490+
* The conversion from TIME to TIMESTAMP_NTZ requires a date component, which TIME itself does
491+
* not provide. This rule injects [[CurrentDate]] as the implicit date part, effectively
492+
* treating the TIME value as a time of day on the current date. This rewrite ensures that all
493+
* such casts within a query use a consistent date, as required by the [[ComputeCurrentTime]]
494+
* rule which replaces [[CurrentDate]] with a fixed value during analysis.
495+
*
496+
* For example, the following SQL:
497+
* {{{
498+
* SELECT CAST(make_time(12, 30, 0) AS TIMESTAMP_NTZ)
499+
* }}}
500+
* will be rewritten to:
501+
* {{{
502+
* SELECT make_timestamp_ntz(current_date, make_time(12, 30, 0))
503+
* }}}
504+
*/
505+
object RewriteTimeCastToTimestampNTZ extends TypeCoercionRule {
506+
override def transform: PartialFunction[Expression, Expression] = {
507+
case c @ Cast(child, TimestampNTZType, _, _) if child.resolved =>
508+
child.dataType match {
509+
case _: TimeType =>
510+
// Convert TIME -> TIMESTAMP_NTZ using MakeTimestampNTZ(CurrentDate(), time)
511+
MakeTimestampNTZ(CurrentDate(), child)
512+
case _ => c
513+
}
514+
}
515+
}
483516
}

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/RewriteTimeCastToTimestampNTZSuite.scala

Lines changed: 0 additions & 38 deletions
This file was deleted.

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/TypeCoercionSuite.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,6 +1772,13 @@ class TypeCoercionSuite extends TypeCoercionSuiteBase {
17721772
assert(wp1.isInstanceOf[Project])
17731773
assert(wp1.expressions.forall(!_.exists(_ == t1.output.head)))
17741774
}
1775+
1776+
test("SPARK-52617: RewriteTimeCastToTimestampNTZ: TIME to TIMESTAMP_NTZ coercion") {
1777+
val expr = Cast(Literal.create(123456789L, TimeType(6)), TimestampNTZType)
1778+
val coerced = RewriteTimeCastToTimestampNTZ.transform.apply(expr)
1779+
val expected = MakeTimestampNTZ(CurrentDate(), Literal.create(123456789L, TimeType(6)))
1780+
assert(coerced.semanticEquals(expected))
1781+
}
17751782
}
17761783

17771784

0 commit comments

Comments
 (0)