Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ case class ToTime(str: Expression, format: Option[Expression])
case Some(expr) if expr.foldable =>
Option(expr.eval())
.map(f => invokeParser(Some(f.toString), Seq(str)))
.getOrElse(Literal(null, expr.dataType))
.getOrElse(Literal(null, TimeType()))
case _ => invokeParser()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@ class TimeExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
parameters = Map("input" -> "'100:50'", "format" -> "'mm:HH'"))
}

test("SPARK-58296: to_time reports TimeType even when a foldable format is NULL") {
// A foldable format that evaluates to NULL must not change the output type: to_time
// still produces a TIME, matching the non-null and no-format branches. Before the fix
// the replacement fell back to the format argument's own type (STRING/NULL).
assert(new ToTime(Literal("00:00:00"), Literal.create(null, StringType)).dataType ===
TimeType())
assert(new ToTime(Literal("00:00:00"), Literal.create(null)).dataType === TimeType())
// The value is still NULL; assert type and value together for this exact case.
checkEvaluation(new ToTime(Literal("00:00:00"), Literal.create(null, StringType)), null)
// Sanity: the branches that were already correct.
assert(new ToTime(Literal("00:00:00")).dataType === TimeType())
assert(new ToTime(Literal("00:00:00"), Literal("HH:mm:ss")).dataType === TimeType())
}

test("HourExpressionBuilder") {
// Empty expressions list
checkError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,20 @@ Project [to_time(time_str#x, Some(fmt_str#x)) AS to_time(time_str, fmt_str)#x]
+- OneRowRelation


-- !query
select typeof(to_time('00:12:00', null))
-- !query analysis
Project [typeof(to_time(00:12:00, Some(null))) AS typeof(to_time(00:12:00, NULL))#x]
+- OneRowRelation


-- !query
select typeof(to_time('00:12:00', cast(null as string)))
-- !query analysis
Project [typeof(to_time(00:12:00, Some(cast(null as string)))) AS typeof(to_time(00:12:00, CAST(NULL AS STRING)))#x]
+- OneRowRelation


-- !query
select to_time("11", "HH")
-- !query analysis
Expand Down
4 changes: 4 additions & 0 deletions sql/core/src/test/resources/sql-tests/inputs/time.sql
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ select time '16:39:45\t';
select to_time(null), to_time('01:02:03'), to_time('23-59-59.999999', 'HH-mm-ss.SSSSSS');
select to_time(time_str, fmt_str) from time_view;

-- SPARK-58296: a NULL format must not change the result type of `to_time` (stays TIME).
select typeof(to_time('00:12:00', null));
select typeof(to_time('00:12:00', cast(null as string)));

-- missing fields in `to_time`
select to_time("11", "HH");
-- invalid: there is no 13 hours
Expand Down
16 changes: 16 additions & 0 deletions sql/core/src/test/resources/sql-tests/results/time.sql.out
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@ struct<to_time(time_str, fmt_str):time(6)>
11:53:26.038344


-- !query
select typeof(to_time('00:12:00', null))
-- !query schema
struct<typeof(to_time(00:12:00, NULL)):string>
-- !query output
time(6)


-- !query
select typeof(to_time('00:12:00', cast(null as string)))
-- !query schema
struct<typeof(to_time(00:12:00, CAST(NULL AS STRING))):string>
-- !query output
time(6)


-- !query
select to_time("11", "HH")
-- !query schema
Expand Down